17639a06cSTakashi Iwai /* 27639a06cSTakashi Iwai * HD-audio codec core device 37639a06cSTakashi Iwai */ 47639a06cSTakashi Iwai 57639a06cSTakashi Iwai #include <linux/init.h> 67639a06cSTakashi Iwai #include <linux/device.h> 77639a06cSTakashi Iwai #include <linux/slab.h> 87639a06cSTakashi Iwai #include <linux/module.h> 97639a06cSTakashi Iwai #include <linux/export.h> 107639a06cSTakashi Iwai #include <linux/pm_runtime.h> 117639a06cSTakashi Iwai #include <sound/hdaudio.h> 1201ed3c06STakashi Iwai #include <sound/hda_regmap.h> 13b7d023e1STakashi Iwai #include <sound/pcm.h> 147639a06cSTakashi Iwai #include "local.h" 157639a06cSTakashi Iwai 167639a06cSTakashi Iwai static void setup_fg_nodes(struct hdac_device *codec); 177639a06cSTakashi Iwai static int get_codec_vendor_name(struct hdac_device *codec); 187639a06cSTakashi Iwai 197639a06cSTakashi Iwai static void default_release(struct device *dev) 207639a06cSTakashi Iwai { 217639a06cSTakashi Iwai snd_hdac_device_exit(container_of(dev, struct hdac_device, dev)); 227639a06cSTakashi Iwai } 237639a06cSTakashi Iwai 247639a06cSTakashi Iwai /** 257639a06cSTakashi Iwai * snd_hdac_device_init - initialize the HD-audio codec base device 267639a06cSTakashi Iwai * @codec: device to initialize 277639a06cSTakashi Iwai * @bus: but to attach 287639a06cSTakashi Iwai * @name: device name string 297639a06cSTakashi Iwai * @addr: codec address 307639a06cSTakashi Iwai * 317639a06cSTakashi Iwai * Returns zero for success or a negative error code. 327639a06cSTakashi Iwai * 337639a06cSTakashi Iwai * This function increments the runtime PM counter and marks it active. 347639a06cSTakashi Iwai * The caller needs to turn it off appropriately later. 357639a06cSTakashi Iwai * 367639a06cSTakashi Iwai * The caller needs to set the device's release op properly by itself. 377639a06cSTakashi Iwai */ 387639a06cSTakashi Iwai int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus, 397639a06cSTakashi Iwai const char *name, unsigned int addr) 407639a06cSTakashi Iwai { 417639a06cSTakashi Iwai struct device *dev; 427639a06cSTakashi Iwai hda_nid_t fg; 437639a06cSTakashi Iwai int err; 447639a06cSTakashi Iwai 457639a06cSTakashi Iwai dev = &codec->dev; 467639a06cSTakashi Iwai device_initialize(dev); 477639a06cSTakashi Iwai dev->parent = bus->dev; 487639a06cSTakashi Iwai dev->bus = &snd_hda_bus_type; 497639a06cSTakashi Iwai dev->release = default_release; 503256be65STakashi Iwai dev->groups = hdac_dev_attr_groups; 517639a06cSTakashi Iwai dev_set_name(dev, "%s", name); 527639a06cSTakashi Iwai device_enable_async_suspend(dev); 537639a06cSTakashi Iwai 547639a06cSTakashi Iwai codec->bus = bus; 557639a06cSTakashi Iwai codec->addr = addr; 567639a06cSTakashi Iwai codec->type = HDA_DEV_CORE; 577639a06cSTakashi Iwai pm_runtime_set_active(&codec->dev); 587639a06cSTakashi Iwai pm_runtime_get_noresume(&codec->dev); 597639a06cSTakashi Iwai atomic_set(&codec->in_pm, 0); 607639a06cSTakashi Iwai 617639a06cSTakashi Iwai err = snd_hdac_bus_add_device(bus, codec); 627639a06cSTakashi Iwai if (err < 0) 637639a06cSTakashi Iwai goto error; 647639a06cSTakashi Iwai 657639a06cSTakashi Iwai /* fill parameters */ 667639a06cSTakashi Iwai codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 677639a06cSTakashi Iwai AC_PAR_VENDOR_ID); 687639a06cSTakashi Iwai if (codec->vendor_id == -1) { 697639a06cSTakashi Iwai /* read again, hopefully the access method was corrected 707639a06cSTakashi Iwai * in the last read... 717639a06cSTakashi Iwai */ 727639a06cSTakashi Iwai codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 737639a06cSTakashi Iwai AC_PAR_VENDOR_ID); 747639a06cSTakashi Iwai } 757639a06cSTakashi Iwai 767639a06cSTakashi Iwai codec->subsystem_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 777639a06cSTakashi Iwai AC_PAR_SUBSYSTEM_ID); 787639a06cSTakashi Iwai codec->revision_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 797639a06cSTakashi Iwai AC_PAR_REV_ID); 807639a06cSTakashi Iwai 817639a06cSTakashi Iwai setup_fg_nodes(codec); 827639a06cSTakashi Iwai if (!codec->afg && !codec->mfg) { 837639a06cSTakashi Iwai dev_err(dev, "no AFG or MFG node found\n"); 847639a06cSTakashi Iwai err = -ENODEV; 857639a06cSTakashi Iwai goto error; 867639a06cSTakashi Iwai } 877639a06cSTakashi Iwai 887639a06cSTakashi Iwai fg = codec->afg ? codec->afg : codec->mfg; 897639a06cSTakashi Iwai 907639a06cSTakashi Iwai err = snd_hdac_refresh_widgets(codec); 917639a06cSTakashi Iwai if (err < 0) 927639a06cSTakashi Iwai goto error; 937639a06cSTakashi Iwai 947639a06cSTakashi Iwai codec->power_caps = snd_hdac_read_parm(codec, fg, AC_PAR_POWER_STATE); 957639a06cSTakashi Iwai /* reread ssid if not set by parameter */ 96ffda568eSDavid Henningsson if (codec->subsystem_id == -1 || codec->subsystem_id == 0) 977639a06cSTakashi Iwai snd_hdac_read(codec, fg, AC_VERB_GET_SUBSYSTEM_ID, 0, 987639a06cSTakashi Iwai &codec->subsystem_id); 997639a06cSTakashi Iwai 1007639a06cSTakashi Iwai err = get_codec_vendor_name(codec); 1017639a06cSTakashi Iwai if (err < 0) 1027639a06cSTakashi Iwai goto error; 1037639a06cSTakashi Iwai 1047639a06cSTakashi Iwai codec->chip_name = kasprintf(GFP_KERNEL, "ID %x", 1057639a06cSTakashi Iwai codec->vendor_id & 0xffff); 1067639a06cSTakashi Iwai if (!codec->chip_name) { 1077639a06cSTakashi Iwai err = -ENOMEM; 1087639a06cSTakashi Iwai goto error; 1097639a06cSTakashi Iwai } 1107639a06cSTakashi Iwai 1117639a06cSTakashi Iwai return 0; 1127639a06cSTakashi Iwai 1137639a06cSTakashi Iwai error: 1147639a06cSTakashi Iwai put_device(&codec->dev); 1157639a06cSTakashi Iwai return err; 1167639a06cSTakashi Iwai } 1177639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_init); 1187639a06cSTakashi Iwai 1197639a06cSTakashi Iwai /** 1207639a06cSTakashi Iwai * snd_hdac_device_exit - clean up the HD-audio codec base device 1217639a06cSTakashi Iwai * @codec: device to clean up 1227639a06cSTakashi Iwai */ 1237639a06cSTakashi Iwai void snd_hdac_device_exit(struct hdac_device *codec) 1247639a06cSTakashi Iwai { 125c4c2533fSTakashi Iwai pm_runtime_put_noidle(&codec->dev); 1267639a06cSTakashi Iwai snd_hdac_bus_remove_device(codec->bus, codec); 1277639a06cSTakashi Iwai kfree(codec->vendor_name); 1287639a06cSTakashi Iwai kfree(codec->chip_name); 1297639a06cSTakashi Iwai } 1307639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_exit); 1317639a06cSTakashi Iwai 1327639a06cSTakashi Iwai /** 1333256be65STakashi Iwai * snd_hdac_device_register - register the hd-audio codec base device 1343256be65STakashi Iwai * codec: the device to register 1353256be65STakashi Iwai */ 1363256be65STakashi Iwai int snd_hdac_device_register(struct hdac_device *codec) 1373256be65STakashi Iwai { 1383256be65STakashi Iwai int err; 1393256be65STakashi Iwai 1403256be65STakashi Iwai err = device_add(&codec->dev); 1413256be65STakashi Iwai if (err < 0) 1423256be65STakashi Iwai return err; 1433256be65STakashi Iwai err = hda_widget_sysfs_init(codec); 1443256be65STakashi Iwai if (err < 0) { 1453256be65STakashi Iwai device_del(&codec->dev); 1463256be65STakashi Iwai return err; 1473256be65STakashi Iwai } 1483256be65STakashi Iwai 1493256be65STakashi Iwai return 0; 1503256be65STakashi Iwai } 1513256be65STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_register); 1523256be65STakashi Iwai 1533256be65STakashi Iwai /** 1543256be65STakashi Iwai * snd_hdac_device_unregister - unregister the hd-audio codec base device 1553256be65STakashi Iwai * codec: the device to unregister 1563256be65STakashi Iwai */ 1573256be65STakashi Iwai void snd_hdac_device_unregister(struct hdac_device *codec) 1583256be65STakashi Iwai { 1593256be65STakashi Iwai if (device_is_registered(&codec->dev)) { 1603256be65STakashi Iwai hda_widget_sysfs_exit(codec); 1613256be65STakashi Iwai device_del(&codec->dev); 1623256be65STakashi Iwai } 1633256be65STakashi Iwai } 1643256be65STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_unregister); 1653256be65STakashi Iwai 1663256be65STakashi Iwai /** 167ded255beSTakashi Iwai * snd_hdac_device_set_chip_name - set/update the codec name 168ded255beSTakashi Iwai * @codec: the HDAC device 169ded255beSTakashi Iwai * @name: name string to set 170ded255beSTakashi Iwai * 171ded255beSTakashi Iwai * Returns 0 if the name is set or updated, or a negative error code. 172ded255beSTakashi Iwai */ 173ded255beSTakashi Iwai int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name) 174ded255beSTakashi Iwai { 175ded255beSTakashi Iwai char *newname; 176ded255beSTakashi Iwai 177ded255beSTakashi Iwai if (!name) 178ded255beSTakashi Iwai return 0; 179ded255beSTakashi Iwai newname = kstrdup(name, GFP_KERNEL); 180ded255beSTakashi Iwai if (!newname) 181ded255beSTakashi Iwai return -ENOMEM; 182ded255beSTakashi Iwai kfree(codec->chip_name); 183ded255beSTakashi Iwai codec->chip_name = newname; 184ded255beSTakashi Iwai return 0; 185ded255beSTakashi Iwai } 186ded255beSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_set_chip_name); 187ded255beSTakashi Iwai 188ded255beSTakashi Iwai /** 1894f9e0c38STakashi Iwai * snd_hdac_codec_modalias - give the module alias name 1904f9e0c38STakashi Iwai * @codec: HDAC device 1914f9e0c38STakashi Iwai * @buf: string buffer to store 1924f9e0c38STakashi Iwai * @size: string buffer size 1934f9e0c38STakashi Iwai * 1944f9e0c38STakashi Iwai * Returns the size of string, like snprintf(), or a negative error code. 1954f9e0c38STakashi Iwai */ 1964f9e0c38STakashi Iwai int snd_hdac_codec_modalias(struct hdac_device *codec, char *buf, size_t size) 1974f9e0c38STakashi Iwai { 1984f9e0c38STakashi Iwai return snprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n", 1994f9e0c38STakashi Iwai codec->vendor_id, codec->revision_id, codec->type); 2004f9e0c38STakashi Iwai } 2014f9e0c38STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_codec_modalias); 2024f9e0c38STakashi Iwai 2034f9e0c38STakashi Iwai /** 2047639a06cSTakashi Iwai * snd_hdac_make_cmd - compose a 32bit command word to be sent to the 2057639a06cSTakashi Iwai * HD-audio controller 2067639a06cSTakashi Iwai * @codec: the codec object 2077639a06cSTakashi Iwai * @nid: NID to encode 2087639a06cSTakashi Iwai * @verb: verb to encode 2097639a06cSTakashi Iwai * @parm: parameter to encode 2107639a06cSTakashi Iwai * 2117639a06cSTakashi Iwai * Return an encoded command verb or -1 for error. 2127639a06cSTakashi Iwai */ 2137639a06cSTakashi Iwai unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, 2147639a06cSTakashi Iwai unsigned int verb, unsigned int parm) 2157639a06cSTakashi Iwai { 2167639a06cSTakashi Iwai u32 val, addr; 2177639a06cSTakashi Iwai 2187639a06cSTakashi Iwai addr = codec->addr; 2197639a06cSTakashi Iwai if ((addr & ~0xf) || (nid & ~0x7f) || 2207639a06cSTakashi Iwai (verb & ~0xfff) || (parm & ~0xffff)) { 2217639a06cSTakashi Iwai dev_err(&codec->dev, "out of range cmd %x:%x:%x:%x\n", 2227639a06cSTakashi Iwai addr, nid, verb, parm); 2237639a06cSTakashi Iwai return -1; 2247639a06cSTakashi Iwai } 2257639a06cSTakashi Iwai 2267639a06cSTakashi Iwai val = addr << 28; 2277639a06cSTakashi Iwai val |= (u32)nid << 20; 2287639a06cSTakashi Iwai val |= verb << 8; 2297639a06cSTakashi Iwai val |= parm; 2307639a06cSTakashi Iwai return val; 2317639a06cSTakashi Iwai } 2327639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_make_cmd); 2337639a06cSTakashi Iwai 2347639a06cSTakashi Iwai /** 23505852448STakashi Iwai * snd_hdac_exec_verb - execute an encoded verb 23605852448STakashi Iwai * @codec: the codec object 23705852448STakashi Iwai * @cmd: encoded verb to execute 23805852448STakashi Iwai * @flags: optional flags, pass zero for default 23905852448STakashi Iwai * @res: the pointer to store the result, NULL if running async 24005852448STakashi Iwai * 24105852448STakashi Iwai * Returns zero if successful, or a negative error code. 24205852448STakashi Iwai * 24305852448STakashi Iwai * This calls the exec_verb op when set in hdac_codec. If not, 24405852448STakashi Iwai * call the default snd_hdac_bus_exec_verb(). 24505852448STakashi Iwai */ 24605852448STakashi Iwai int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, 24705852448STakashi Iwai unsigned int flags, unsigned int *res) 24805852448STakashi Iwai { 24905852448STakashi Iwai if (codec->exec_verb) 25005852448STakashi Iwai return codec->exec_verb(codec, cmd, flags, res); 25105852448STakashi Iwai return snd_hdac_bus_exec_verb(codec->bus, codec->addr, cmd, res); 25205852448STakashi Iwai } 25305852448STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_exec_verb); 25405852448STakashi Iwai 25505852448STakashi Iwai 25605852448STakashi Iwai /** 2577639a06cSTakashi Iwai * snd_hdac_read - execute a verb 2587639a06cSTakashi Iwai * @codec: the codec object 2597639a06cSTakashi Iwai * @nid: NID to execute a verb 2607639a06cSTakashi Iwai * @verb: verb to execute 2617639a06cSTakashi Iwai * @parm: parameter for a verb 2627639a06cSTakashi Iwai * @res: the pointer to store the result, NULL if running async 2637639a06cSTakashi Iwai * 2647639a06cSTakashi Iwai * Returns zero if successful, or a negative error code. 2657639a06cSTakashi Iwai */ 2667639a06cSTakashi Iwai int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, 2677639a06cSTakashi Iwai unsigned int verb, unsigned int parm, unsigned int *res) 2687639a06cSTakashi Iwai { 2697639a06cSTakashi Iwai unsigned int cmd = snd_hdac_make_cmd(codec, nid, verb, parm); 2707639a06cSTakashi Iwai 27105852448STakashi Iwai return snd_hdac_exec_verb(codec, cmd, 0, res); 2727639a06cSTakashi Iwai } 2737639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_read); 2747639a06cSTakashi Iwai 2757639a06cSTakashi Iwai /** 27601ed3c06STakashi Iwai * _snd_hdac_read_parm - read a parmeter 2777639a06cSTakashi Iwai * 27801ed3c06STakashi Iwai * This function returns zero or an error unlike snd_hdac_read_parm(). 2797639a06cSTakashi Iwai */ 28001ed3c06STakashi Iwai int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm, 28101ed3c06STakashi Iwai unsigned int *res) 2827639a06cSTakashi Iwai { 28301ed3c06STakashi Iwai unsigned int cmd; 2847639a06cSTakashi Iwai 28501ed3c06STakashi Iwai cmd = snd_hdac_regmap_encode_verb(nid, AC_VERB_PARAMETERS) | parm; 28601ed3c06STakashi Iwai return snd_hdac_regmap_read_raw(codec, cmd, res); 2877639a06cSTakashi Iwai } 28801ed3c06STakashi Iwai EXPORT_SYMBOL_GPL(_snd_hdac_read_parm); 2897639a06cSTakashi Iwai 2907639a06cSTakashi Iwai /** 2919ba17b4dSTakashi Iwai * snd_hdac_read_parm_uncached - read a codec parameter without caching 2927639a06cSTakashi Iwai * @codec: the codec object 2937639a06cSTakashi Iwai * @nid: NID to read a parameter 2947639a06cSTakashi Iwai * @parm: parameter to read 2957639a06cSTakashi Iwai * 2967639a06cSTakashi Iwai * Returns -1 for error. If you need to distinguish the error more 2977639a06cSTakashi Iwai * strictly, use snd_hdac_read() directly. 2987639a06cSTakashi Iwai */ 2999ba17b4dSTakashi Iwai int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, 3009ba17b4dSTakashi Iwai int parm) 3017639a06cSTakashi Iwai { 302*3194ed49STakashi Iwai unsigned int cmd, val; 3037639a06cSTakashi Iwai 304*3194ed49STakashi Iwai cmd = snd_hdac_regmap_encode_verb(nid, AC_VERB_PARAMETERS) | parm; 305*3194ed49STakashi Iwai if (snd_hdac_regmap_read_raw_uncached(codec, cmd, &val) < 0) 306*3194ed49STakashi Iwai return -1; 3077639a06cSTakashi Iwai return val; 3087639a06cSTakashi Iwai } 3099ba17b4dSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_read_parm_uncached); 3109ba17b4dSTakashi Iwai 3119ba17b4dSTakashi Iwai /** 312faa75f8aSTakashi Iwai * snd_hdac_override_parm - override read-only parameters 313faa75f8aSTakashi Iwai * @codec: the codec object 314faa75f8aSTakashi Iwai * @nid: NID for the parameter 315faa75f8aSTakashi Iwai * @parm: the parameter to change 316faa75f8aSTakashi Iwai * @val: the parameter value to overwrite 317faa75f8aSTakashi Iwai */ 318faa75f8aSTakashi Iwai int snd_hdac_override_parm(struct hdac_device *codec, hda_nid_t nid, 319faa75f8aSTakashi Iwai unsigned int parm, unsigned int val) 320faa75f8aSTakashi Iwai { 321faa75f8aSTakashi Iwai unsigned int verb = (AC_VERB_PARAMETERS << 8) | (nid << 20) | parm; 322faa75f8aSTakashi Iwai int err; 323faa75f8aSTakashi Iwai 324faa75f8aSTakashi Iwai if (!codec->regmap) 325faa75f8aSTakashi Iwai return -EINVAL; 326faa75f8aSTakashi Iwai 327faa75f8aSTakashi Iwai codec->caps_overwriting = true; 328faa75f8aSTakashi Iwai err = snd_hdac_regmap_write_raw(codec, verb, val); 329faa75f8aSTakashi Iwai codec->caps_overwriting = false; 330faa75f8aSTakashi Iwai return err; 331faa75f8aSTakashi Iwai } 332faa75f8aSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_override_parm); 3337639a06cSTakashi Iwai 3347639a06cSTakashi Iwai /** 3357639a06cSTakashi Iwai * snd_hdac_get_sub_nodes - get start NID and number of subtree nodes 3367639a06cSTakashi Iwai * @codec: the codec object 3377639a06cSTakashi Iwai * @nid: NID to inspect 3387639a06cSTakashi Iwai * @start_id: the pointer to store the starting NID 3397639a06cSTakashi Iwai * 3407639a06cSTakashi Iwai * Returns the number of subtree nodes or zero if not found. 3419ba17b4dSTakashi Iwai * This function reads parameters always without caching. 3427639a06cSTakashi Iwai */ 3437639a06cSTakashi Iwai int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, 3447639a06cSTakashi Iwai hda_nid_t *start_id) 3457639a06cSTakashi Iwai { 3467639a06cSTakashi Iwai unsigned int parm; 3477639a06cSTakashi Iwai 3489ba17b4dSTakashi Iwai parm = snd_hdac_read_parm_uncached(codec, nid, AC_PAR_NODE_COUNT); 3497639a06cSTakashi Iwai if (parm == -1) { 3507639a06cSTakashi Iwai *start_id = 0; 3517639a06cSTakashi Iwai return 0; 3527639a06cSTakashi Iwai } 3537639a06cSTakashi Iwai *start_id = (parm >> 16) & 0x7fff; 3547639a06cSTakashi Iwai return (int)(parm & 0x7fff); 3557639a06cSTakashi Iwai } 3567639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_get_sub_nodes); 3577639a06cSTakashi Iwai 3587639a06cSTakashi Iwai /* 3597639a06cSTakashi Iwai * look for an AFG and MFG nodes 3607639a06cSTakashi Iwai */ 3617639a06cSTakashi Iwai static void setup_fg_nodes(struct hdac_device *codec) 3627639a06cSTakashi Iwai { 3637639a06cSTakashi Iwai int i, total_nodes, function_id; 3647639a06cSTakashi Iwai hda_nid_t nid; 3657639a06cSTakashi Iwai 3667639a06cSTakashi Iwai total_nodes = snd_hdac_get_sub_nodes(codec, AC_NODE_ROOT, &nid); 3677639a06cSTakashi Iwai for (i = 0; i < total_nodes; i++, nid++) { 3687639a06cSTakashi Iwai function_id = snd_hdac_read_parm(codec, nid, 3697639a06cSTakashi Iwai AC_PAR_FUNCTION_TYPE); 3707639a06cSTakashi Iwai switch (function_id & 0xff) { 3717639a06cSTakashi Iwai case AC_GRP_AUDIO_FUNCTION: 3727639a06cSTakashi Iwai codec->afg = nid; 3737639a06cSTakashi Iwai codec->afg_function_id = function_id & 0xff; 3747639a06cSTakashi Iwai codec->afg_unsol = (function_id >> 8) & 1; 3757639a06cSTakashi Iwai break; 3767639a06cSTakashi Iwai case AC_GRP_MODEM_FUNCTION: 3777639a06cSTakashi Iwai codec->mfg = nid; 3787639a06cSTakashi Iwai codec->mfg_function_id = function_id & 0xff; 3797639a06cSTakashi Iwai codec->mfg_unsol = (function_id >> 8) & 1; 3807639a06cSTakashi Iwai break; 3817639a06cSTakashi Iwai default: 3827639a06cSTakashi Iwai break; 3837639a06cSTakashi Iwai } 3847639a06cSTakashi Iwai } 3857639a06cSTakashi Iwai } 3867639a06cSTakashi Iwai 3877639a06cSTakashi Iwai /** 3887639a06cSTakashi Iwai * snd_hdac_refresh_widgets - Reset the widget start/end nodes 3897639a06cSTakashi Iwai * @codec: the codec object 3907639a06cSTakashi Iwai */ 3917639a06cSTakashi Iwai int snd_hdac_refresh_widgets(struct hdac_device *codec) 3927639a06cSTakashi Iwai { 3937639a06cSTakashi Iwai hda_nid_t start_nid; 3947639a06cSTakashi Iwai int nums; 3957639a06cSTakashi Iwai 3967639a06cSTakashi Iwai nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid); 3977639a06cSTakashi Iwai if (!start_nid || nums <= 0 || nums >= 0xff) { 3987639a06cSTakashi Iwai dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n", 3997639a06cSTakashi Iwai codec->afg); 4007639a06cSTakashi Iwai return -EINVAL; 4017639a06cSTakashi Iwai } 4027639a06cSTakashi Iwai 4037639a06cSTakashi Iwai codec->num_nodes = nums; 4047639a06cSTakashi Iwai codec->start_nid = start_nid; 4057639a06cSTakashi Iwai codec->end_nid = start_nid + nums; 4067639a06cSTakashi Iwai return 0; 4077639a06cSTakashi Iwai } 4087639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); 4097639a06cSTakashi Iwai 41018dfd79dSVinod Koul /** 41118dfd79dSVinod Koul * snd_hdac_refresh_widget_sysfs - Reset the codec widgets and reinit the 41218dfd79dSVinod Koul * codec sysfs 41318dfd79dSVinod Koul * @codec: the codec object 41418dfd79dSVinod Koul * 41518dfd79dSVinod Koul * first we need to remove sysfs, then refresh widgets and lastly 41618dfd79dSVinod Koul * recreate it 41718dfd79dSVinod Koul */ 41818dfd79dSVinod Koul int snd_hdac_refresh_widget_sysfs(struct hdac_device *codec) 41918dfd79dSVinod Koul { 42018dfd79dSVinod Koul int ret; 42118dfd79dSVinod Koul 422a92d5ee8STakashi Iwai if (device_is_registered(&codec->dev)) 42318dfd79dSVinod Koul hda_widget_sysfs_exit(codec); 42418dfd79dSVinod Koul ret = snd_hdac_refresh_widgets(codec); 42518dfd79dSVinod Koul if (ret) { 42618dfd79dSVinod Koul dev_err(&codec->dev, "failed to refresh widget: %d\n", ret); 42718dfd79dSVinod Koul return ret; 42818dfd79dSVinod Koul } 429a92d5ee8STakashi Iwai if (device_is_registered(&codec->dev)) { 43018dfd79dSVinod Koul ret = hda_widget_sysfs_init(codec); 43118dfd79dSVinod Koul if (ret) { 43218dfd79dSVinod Koul dev_err(&codec->dev, "failed to init sysfs: %d\n", ret); 43318dfd79dSVinod Koul return ret; 43418dfd79dSVinod Koul } 435a92d5ee8STakashi Iwai } 43618dfd79dSVinod Koul return ret; 43718dfd79dSVinod Koul } 43818dfd79dSVinod Koul EXPORT_SYMBOL_GPL(snd_hdac_refresh_widget_sysfs); 43918dfd79dSVinod Koul 4407639a06cSTakashi Iwai /* return CONNLIST_LEN parameter of the given widget */ 4417639a06cSTakashi Iwai static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid) 4427639a06cSTakashi Iwai { 4437639a06cSTakashi Iwai unsigned int wcaps = get_wcaps(codec, nid); 4447639a06cSTakashi Iwai unsigned int parm; 4457639a06cSTakashi Iwai 4467639a06cSTakashi Iwai if (!(wcaps & AC_WCAP_CONN_LIST) && 4477639a06cSTakashi Iwai get_wcaps_type(wcaps) != AC_WID_VOL_KNB) 4487639a06cSTakashi Iwai return 0; 4497639a06cSTakashi Iwai 4507639a06cSTakashi Iwai parm = snd_hdac_read_parm(codec, nid, AC_PAR_CONNLIST_LEN); 4517639a06cSTakashi Iwai if (parm == -1) 4527639a06cSTakashi Iwai parm = 0; 4537639a06cSTakashi Iwai return parm; 4547639a06cSTakashi Iwai } 4557639a06cSTakashi Iwai 4567639a06cSTakashi Iwai /** 4577639a06cSTakashi Iwai * snd_hdac_get_connections - get a widget connection list 4587639a06cSTakashi Iwai * @codec: the codec object 4597639a06cSTakashi Iwai * @nid: NID 4607639a06cSTakashi Iwai * @conn_list: the array to store the results, can be NULL 4617639a06cSTakashi Iwai * @max_conns: the max size of the given array 4627639a06cSTakashi Iwai * 4637639a06cSTakashi Iwai * Returns the number of connected widgets, zero for no connection, or a 4647639a06cSTakashi Iwai * negative error code. When the number of elements don't fit with the 4657639a06cSTakashi Iwai * given array size, it returns -ENOSPC. 4667639a06cSTakashi Iwai * 4677639a06cSTakashi Iwai * When @conn_list is NULL, it just checks the number of connections. 4687639a06cSTakashi Iwai */ 4697639a06cSTakashi Iwai int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, 4707639a06cSTakashi Iwai hda_nid_t *conn_list, int max_conns) 4717639a06cSTakashi Iwai { 4727639a06cSTakashi Iwai unsigned int parm; 4737639a06cSTakashi Iwai int i, conn_len, conns, err; 4747639a06cSTakashi Iwai unsigned int shift, num_elems, mask; 4757639a06cSTakashi Iwai hda_nid_t prev_nid; 4767639a06cSTakashi Iwai int null_count = 0; 4777639a06cSTakashi Iwai 4787639a06cSTakashi Iwai parm = get_num_conns(codec, nid); 4797639a06cSTakashi Iwai if (!parm) 4807639a06cSTakashi Iwai return 0; 4817639a06cSTakashi Iwai 4827639a06cSTakashi Iwai if (parm & AC_CLIST_LONG) { 4837639a06cSTakashi Iwai /* long form */ 4847639a06cSTakashi Iwai shift = 16; 4857639a06cSTakashi Iwai num_elems = 2; 4867639a06cSTakashi Iwai } else { 4877639a06cSTakashi Iwai /* short form */ 4887639a06cSTakashi Iwai shift = 8; 4897639a06cSTakashi Iwai num_elems = 4; 4907639a06cSTakashi Iwai } 4917639a06cSTakashi Iwai conn_len = parm & AC_CLIST_LENGTH; 4927639a06cSTakashi Iwai mask = (1 << (shift-1)) - 1; 4937639a06cSTakashi Iwai 4947639a06cSTakashi Iwai if (!conn_len) 4957639a06cSTakashi Iwai return 0; /* no connection */ 4967639a06cSTakashi Iwai 4977639a06cSTakashi Iwai if (conn_len == 1) { 4987639a06cSTakashi Iwai /* single connection */ 4997639a06cSTakashi Iwai err = snd_hdac_read(codec, nid, AC_VERB_GET_CONNECT_LIST, 0, 5007639a06cSTakashi Iwai &parm); 5017639a06cSTakashi Iwai if (err < 0) 5027639a06cSTakashi Iwai return err; 5037639a06cSTakashi Iwai if (conn_list) 5047639a06cSTakashi Iwai conn_list[0] = parm & mask; 5057639a06cSTakashi Iwai return 1; 5067639a06cSTakashi Iwai } 5077639a06cSTakashi Iwai 5087639a06cSTakashi Iwai /* multi connection */ 5097639a06cSTakashi Iwai conns = 0; 5107639a06cSTakashi Iwai prev_nid = 0; 5117639a06cSTakashi Iwai for (i = 0; i < conn_len; i++) { 5127639a06cSTakashi Iwai int range_val; 5137639a06cSTakashi Iwai hda_nid_t val, n; 5147639a06cSTakashi Iwai 5157639a06cSTakashi Iwai if (i % num_elems == 0) { 5167639a06cSTakashi Iwai err = snd_hdac_read(codec, nid, 5177639a06cSTakashi Iwai AC_VERB_GET_CONNECT_LIST, i, 5187639a06cSTakashi Iwai &parm); 5197639a06cSTakashi Iwai if (err < 0) 5207639a06cSTakashi Iwai return -EIO; 5217639a06cSTakashi Iwai } 5227639a06cSTakashi Iwai range_val = !!(parm & (1 << (shift-1))); /* ranges */ 5237639a06cSTakashi Iwai val = parm & mask; 5247639a06cSTakashi Iwai if (val == 0 && null_count++) { /* no second chance */ 5257639a06cSTakashi Iwai dev_dbg(&codec->dev, 5267639a06cSTakashi Iwai "invalid CONNECT_LIST verb %x[%i]:%x\n", 5277639a06cSTakashi Iwai nid, i, parm); 5287639a06cSTakashi Iwai return 0; 5297639a06cSTakashi Iwai } 5307639a06cSTakashi Iwai parm >>= shift; 5317639a06cSTakashi Iwai if (range_val) { 5327639a06cSTakashi Iwai /* ranges between the previous and this one */ 5337639a06cSTakashi Iwai if (!prev_nid || prev_nid >= val) { 5347639a06cSTakashi Iwai dev_warn(&codec->dev, 5357639a06cSTakashi Iwai "invalid dep_range_val %x:%x\n", 5367639a06cSTakashi Iwai prev_nid, val); 5377639a06cSTakashi Iwai continue; 5387639a06cSTakashi Iwai } 5397639a06cSTakashi Iwai for (n = prev_nid + 1; n <= val; n++) { 5407639a06cSTakashi Iwai if (conn_list) { 5417639a06cSTakashi Iwai if (conns >= max_conns) 5427639a06cSTakashi Iwai return -ENOSPC; 5437639a06cSTakashi Iwai conn_list[conns] = n; 5447639a06cSTakashi Iwai } 5457639a06cSTakashi Iwai conns++; 5467639a06cSTakashi Iwai } 5477639a06cSTakashi Iwai } else { 5487639a06cSTakashi Iwai if (conn_list) { 5497639a06cSTakashi Iwai if (conns >= max_conns) 5507639a06cSTakashi Iwai return -ENOSPC; 5517639a06cSTakashi Iwai conn_list[conns] = val; 5527639a06cSTakashi Iwai } 5537639a06cSTakashi Iwai conns++; 5547639a06cSTakashi Iwai } 5557639a06cSTakashi Iwai prev_nid = val; 5567639a06cSTakashi Iwai } 5577639a06cSTakashi Iwai return conns; 5587639a06cSTakashi Iwai } 5597639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_get_connections); 5607639a06cSTakashi Iwai 5617639a06cSTakashi Iwai #ifdef CONFIG_PM 5627639a06cSTakashi Iwai /** 563664c7155STakashi Iwai * snd_hdac_power_up - power up the codec 5647639a06cSTakashi Iwai * @codec: the codec object 565664c7155STakashi Iwai * 566664c7155STakashi Iwai * This function calls the runtime PM helper to power up the given codec. 567664c7155STakashi Iwai * Unlike snd_hdac_power_up_pm(), you should call this only for the code 568664c7155STakashi Iwai * path that isn't included in PM path. Otherwise it gets stuck. 569fbce23a0STakashi Iwai * 570fbce23a0STakashi Iwai * Returns zero if successful, or a negative error code. 5717639a06cSTakashi Iwai */ 572fbce23a0STakashi Iwai int snd_hdac_power_up(struct hdac_device *codec) 5737639a06cSTakashi Iwai { 574fbce23a0STakashi Iwai return pm_runtime_get_sync(&codec->dev); 5757639a06cSTakashi Iwai } 5767639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_up); 5777639a06cSTakashi Iwai 5787639a06cSTakashi Iwai /** 579664c7155STakashi Iwai * snd_hdac_power_down - power down the codec 5807639a06cSTakashi Iwai * @codec: the codec object 581fbce23a0STakashi Iwai * 582fbce23a0STakashi Iwai * Returns zero if successful, or a negative error code. 5837639a06cSTakashi Iwai */ 584fbce23a0STakashi Iwai int snd_hdac_power_down(struct hdac_device *codec) 5857639a06cSTakashi Iwai { 5867639a06cSTakashi Iwai struct device *dev = &codec->dev; 5877639a06cSTakashi Iwai 5887639a06cSTakashi Iwai pm_runtime_mark_last_busy(dev); 589fbce23a0STakashi Iwai return pm_runtime_put_autosuspend(dev); 5907639a06cSTakashi Iwai } 5917639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_down); 592c3aeda62STakashi Iwai 593c3aeda62STakashi Iwai /** 594c3aeda62STakashi Iwai * snd_hdac_power_up_pm - power up the codec 595c3aeda62STakashi Iwai * @codec: the codec object 596c3aeda62STakashi Iwai * 597c3aeda62STakashi Iwai * This function can be called in a recursive code path like init code 598c3aeda62STakashi Iwai * which may be called by PM suspend/resume again. OTOH, if a power-up 599c3aeda62STakashi Iwai * call must wake up the sleeper (e.g. in a kctl callback), use 600c3aeda62STakashi Iwai * snd_hdac_power_up() instead. 601fbce23a0STakashi Iwai * 602fbce23a0STakashi Iwai * Returns zero if successful, or a negative error code. 603c3aeda62STakashi Iwai */ 604fbce23a0STakashi Iwai int snd_hdac_power_up_pm(struct hdac_device *codec) 605c3aeda62STakashi Iwai { 606c3aeda62STakashi Iwai if (!atomic_inc_not_zero(&codec->in_pm)) 607fbce23a0STakashi Iwai return snd_hdac_power_up(codec); 608fbce23a0STakashi Iwai return 0; 609c3aeda62STakashi Iwai } 610c3aeda62STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm); 611c3aeda62STakashi Iwai 612fc4f000bSTakashi Iwai /* like snd_hdac_power_up_pm(), but only increment the pm count when 613fc4f000bSTakashi Iwai * already powered up. Returns -1 if not powered up, 1 if incremented 614fc4f000bSTakashi Iwai * or 0 if unchanged. Only used in hdac_regmap.c 615fc4f000bSTakashi Iwai */ 616fc4f000bSTakashi Iwai int snd_hdac_keep_power_up(struct hdac_device *codec) 617fc4f000bSTakashi Iwai { 618fc4f000bSTakashi Iwai if (!atomic_inc_not_zero(&codec->in_pm)) { 619fc4f000bSTakashi Iwai int ret = pm_runtime_get_if_in_use(&codec->dev); 620fc4f000bSTakashi Iwai if (!ret) 621fc4f000bSTakashi Iwai return -1; 622fc4f000bSTakashi Iwai if (ret < 0) 623fc4f000bSTakashi Iwai return 0; 624fc4f000bSTakashi Iwai } 625fc4f000bSTakashi Iwai return 1; 626fc4f000bSTakashi Iwai } 627fc4f000bSTakashi Iwai 628c3aeda62STakashi Iwai /** 629c3aeda62STakashi Iwai * snd_hdac_power_down_pm - power down the codec 630c3aeda62STakashi Iwai * @codec: the codec object 631c3aeda62STakashi Iwai * 632c3aeda62STakashi Iwai * Like snd_hdac_power_up_pm(), this function is used in a recursive 633c3aeda62STakashi Iwai * code path like init code which may be called by PM suspend/resume again. 634fbce23a0STakashi Iwai * 635fbce23a0STakashi Iwai * Returns zero if successful, or a negative error code. 636c3aeda62STakashi Iwai */ 637fbce23a0STakashi Iwai int snd_hdac_power_down_pm(struct hdac_device *codec) 638c3aeda62STakashi Iwai { 639c3aeda62STakashi Iwai if (atomic_dec_if_positive(&codec->in_pm) < 0) 640fbce23a0STakashi Iwai return snd_hdac_power_down(codec); 641fbce23a0STakashi Iwai return 0; 642c3aeda62STakashi Iwai } 643c3aeda62STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); 6447639a06cSTakashi Iwai #endif 6457639a06cSTakashi Iwai 64678dd5e21STakashi Iwai /** 64778dd5e21STakashi Iwai * snd_hdac_link_power - Enable/disable the link power for a codec 64878dd5e21STakashi Iwai * @codec: the codec object 64978dd5e21STakashi Iwai * @bool: enable or disable the link power 650a5e7e07cSMengdong Lin */ 651a5e7e07cSMengdong Lin int snd_hdac_link_power(struct hdac_device *codec, bool enable) 652a5e7e07cSMengdong Lin { 653a5e7e07cSMengdong Lin if (!codec->link_power_control) 654a5e7e07cSMengdong Lin return 0; 655a5e7e07cSMengdong Lin 656a5e7e07cSMengdong Lin if (codec->bus->ops->link_power) 657a5e7e07cSMengdong Lin return codec->bus->ops->link_power(codec->bus, enable); 658a5e7e07cSMengdong Lin else 659a5e7e07cSMengdong Lin return -EINVAL; 660a5e7e07cSMengdong Lin } 661a5e7e07cSMengdong Lin EXPORT_SYMBOL_GPL(snd_hdac_link_power); 662a5e7e07cSMengdong Lin 6637639a06cSTakashi Iwai /* codec vendor labels */ 6647639a06cSTakashi Iwai struct hda_vendor_id { 6657639a06cSTakashi Iwai unsigned int id; 6667639a06cSTakashi Iwai const char *name; 6677639a06cSTakashi Iwai }; 6687639a06cSTakashi Iwai 6697639a06cSTakashi Iwai static struct hda_vendor_id hda_vendor_ids[] = { 6707639a06cSTakashi Iwai { 0x1002, "ATI" }, 6717639a06cSTakashi Iwai { 0x1013, "Cirrus Logic" }, 6727639a06cSTakashi Iwai { 0x1057, "Motorola" }, 6737639a06cSTakashi Iwai { 0x1095, "Silicon Image" }, 6747639a06cSTakashi Iwai { 0x10de, "Nvidia" }, 6757639a06cSTakashi Iwai { 0x10ec, "Realtek" }, 6767639a06cSTakashi Iwai { 0x1102, "Creative" }, 6777639a06cSTakashi Iwai { 0x1106, "VIA" }, 6787639a06cSTakashi Iwai { 0x111d, "IDT" }, 6797639a06cSTakashi Iwai { 0x11c1, "LSI" }, 6807639a06cSTakashi Iwai { 0x11d4, "Analog Devices" }, 6817639a06cSTakashi Iwai { 0x13f6, "C-Media" }, 6827639a06cSTakashi Iwai { 0x14f1, "Conexant" }, 6837639a06cSTakashi Iwai { 0x17e8, "Chrontel" }, 6847639a06cSTakashi Iwai { 0x1854, "LG" }, 6857639a06cSTakashi Iwai { 0x1aec, "Wolfson Microelectronics" }, 6867639a06cSTakashi Iwai { 0x1af4, "QEMU" }, 6877639a06cSTakashi Iwai { 0x434d, "C-Media" }, 6887639a06cSTakashi Iwai { 0x8086, "Intel" }, 6897639a06cSTakashi Iwai { 0x8384, "SigmaTel" }, 6907639a06cSTakashi Iwai {} /* terminator */ 6917639a06cSTakashi Iwai }; 6927639a06cSTakashi Iwai 6937639a06cSTakashi Iwai /* store the codec vendor name */ 6947639a06cSTakashi Iwai static int get_codec_vendor_name(struct hdac_device *codec) 6957639a06cSTakashi Iwai { 6967639a06cSTakashi Iwai const struct hda_vendor_id *c; 6977639a06cSTakashi Iwai u16 vendor_id = codec->vendor_id >> 16; 6987639a06cSTakashi Iwai 6997639a06cSTakashi Iwai for (c = hda_vendor_ids; c->id; c++) { 7007639a06cSTakashi Iwai if (c->id == vendor_id) { 7017639a06cSTakashi Iwai codec->vendor_name = kstrdup(c->name, GFP_KERNEL); 7027639a06cSTakashi Iwai return codec->vendor_name ? 0 : -ENOMEM; 7037639a06cSTakashi Iwai } 7047639a06cSTakashi Iwai } 7057639a06cSTakashi Iwai 7067639a06cSTakashi Iwai codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id); 7077639a06cSTakashi Iwai return codec->vendor_name ? 0 : -ENOMEM; 7087639a06cSTakashi Iwai } 709b7d023e1STakashi Iwai 710b7d023e1STakashi Iwai /* 711b7d023e1STakashi Iwai * stream formats 712b7d023e1STakashi Iwai */ 713b7d023e1STakashi Iwai struct hda_rate_tbl { 714b7d023e1STakashi Iwai unsigned int hz; 715b7d023e1STakashi Iwai unsigned int alsa_bits; 716b7d023e1STakashi Iwai unsigned int hda_fmt; 717b7d023e1STakashi Iwai }; 718b7d023e1STakashi Iwai 719b7d023e1STakashi Iwai /* rate = base * mult / div */ 720b7d023e1STakashi Iwai #define HDA_RATE(base, mult, div) \ 721b7d023e1STakashi Iwai (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ 722b7d023e1STakashi Iwai (((div) - 1) << AC_FMT_DIV_SHIFT)) 723b7d023e1STakashi Iwai 724b7d023e1STakashi Iwai static struct hda_rate_tbl rate_bits[] = { 725b7d023e1STakashi Iwai /* rate in Hz, ALSA rate bitmask, HDA format value */ 726b7d023e1STakashi Iwai 727b7d023e1STakashi Iwai /* autodetected value used in snd_hda_query_supported_pcm */ 728b7d023e1STakashi Iwai { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, 729b7d023e1STakashi Iwai { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, 730b7d023e1STakashi Iwai { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, 731b7d023e1STakashi Iwai { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, 732b7d023e1STakashi Iwai { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, 733b7d023e1STakashi Iwai { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, 734b7d023e1STakashi Iwai { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, 735b7d023e1STakashi Iwai { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, 736b7d023e1STakashi Iwai { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, 737b7d023e1STakashi Iwai { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, 738b7d023e1STakashi Iwai { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, 739b7d023e1STakashi Iwai #define AC_PAR_PCM_RATE_BITS 11 740b7d023e1STakashi Iwai /* up to bits 10, 384kHZ isn't supported properly */ 741b7d023e1STakashi Iwai 742b7d023e1STakashi Iwai /* not autodetected value */ 743b7d023e1STakashi Iwai { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, 744b7d023e1STakashi Iwai 745b7d023e1STakashi Iwai { 0 } /* terminator */ 746b7d023e1STakashi Iwai }; 747b7d023e1STakashi Iwai 748b7d023e1STakashi Iwai /** 749b7d023e1STakashi Iwai * snd_hdac_calc_stream_format - calculate the format bitset 750b7d023e1STakashi Iwai * @rate: the sample rate 751b7d023e1STakashi Iwai * @channels: the number of channels 752b7d023e1STakashi Iwai * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) 753b7d023e1STakashi Iwai * @maxbps: the max. bps 754b7d023e1STakashi Iwai * @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant) 755b7d023e1STakashi Iwai * 756b7d023e1STakashi Iwai * Calculate the format bitset from the given rate, channels and th PCM format. 757b7d023e1STakashi Iwai * 758b7d023e1STakashi Iwai * Return zero if invalid. 759b7d023e1STakashi Iwai */ 760b7d023e1STakashi Iwai unsigned int snd_hdac_calc_stream_format(unsigned int rate, 761b7d023e1STakashi Iwai unsigned int channels, 762b7d023e1STakashi Iwai unsigned int format, 763b7d023e1STakashi Iwai unsigned int maxbps, 764b7d023e1STakashi Iwai unsigned short spdif_ctls) 765b7d023e1STakashi Iwai { 766b7d023e1STakashi Iwai int i; 767b7d023e1STakashi Iwai unsigned int val = 0; 768b7d023e1STakashi Iwai 769b7d023e1STakashi Iwai for (i = 0; rate_bits[i].hz; i++) 770b7d023e1STakashi Iwai if (rate_bits[i].hz == rate) { 771b7d023e1STakashi Iwai val = rate_bits[i].hda_fmt; 772b7d023e1STakashi Iwai break; 773b7d023e1STakashi Iwai } 774b7d023e1STakashi Iwai if (!rate_bits[i].hz) 775b7d023e1STakashi Iwai return 0; 776b7d023e1STakashi Iwai 777b7d023e1STakashi Iwai if (channels == 0 || channels > 8) 778b7d023e1STakashi Iwai return 0; 779b7d023e1STakashi Iwai val |= channels - 1; 780b7d023e1STakashi Iwai 781b7d023e1STakashi Iwai switch (snd_pcm_format_width(format)) { 782b7d023e1STakashi Iwai case 8: 783b7d023e1STakashi Iwai val |= AC_FMT_BITS_8; 784b7d023e1STakashi Iwai break; 785b7d023e1STakashi Iwai case 16: 786b7d023e1STakashi Iwai val |= AC_FMT_BITS_16; 787b7d023e1STakashi Iwai break; 788b7d023e1STakashi Iwai case 20: 789b7d023e1STakashi Iwai case 24: 790b7d023e1STakashi Iwai case 32: 791b7d023e1STakashi Iwai if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) 792b7d023e1STakashi Iwai val |= AC_FMT_BITS_32; 793b7d023e1STakashi Iwai else if (maxbps >= 24) 794b7d023e1STakashi Iwai val |= AC_FMT_BITS_24; 795b7d023e1STakashi Iwai else 796b7d023e1STakashi Iwai val |= AC_FMT_BITS_20; 797b7d023e1STakashi Iwai break; 798b7d023e1STakashi Iwai default: 799b7d023e1STakashi Iwai return 0; 800b7d023e1STakashi Iwai } 801b7d023e1STakashi Iwai 802b7d023e1STakashi Iwai if (spdif_ctls & AC_DIG1_NONAUDIO) 803b7d023e1STakashi Iwai val |= AC_FMT_TYPE_NON_PCM; 804b7d023e1STakashi Iwai 805b7d023e1STakashi Iwai return val; 806b7d023e1STakashi Iwai } 807b7d023e1STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_calc_stream_format); 808b7d023e1STakashi Iwai 809b7d023e1STakashi Iwai static unsigned int query_pcm_param(struct hdac_device *codec, hda_nid_t nid) 810b7d023e1STakashi Iwai { 811b7d023e1STakashi Iwai unsigned int val = 0; 812b7d023e1STakashi Iwai 813b7d023e1STakashi Iwai if (nid != codec->afg && 814b7d023e1STakashi Iwai (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) 815b7d023e1STakashi Iwai val = snd_hdac_read_parm(codec, nid, AC_PAR_PCM); 816b7d023e1STakashi Iwai if (!val || val == -1) 817b7d023e1STakashi Iwai val = snd_hdac_read_parm(codec, codec->afg, AC_PAR_PCM); 818b7d023e1STakashi Iwai if (!val || val == -1) 819b7d023e1STakashi Iwai return 0; 820b7d023e1STakashi Iwai return val; 821b7d023e1STakashi Iwai } 822b7d023e1STakashi Iwai 823b7d023e1STakashi Iwai static unsigned int query_stream_param(struct hdac_device *codec, hda_nid_t nid) 824b7d023e1STakashi Iwai { 825b7d023e1STakashi Iwai unsigned int streams = snd_hdac_read_parm(codec, nid, AC_PAR_STREAM); 826b7d023e1STakashi Iwai 827b7d023e1STakashi Iwai if (!streams || streams == -1) 828b7d023e1STakashi Iwai streams = snd_hdac_read_parm(codec, codec->afg, AC_PAR_STREAM); 829b7d023e1STakashi Iwai if (!streams || streams == -1) 830b7d023e1STakashi Iwai return 0; 831b7d023e1STakashi Iwai return streams; 832b7d023e1STakashi Iwai } 833b7d023e1STakashi Iwai 834b7d023e1STakashi Iwai /** 835b7d023e1STakashi Iwai * snd_hdac_query_supported_pcm - query the supported PCM rates and formats 836b7d023e1STakashi Iwai * @codec: the codec object 837b7d023e1STakashi Iwai * @nid: NID to query 838b7d023e1STakashi Iwai * @ratesp: the pointer to store the detected rate bitflags 839b7d023e1STakashi Iwai * @formatsp: the pointer to store the detected formats 840b7d023e1STakashi Iwai * @bpsp: the pointer to store the detected format widths 841b7d023e1STakashi Iwai * 842b7d023e1STakashi Iwai * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp 843b7d023e1STakashi Iwai * or @bsps argument is ignored. 844b7d023e1STakashi Iwai * 845b7d023e1STakashi Iwai * Returns 0 if successful, otherwise a negative error code. 846b7d023e1STakashi Iwai */ 847b7d023e1STakashi Iwai int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid, 848b7d023e1STakashi Iwai u32 *ratesp, u64 *formatsp, unsigned int *bpsp) 849b7d023e1STakashi Iwai { 850b7d023e1STakashi Iwai unsigned int i, val, wcaps; 851b7d023e1STakashi Iwai 852b7d023e1STakashi Iwai wcaps = get_wcaps(codec, nid); 853b7d023e1STakashi Iwai val = query_pcm_param(codec, nid); 854b7d023e1STakashi Iwai 855b7d023e1STakashi Iwai if (ratesp) { 856b7d023e1STakashi Iwai u32 rates = 0; 857b7d023e1STakashi Iwai for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) { 858b7d023e1STakashi Iwai if (val & (1 << i)) 859b7d023e1STakashi Iwai rates |= rate_bits[i].alsa_bits; 860b7d023e1STakashi Iwai } 861b7d023e1STakashi Iwai if (rates == 0) { 862b7d023e1STakashi Iwai dev_err(&codec->dev, 863b7d023e1STakashi Iwai "rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)\n", 864b7d023e1STakashi Iwai nid, val, 865b7d023e1STakashi Iwai (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); 866b7d023e1STakashi Iwai return -EIO; 867b7d023e1STakashi Iwai } 868b7d023e1STakashi Iwai *ratesp = rates; 869b7d023e1STakashi Iwai } 870b7d023e1STakashi Iwai 871b7d023e1STakashi Iwai if (formatsp || bpsp) { 872b7d023e1STakashi Iwai u64 formats = 0; 873b7d023e1STakashi Iwai unsigned int streams, bps; 874b7d023e1STakashi Iwai 875b7d023e1STakashi Iwai streams = query_stream_param(codec, nid); 876b7d023e1STakashi Iwai if (!streams) 877b7d023e1STakashi Iwai return -EIO; 878b7d023e1STakashi Iwai 879b7d023e1STakashi Iwai bps = 0; 880b7d023e1STakashi Iwai if (streams & AC_SUPFMT_PCM) { 881b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_8) { 882b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_U8; 883b7d023e1STakashi Iwai bps = 8; 884b7d023e1STakashi Iwai } 885b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_16) { 886b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_S16_LE; 887b7d023e1STakashi Iwai bps = 16; 888b7d023e1STakashi Iwai } 889b7d023e1STakashi Iwai if (wcaps & AC_WCAP_DIGITAL) { 890b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_32) 891b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; 892b7d023e1STakashi Iwai if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24)) 893b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_S32_LE; 894b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_24) 895b7d023e1STakashi Iwai bps = 24; 896b7d023e1STakashi Iwai else if (val & AC_SUPPCM_BITS_20) 897b7d023e1STakashi Iwai bps = 20; 898b7d023e1STakashi Iwai } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24| 899b7d023e1STakashi Iwai AC_SUPPCM_BITS_32)) { 900b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_S32_LE; 901b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_32) 902b7d023e1STakashi Iwai bps = 32; 903b7d023e1STakashi Iwai else if (val & AC_SUPPCM_BITS_24) 904b7d023e1STakashi Iwai bps = 24; 905b7d023e1STakashi Iwai else if (val & AC_SUPPCM_BITS_20) 906b7d023e1STakashi Iwai bps = 20; 907b7d023e1STakashi Iwai } 908b7d023e1STakashi Iwai } 909b7d023e1STakashi Iwai #if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */ 910b7d023e1STakashi Iwai if (streams & AC_SUPFMT_FLOAT32) { 911b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; 912b7d023e1STakashi Iwai if (!bps) 913b7d023e1STakashi Iwai bps = 32; 914b7d023e1STakashi Iwai } 915b7d023e1STakashi Iwai #endif 916b7d023e1STakashi Iwai if (streams == AC_SUPFMT_AC3) { 917b7d023e1STakashi Iwai /* should be exclusive */ 918b7d023e1STakashi Iwai /* temporary hack: we have still no proper support 919b7d023e1STakashi Iwai * for the direct AC3 stream... 920b7d023e1STakashi Iwai */ 921b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_U8; 922b7d023e1STakashi Iwai bps = 8; 923b7d023e1STakashi Iwai } 924b7d023e1STakashi Iwai if (formats == 0) { 925b7d023e1STakashi Iwai dev_err(&codec->dev, 926b7d023e1STakashi Iwai "formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)\n", 927b7d023e1STakashi Iwai nid, val, 928b7d023e1STakashi Iwai (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, 929b7d023e1STakashi Iwai streams); 930b7d023e1STakashi Iwai return -EIO; 931b7d023e1STakashi Iwai } 932b7d023e1STakashi Iwai if (formatsp) 933b7d023e1STakashi Iwai *formatsp = formats; 934b7d023e1STakashi Iwai if (bpsp) 935b7d023e1STakashi Iwai *bpsp = bps; 936b7d023e1STakashi Iwai } 937b7d023e1STakashi Iwai 938b7d023e1STakashi Iwai return 0; 939b7d023e1STakashi Iwai } 940b7d023e1STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_query_supported_pcm); 941b7d023e1STakashi Iwai 942b7d023e1STakashi Iwai /** 943b7d023e1STakashi Iwai * snd_hdac_is_supported_format - Check the validity of the format 944b7d023e1STakashi Iwai * @codec: the codec object 945b7d023e1STakashi Iwai * @nid: NID to check 946b7d023e1STakashi Iwai * @format: the HD-audio format value to check 947b7d023e1STakashi Iwai * 948b7d023e1STakashi Iwai * Check whether the given node supports the format value. 949b7d023e1STakashi Iwai * 950b7d023e1STakashi Iwai * Returns true if supported, false if not. 951b7d023e1STakashi Iwai */ 952b7d023e1STakashi Iwai bool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid, 953b7d023e1STakashi Iwai unsigned int format) 954b7d023e1STakashi Iwai { 955b7d023e1STakashi Iwai int i; 956b7d023e1STakashi Iwai unsigned int val = 0, rate, stream; 957b7d023e1STakashi Iwai 958b7d023e1STakashi Iwai val = query_pcm_param(codec, nid); 959b7d023e1STakashi Iwai if (!val) 960b7d023e1STakashi Iwai return false; 961b7d023e1STakashi Iwai 962b7d023e1STakashi Iwai rate = format & 0xff00; 963b7d023e1STakashi Iwai for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) 964b7d023e1STakashi Iwai if (rate_bits[i].hda_fmt == rate) { 965b7d023e1STakashi Iwai if (val & (1 << i)) 966b7d023e1STakashi Iwai break; 967b7d023e1STakashi Iwai return false; 968b7d023e1STakashi Iwai } 969b7d023e1STakashi Iwai if (i >= AC_PAR_PCM_RATE_BITS) 970b7d023e1STakashi Iwai return false; 971b7d023e1STakashi Iwai 972b7d023e1STakashi Iwai stream = query_stream_param(codec, nid); 973b7d023e1STakashi Iwai if (!stream) 974b7d023e1STakashi Iwai return false; 975b7d023e1STakashi Iwai 976b7d023e1STakashi Iwai if (stream & AC_SUPFMT_PCM) { 977b7d023e1STakashi Iwai switch (format & 0xf0) { 978b7d023e1STakashi Iwai case 0x00: 979b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_8)) 980b7d023e1STakashi Iwai return false; 981b7d023e1STakashi Iwai break; 982b7d023e1STakashi Iwai case 0x10: 983b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_16)) 984b7d023e1STakashi Iwai return false; 985b7d023e1STakashi Iwai break; 986b7d023e1STakashi Iwai case 0x20: 987b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_20)) 988b7d023e1STakashi Iwai return false; 989b7d023e1STakashi Iwai break; 990b7d023e1STakashi Iwai case 0x30: 991b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_24)) 992b7d023e1STakashi Iwai return false; 993b7d023e1STakashi Iwai break; 994b7d023e1STakashi Iwai case 0x40: 995b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_32)) 996b7d023e1STakashi Iwai return false; 997b7d023e1STakashi Iwai break; 998b7d023e1STakashi Iwai default: 999b7d023e1STakashi Iwai return false; 1000b7d023e1STakashi Iwai } 1001b7d023e1STakashi Iwai } else { 1002b7d023e1STakashi Iwai /* FIXME: check for float32 and AC3? */ 1003b7d023e1STakashi Iwai } 1004b7d023e1STakashi Iwai 1005b7d023e1STakashi Iwai return true; 1006b7d023e1STakashi Iwai } 1007b7d023e1STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_is_supported_format); 10081b5e6167SSubhransu S. Prusty 10091b5e6167SSubhransu S. Prusty static unsigned int codec_read(struct hdac_device *hdac, hda_nid_t nid, 10101b5e6167SSubhransu S. Prusty int flags, unsigned int verb, unsigned int parm) 10111b5e6167SSubhransu S. Prusty { 10121b5e6167SSubhransu S. Prusty unsigned int cmd = snd_hdac_make_cmd(hdac, nid, verb, parm); 10131b5e6167SSubhransu S. Prusty unsigned int res; 10141b5e6167SSubhransu S. Prusty 10151b5e6167SSubhransu S. Prusty if (snd_hdac_exec_verb(hdac, cmd, flags, &res)) 10161b5e6167SSubhransu S. Prusty return -1; 10171b5e6167SSubhransu S. Prusty 10181b5e6167SSubhransu S. Prusty return res; 10191b5e6167SSubhransu S. Prusty } 10201b5e6167SSubhransu S. Prusty 10211b5e6167SSubhransu S. Prusty static int codec_write(struct hdac_device *hdac, hda_nid_t nid, 10221b5e6167SSubhransu S. Prusty int flags, unsigned int verb, unsigned int parm) 10231b5e6167SSubhransu S. Prusty { 10241b5e6167SSubhransu S. Prusty unsigned int cmd = snd_hdac_make_cmd(hdac, nid, verb, parm); 10251b5e6167SSubhransu S. Prusty 10261b5e6167SSubhransu S. Prusty return snd_hdac_exec_verb(hdac, cmd, flags, NULL); 10271b5e6167SSubhransu S. Prusty } 10281b5e6167SSubhransu S. Prusty 10291b5e6167SSubhransu S. Prusty /** 10301b5e6167SSubhransu S. Prusty * snd_hdac_codec_read - send a command and get the response 10311b5e6167SSubhransu S. Prusty * @hdac: the HDAC device 10321b5e6167SSubhransu S. Prusty * @nid: NID to send the command 10331b5e6167SSubhransu S. Prusty * @flags: optional bit flags 10341b5e6167SSubhransu S. Prusty * @verb: the verb to send 10351b5e6167SSubhransu S. Prusty * @parm: the parameter for the verb 10361b5e6167SSubhransu S. Prusty * 10371b5e6167SSubhransu S. Prusty * Send a single command and read the corresponding response. 10381b5e6167SSubhransu S. Prusty * 10391b5e6167SSubhransu S. Prusty * Returns the obtained response value, or -1 for an error. 10401b5e6167SSubhransu S. Prusty */ 10411b5e6167SSubhransu S. Prusty int snd_hdac_codec_read(struct hdac_device *hdac, hda_nid_t nid, 10421b5e6167SSubhransu S. Prusty int flags, unsigned int verb, unsigned int parm) 10431b5e6167SSubhransu S. Prusty { 10441b5e6167SSubhransu S. Prusty return codec_read(hdac, nid, flags, verb, parm); 10451b5e6167SSubhransu S. Prusty } 10461b5e6167SSubhransu S. Prusty EXPORT_SYMBOL_GPL(snd_hdac_codec_read); 10471b5e6167SSubhransu S. Prusty 10481b5e6167SSubhransu S. Prusty /** 10491b5e6167SSubhransu S. Prusty * snd_hdac_codec_write - send a single command without waiting for response 10501b5e6167SSubhransu S. Prusty * @hdac: the HDAC device 10511b5e6167SSubhransu S. Prusty * @nid: NID to send the command 10521b5e6167SSubhransu S. Prusty * @flags: optional bit flags 10531b5e6167SSubhransu S. Prusty * @verb: the verb to send 10541b5e6167SSubhransu S. Prusty * @parm: the parameter for the verb 10551b5e6167SSubhransu S. Prusty * 10561b5e6167SSubhransu S. Prusty * Send a single command without waiting for response. 10571b5e6167SSubhransu S. Prusty * 10581b5e6167SSubhransu S. Prusty * Returns 0 if successful, or a negative error code. 10591b5e6167SSubhransu S. Prusty */ 10601b5e6167SSubhransu S. Prusty int snd_hdac_codec_write(struct hdac_device *hdac, hda_nid_t nid, 10611b5e6167SSubhransu S. Prusty int flags, unsigned int verb, unsigned int parm) 10621b5e6167SSubhransu S. Prusty { 10631b5e6167SSubhransu S. Prusty return codec_write(hdac, nid, flags, verb, parm); 10641b5e6167SSubhransu S. Prusty } 10651b5e6167SSubhransu S. Prusty EXPORT_SYMBOL_GPL(snd_hdac_codec_write); 10661b5e6167SSubhransu S. Prusty 106778dd5e21STakashi Iwai /** 106878dd5e21STakashi Iwai * snd_hdac_check_power_state - check whether the actual power state matches 10691b5e6167SSubhransu S. Prusty * with the target state 10701b5e6167SSubhransu S. Prusty * 10711b5e6167SSubhransu S. Prusty * @hdac: the HDAC device 10721b5e6167SSubhransu S. Prusty * @nid: NID to send the command 10731b5e6167SSubhransu S. Prusty * @target_state: target state to check for 10741b5e6167SSubhransu S. Prusty * 10751b5e6167SSubhransu S. Prusty * Return true if state matches, false if not 10761b5e6167SSubhransu S. Prusty */ 10771b5e6167SSubhransu S. Prusty bool snd_hdac_check_power_state(struct hdac_device *hdac, 10781b5e6167SSubhransu S. Prusty hda_nid_t nid, unsigned int target_state) 10791b5e6167SSubhransu S. Prusty { 10801b5e6167SSubhransu S. Prusty unsigned int state = codec_read(hdac, nid, 0, 10811b5e6167SSubhransu S. Prusty AC_VERB_GET_POWER_STATE, 0); 10821b5e6167SSubhransu S. Prusty 10831b5e6167SSubhransu S. Prusty if (state & AC_PWRST_ERROR) 10841b5e6167SSubhransu S. Prusty return true; 10851b5e6167SSubhransu S. Prusty state = (state >> 4) & 0x0f; 10861b5e6167SSubhransu S. Prusty return (state == target_state); 10871b5e6167SSubhransu S. Prusty } 10881b5e6167SSubhransu S. Prusty EXPORT_SYMBOL_GPL(snd_hdac_check_power_state); 1089