17639a06cSTakashi Iwai /* 27639a06cSTakashi Iwai * HD-audio codec core device 37639a06cSTakashi Iwai */ 47639a06cSTakashi Iwai 57639a06cSTakashi Iwai #include <linux/init.h> 609787492SAbhijeet Kumar #include <linux/delay.h> 77639a06cSTakashi Iwai #include <linux/device.h> 87639a06cSTakashi Iwai #include <linux/slab.h> 97639a06cSTakashi Iwai #include <linux/module.h> 107639a06cSTakashi Iwai #include <linux/export.h> 117639a06cSTakashi Iwai #include <linux/pm_runtime.h> 127639a06cSTakashi Iwai #include <sound/hdaudio.h> 1301ed3c06STakashi Iwai #include <sound/hda_regmap.h> 14b7d023e1STakashi Iwai #include <sound/pcm.h> 157639a06cSTakashi Iwai #include "local.h" 167639a06cSTakashi Iwai 177639a06cSTakashi Iwai static void setup_fg_nodes(struct hdac_device *codec); 187639a06cSTakashi Iwai static int get_codec_vendor_name(struct hdac_device *codec); 197639a06cSTakashi Iwai 207639a06cSTakashi Iwai static void default_release(struct device *dev) 217639a06cSTakashi Iwai { 227639a06cSTakashi Iwai snd_hdac_device_exit(container_of(dev, struct hdac_device, dev)); 237639a06cSTakashi Iwai } 247639a06cSTakashi Iwai 257639a06cSTakashi Iwai /** 267639a06cSTakashi Iwai * snd_hdac_device_init - initialize the HD-audio codec base device 277639a06cSTakashi Iwai * @codec: device to initialize 287639a06cSTakashi Iwai * @bus: but to attach 297639a06cSTakashi Iwai * @name: device name string 307639a06cSTakashi Iwai * @addr: codec address 317639a06cSTakashi Iwai * 327639a06cSTakashi Iwai * Returns zero for success or a negative error code. 337639a06cSTakashi Iwai * 347639a06cSTakashi Iwai * This function increments the runtime PM counter and marks it active. 357639a06cSTakashi Iwai * The caller needs to turn it off appropriately later. 367639a06cSTakashi Iwai * 377639a06cSTakashi Iwai * The caller needs to set the device's release op properly by itself. 387639a06cSTakashi Iwai */ 397639a06cSTakashi Iwai int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus, 407639a06cSTakashi Iwai const char *name, unsigned int addr) 417639a06cSTakashi Iwai { 427639a06cSTakashi Iwai struct device *dev; 437639a06cSTakashi Iwai hda_nid_t fg; 447639a06cSTakashi Iwai int err; 457639a06cSTakashi Iwai 467639a06cSTakashi Iwai dev = &codec->dev; 477639a06cSTakashi Iwai device_initialize(dev); 487639a06cSTakashi Iwai dev->parent = bus->dev; 497639a06cSTakashi Iwai dev->bus = &snd_hda_bus_type; 507639a06cSTakashi Iwai dev->release = default_release; 513256be65STakashi Iwai dev->groups = hdac_dev_attr_groups; 527639a06cSTakashi Iwai dev_set_name(dev, "%s", name); 537639a06cSTakashi Iwai device_enable_async_suspend(dev); 547639a06cSTakashi Iwai 557639a06cSTakashi Iwai codec->bus = bus; 567639a06cSTakashi Iwai codec->addr = addr; 577639a06cSTakashi Iwai codec->type = HDA_DEV_CORE; 58ed180abbSAmadeusz Sławiński mutex_init(&codec->widget_lock); 597639a06cSTakashi Iwai pm_runtime_set_active(&codec->dev); 607639a06cSTakashi Iwai pm_runtime_get_noresume(&codec->dev); 617639a06cSTakashi Iwai atomic_set(&codec->in_pm, 0); 627639a06cSTakashi Iwai 637639a06cSTakashi Iwai err = snd_hdac_bus_add_device(bus, codec); 647639a06cSTakashi Iwai if (err < 0) 657639a06cSTakashi Iwai goto error; 667639a06cSTakashi Iwai 677639a06cSTakashi Iwai /* fill parameters */ 687639a06cSTakashi Iwai codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 697639a06cSTakashi Iwai AC_PAR_VENDOR_ID); 707639a06cSTakashi Iwai if (codec->vendor_id == -1) { 717639a06cSTakashi Iwai /* read again, hopefully the access method was corrected 727639a06cSTakashi Iwai * in the last read... 737639a06cSTakashi Iwai */ 747639a06cSTakashi Iwai codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 757639a06cSTakashi Iwai AC_PAR_VENDOR_ID); 767639a06cSTakashi Iwai } 777639a06cSTakashi Iwai 787639a06cSTakashi Iwai codec->subsystem_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 797639a06cSTakashi Iwai AC_PAR_SUBSYSTEM_ID); 807639a06cSTakashi Iwai codec->revision_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 817639a06cSTakashi Iwai AC_PAR_REV_ID); 827639a06cSTakashi Iwai 837639a06cSTakashi Iwai setup_fg_nodes(codec); 847639a06cSTakashi Iwai if (!codec->afg && !codec->mfg) { 857639a06cSTakashi Iwai dev_err(dev, "no AFG or MFG node found\n"); 867639a06cSTakashi Iwai err = -ENODEV; 877639a06cSTakashi Iwai goto error; 887639a06cSTakashi Iwai } 897639a06cSTakashi Iwai 907639a06cSTakashi Iwai fg = codec->afg ? codec->afg : codec->mfg; 917639a06cSTakashi Iwai 929780ded3STakashi Iwai err = snd_hdac_refresh_widgets(codec, false); 937639a06cSTakashi Iwai if (err < 0) 947639a06cSTakashi Iwai goto error; 957639a06cSTakashi Iwai 967639a06cSTakashi Iwai codec->power_caps = snd_hdac_read_parm(codec, fg, AC_PAR_POWER_STATE); 977639a06cSTakashi Iwai /* reread ssid if not set by parameter */ 98ffda568eSDavid Henningsson if (codec->subsystem_id == -1 || codec->subsystem_id == 0) 997639a06cSTakashi Iwai snd_hdac_read(codec, fg, AC_VERB_GET_SUBSYSTEM_ID, 0, 1007639a06cSTakashi Iwai &codec->subsystem_id); 1017639a06cSTakashi Iwai 1027639a06cSTakashi Iwai err = get_codec_vendor_name(codec); 1037639a06cSTakashi Iwai if (err < 0) 1047639a06cSTakashi Iwai goto error; 1057639a06cSTakashi Iwai 1067639a06cSTakashi Iwai codec->chip_name = kasprintf(GFP_KERNEL, "ID %x", 1077639a06cSTakashi Iwai codec->vendor_id & 0xffff); 1087639a06cSTakashi Iwai if (!codec->chip_name) { 1097639a06cSTakashi Iwai err = -ENOMEM; 1107639a06cSTakashi Iwai goto error; 1117639a06cSTakashi Iwai } 1127639a06cSTakashi Iwai 1137639a06cSTakashi Iwai return 0; 1147639a06cSTakashi Iwai 1157639a06cSTakashi Iwai error: 1167639a06cSTakashi Iwai put_device(&codec->dev); 1177639a06cSTakashi Iwai return err; 1187639a06cSTakashi Iwai } 1197639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_init); 1207639a06cSTakashi Iwai 1217639a06cSTakashi Iwai /** 1227639a06cSTakashi Iwai * snd_hdac_device_exit - clean up the HD-audio codec base device 1237639a06cSTakashi Iwai * @codec: device to clean up 1247639a06cSTakashi Iwai */ 1257639a06cSTakashi Iwai void snd_hdac_device_exit(struct hdac_device *codec) 1267639a06cSTakashi Iwai { 127c4c2533fSTakashi Iwai pm_runtime_put_noidle(&codec->dev); 1287639a06cSTakashi Iwai snd_hdac_bus_remove_device(codec->bus, codec); 1297639a06cSTakashi Iwai kfree(codec->vendor_name); 1307639a06cSTakashi Iwai kfree(codec->chip_name); 1317639a06cSTakashi Iwai } 1327639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_exit); 1337639a06cSTakashi Iwai 1347639a06cSTakashi Iwai /** 1353256be65STakashi Iwai * snd_hdac_device_register - register the hd-audio codec base device 1363256be65STakashi Iwai * codec: the device to register 1373256be65STakashi Iwai */ 1383256be65STakashi Iwai int snd_hdac_device_register(struct hdac_device *codec) 1393256be65STakashi Iwai { 1403256be65STakashi Iwai int err; 1413256be65STakashi Iwai 1423256be65STakashi Iwai err = device_add(&codec->dev); 1433256be65STakashi Iwai if (err < 0) 1443256be65STakashi Iwai return err; 145ed180abbSAmadeusz Sławiński mutex_lock(&codec->widget_lock); 1463256be65STakashi Iwai err = hda_widget_sysfs_init(codec); 147ed180abbSAmadeusz Sławiński mutex_unlock(&codec->widget_lock); 1483256be65STakashi Iwai if (err < 0) { 1493256be65STakashi Iwai device_del(&codec->dev); 1503256be65STakashi Iwai return err; 1513256be65STakashi Iwai } 1523256be65STakashi Iwai 1533256be65STakashi Iwai return 0; 1543256be65STakashi Iwai } 1553256be65STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_register); 1563256be65STakashi Iwai 1573256be65STakashi Iwai /** 1583256be65STakashi Iwai * snd_hdac_device_unregister - unregister the hd-audio codec base device 1593256be65STakashi Iwai * codec: the device to unregister 1603256be65STakashi Iwai */ 1613256be65STakashi Iwai void snd_hdac_device_unregister(struct hdac_device *codec) 1623256be65STakashi Iwai { 1633256be65STakashi Iwai if (device_is_registered(&codec->dev)) { 164ed180abbSAmadeusz Sławiński mutex_lock(&codec->widget_lock); 1653256be65STakashi Iwai hda_widget_sysfs_exit(codec); 166ed180abbSAmadeusz Sławiński mutex_unlock(&codec->widget_lock); 1673256be65STakashi Iwai device_del(&codec->dev); 168eb8d0eaaSTakashi Iwai snd_hdac_bus_remove_device(codec->bus, codec); 1693256be65STakashi Iwai } 1703256be65STakashi Iwai } 1713256be65STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_unregister); 1723256be65STakashi Iwai 1733256be65STakashi Iwai /** 174ded255beSTakashi Iwai * snd_hdac_device_set_chip_name - set/update the codec name 175ded255beSTakashi Iwai * @codec: the HDAC device 176ded255beSTakashi Iwai * @name: name string to set 177ded255beSTakashi Iwai * 178ded255beSTakashi Iwai * Returns 0 if the name is set or updated, or a negative error code. 179ded255beSTakashi Iwai */ 180ded255beSTakashi Iwai int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name) 181ded255beSTakashi Iwai { 182ded255beSTakashi Iwai char *newname; 183ded255beSTakashi Iwai 184ded255beSTakashi Iwai if (!name) 185ded255beSTakashi Iwai return 0; 186ded255beSTakashi Iwai newname = kstrdup(name, GFP_KERNEL); 187ded255beSTakashi Iwai if (!newname) 188ded255beSTakashi Iwai return -ENOMEM; 189ded255beSTakashi Iwai kfree(codec->chip_name); 190ded255beSTakashi Iwai codec->chip_name = newname; 191ded255beSTakashi Iwai return 0; 192ded255beSTakashi Iwai } 193ded255beSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_set_chip_name); 194ded255beSTakashi Iwai 195ded255beSTakashi Iwai /** 1964f9e0c38STakashi Iwai * snd_hdac_codec_modalias - give the module alias name 1974f9e0c38STakashi Iwai * @codec: HDAC device 1984f9e0c38STakashi Iwai * @buf: string buffer to store 1994f9e0c38STakashi Iwai * @size: string buffer size 2004f9e0c38STakashi Iwai * 2014f9e0c38STakashi Iwai * Returns the size of string, like snprintf(), or a negative error code. 2024f9e0c38STakashi Iwai */ 2034f9e0c38STakashi Iwai int snd_hdac_codec_modalias(struct hdac_device *codec, char *buf, size_t size) 2044f9e0c38STakashi Iwai { 2054f9e0c38STakashi Iwai return snprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n", 2064f9e0c38STakashi Iwai codec->vendor_id, codec->revision_id, codec->type); 2074f9e0c38STakashi Iwai } 2084f9e0c38STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_codec_modalias); 2094f9e0c38STakashi Iwai 2104f9e0c38STakashi Iwai /** 2117639a06cSTakashi Iwai * snd_hdac_make_cmd - compose a 32bit command word to be sent to the 2127639a06cSTakashi Iwai * HD-audio controller 2137639a06cSTakashi Iwai * @codec: the codec object 2147639a06cSTakashi Iwai * @nid: NID to encode 2157639a06cSTakashi Iwai * @verb: verb to encode 2167639a06cSTakashi Iwai * @parm: parameter to encode 2177639a06cSTakashi Iwai * 2187639a06cSTakashi Iwai * Return an encoded command verb or -1 for error. 2197639a06cSTakashi Iwai */ 2207639a06cSTakashi Iwai unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, 2217639a06cSTakashi Iwai unsigned int verb, unsigned int parm) 2227639a06cSTakashi Iwai { 2237639a06cSTakashi Iwai u32 val, addr; 2247639a06cSTakashi Iwai 2257639a06cSTakashi Iwai addr = codec->addr; 2267639a06cSTakashi Iwai if ((addr & ~0xf) || (nid & ~0x7f) || 2277639a06cSTakashi Iwai (verb & ~0xfff) || (parm & ~0xffff)) { 2287639a06cSTakashi Iwai dev_err(&codec->dev, "out of range cmd %x:%x:%x:%x\n", 2297639a06cSTakashi Iwai addr, nid, verb, parm); 2307639a06cSTakashi Iwai return -1; 2317639a06cSTakashi Iwai } 2327639a06cSTakashi Iwai 2337639a06cSTakashi Iwai val = addr << 28; 2347639a06cSTakashi Iwai val |= (u32)nid << 20; 2357639a06cSTakashi Iwai val |= verb << 8; 2367639a06cSTakashi Iwai val |= parm; 2377639a06cSTakashi Iwai return val; 2387639a06cSTakashi Iwai } 2397639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_make_cmd); 2407639a06cSTakashi Iwai 2417639a06cSTakashi Iwai /** 24205852448STakashi Iwai * snd_hdac_exec_verb - execute an encoded verb 24305852448STakashi Iwai * @codec: the codec object 24405852448STakashi Iwai * @cmd: encoded verb to execute 24505852448STakashi Iwai * @flags: optional flags, pass zero for default 24605852448STakashi Iwai * @res: the pointer to store the result, NULL if running async 24705852448STakashi Iwai * 24805852448STakashi Iwai * Returns zero if successful, or a negative error code. 24905852448STakashi Iwai * 25005852448STakashi Iwai * This calls the exec_verb op when set in hdac_codec. If not, 25105852448STakashi Iwai * call the default snd_hdac_bus_exec_verb(). 25205852448STakashi Iwai */ 25305852448STakashi Iwai int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, 25405852448STakashi Iwai unsigned int flags, unsigned int *res) 25505852448STakashi Iwai { 25605852448STakashi Iwai if (codec->exec_verb) 25705852448STakashi Iwai return codec->exec_verb(codec, cmd, flags, res); 25805852448STakashi Iwai return snd_hdac_bus_exec_verb(codec->bus, codec->addr, cmd, res); 25905852448STakashi Iwai } 26005852448STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_exec_verb); 26105852448STakashi Iwai 26205852448STakashi Iwai 26305852448STakashi Iwai /** 2647639a06cSTakashi Iwai * snd_hdac_read - execute a verb 2657639a06cSTakashi Iwai * @codec: the codec object 2667639a06cSTakashi Iwai * @nid: NID to execute a verb 2677639a06cSTakashi Iwai * @verb: verb to execute 2687639a06cSTakashi Iwai * @parm: parameter for a verb 2697639a06cSTakashi Iwai * @res: the pointer to store the result, NULL if running async 2707639a06cSTakashi Iwai * 2717639a06cSTakashi Iwai * Returns zero if successful, or a negative error code. 2727639a06cSTakashi Iwai */ 2737639a06cSTakashi Iwai int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, 2747639a06cSTakashi Iwai unsigned int verb, unsigned int parm, unsigned int *res) 2757639a06cSTakashi Iwai { 2767639a06cSTakashi Iwai unsigned int cmd = snd_hdac_make_cmd(codec, nid, verb, parm); 2777639a06cSTakashi Iwai 27805852448STakashi Iwai return snd_hdac_exec_verb(codec, cmd, 0, res); 2797639a06cSTakashi Iwai } 2807639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_read); 2817639a06cSTakashi Iwai 2827639a06cSTakashi Iwai /** 28301ed3c06STakashi Iwai * _snd_hdac_read_parm - read a parmeter 2847639a06cSTakashi Iwai * 28501ed3c06STakashi Iwai * This function returns zero or an error unlike snd_hdac_read_parm(). 2867639a06cSTakashi Iwai */ 28701ed3c06STakashi Iwai int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm, 28801ed3c06STakashi Iwai unsigned int *res) 2897639a06cSTakashi Iwai { 29001ed3c06STakashi Iwai unsigned int cmd; 2917639a06cSTakashi Iwai 29201ed3c06STakashi Iwai cmd = snd_hdac_regmap_encode_verb(nid, AC_VERB_PARAMETERS) | parm; 29301ed3c06STakashi Iwai return snd_hdac_regmap_read_raw(codec, cmd, res); 2947639a06cSTakashi Iwai } 29501ed3c06STakashi Iwai EXPORT_SYMBOL_GPL(_snd_hdac_read_parm); 2967639a06cSTakashi Iwai 2977639a06cSTakashi Iwai /** 2989ba17b4dSTakashi Iwai * snd_hdac_read_parm_uncached - read a codec parameter without caching 2997639a06cSTakashi Iwai * @codec: the codec object 3007639a06cSTakashi Iwai * @nid: NID to read a parameter 3017639a06cSTakashi Iwai * @parm: parameter to read 3027639a06cSTakashi Iwai * 3037639a06cSTakashi Iwai * Returns -1 for error. If you need to distinguish the error more 3047639a06cSTakashi Iwai * strictly, use snd_hdac_read() directly. 3057639a06cSTakashi Iwai */ 3069ba17b4dSTakashi Iwai int snd_hdac_read_parm_uncached(struct hdac_device *codec, hda_nid_t nid, 3079ba17b4dSTakashi Iwai int parm) 3087639a06cSTakashi Iwai { 3093194ed49STakashi Iwai unsigned int cmd, val; 3107639a06cSTakashi Iwai 3113194ed49STakashi Iwai cmd = snd_hdac_regmap_encode_verb(nid, AC_VERB_PARAMETERS) | parm; 3123194ed49STakashi Iwai if (snd_hdac_regmap_read_raw_uncached(codec, cmd, &val) < 0) 3133194ed49STakashi Iwai return -1; 3147639a06cSTakashi Iwai return val; 3157639a06cSTakashi Iwai } 3169ba17b4dSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_read_parm_uncached); 3179ba17b4dSTakashi Iwai 3189ba17b4dSTakashi Iwai /** 319faa75f8aSTakashi Iwai * snd_hdac_override_parm - override read-only parameters 320faa75f8aSTakashi Iwai * @codec: the codec object 321faa75f8aSTakashi Iwai * @nid: NID for the parameter 322faa75f8aSTakashi Iwai * @parm: the parameter to change 323faa75f8aSTakashi Iwai * @val: the parameter value to overwrite 324faa75f8aSTakashi Iwai */ 325faa75f8aSTakashi Iwai int snd_hdac_override_parm(struct hdac_device *codec, hda_nid_t nid, 326faa75f8aSTakashi Iwai unsigned int parm, unsigned int val) 327faa75f8aSTakashi Iwai { 328faa75f8aSTakashi Iwai unsigned int verb = (AC_VERB_PARAMETERS << 8) | (nid << 20) | parm; 329faa75f8aSTakashi Iwai int err; 330faa75f8aSTakashi Iwai 331faa75f8aSTakashi Iwai if (!codec->regmap) 332faa75f8aSTakashi Iwai return -EINVAL; 333faa75f8aSTakashi Iwai 334faa75f8aSTakashi Iwai codec->caps_overwriting = true; 335faa75f8aSTakashi Iwai err = snd_hdac_regmap_write_raw(codec, verb, val); 336faa75f8aSTakashi Iwai codec->caps_overwriting = false; 337faa75f8aSTakashi Iwai return err; 338faa75f8aSTakashi Iwai } 339faa75f8aSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_override_parm); 3407639a06cSTakashi Iwai 3417639a06cSTakashi Iwai /** 3427639a06cSTakashi Iwai * snd_hdac_get_sub_nodes - get start NID and number of subtree nodes 3437639a06cSTakashi Iwai * @codec: the codec object 3447639a06cSTakashi Iwai * @nid: NID to inspect 3457639a06cSTakashi Iwai * @start_id: the pointer to store the starting NID 3467639a06cSTakashi Iwai * 3477639a06cSTakashi Iwai * Returns the number of subtree nodes or zero if not found. 3489ba17b4dSTakashi Iwai * This function reads parameters always without caching. 3497639a06cSTakashi Iwai */ 3507639a06cSTakashi Iwai int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, 3517639a06cSTakashi Iwai hda_nid_t *start_id) 3527639a06cSTakashi Iwai { 3537639a06cSTakashi Iwai unsigned int parm; 3547639a06cSTakashi Iwai 3559ba17b4dSTakashi Iwai parm = snd_hdac_read_parm_uncached(codec, nid, AC_PAR_NODE_COUNT); 3567639a06cSTakashi Iwai if (parm == -1) { 3577639a06cSTakashi Iwai *start_id = 0; 3587639a06cSTakashi Iwai return 0; 3597639a06cSTakashi Iwai } 3607639a06cSTakashi Iwai *start_id = (parm >> 16) & 0x7fff; 3617639a06cSTakashi Iwai return (int)(parm & 0x7fff); 3627639a06cSTakashi Iwai } 3637639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_get_sub_nodes); 3647639a06cSTakashi Iwai 3657639a06cSTakashi Iwai /* 3667639a06cSTakashi Iwai * look for an AFG and MFG nodes 3677639a06cSTakashi Iwai */ 3687639a06cSTakashi Iwai static void setup_fg_nodes(struct hdac_device *codec) 3697639a06cSTakashi Iwai { 3707639a06cSTakashi Iwai int i, total_nodes, function_id; 3717639a06cSTakashi Iwai hda_nid_t nid; 3727639a06cSTakashi Iwai 3737639a06cSTakashi Iwai total_nodes = snd_hdac_get_sub_nodes(codec, AC_NODE_ROOT, &nid); 3747639a06cSTakashi Iwai for (i = 0; i < total_nodes; i++, nid++) { 3757639a06cSTakashi Iwai function_id = snd_hdac_read_parm(codec, nid, 3767639a06cSTakashi Iwai AC_PAR_FUNCTION_TYPE); 3777639a06cSTakashi Iwai switch (function_id & 0xff) { 3787639a06cSTakashi Iwai case AC_GRP_AUDIO_FUNCTION: 3797639a06cSTakashi Iwai codec->afg = nid; 3807639a06cSTakashi Iwai codec->afg_function_id = function_id & 0xff; 3817639a06cSTakashi Iwai codec->afg_unsol = (function_id >> 8) & 1; 3827639a06cSTakashi Iwai break; 3837639a06cSTakashi Iwai case AC_GRP_MODEM_FUNCTION: 3847639a06cSTakashi Iwai codec->mfg = nid; 3857639a06cSTakashi Iwai codec->mfg_function_id = function_id & 0xff; 3867639a06cSTakashi Iwai codec->mfg_unsol = (function_id >> 8) & 1; 3877639a06cSTakashi Iwai break; 3887639a06cSTakashi Iwai default: 3897639a06cSTakashi Iwai break; 3907639a06cSTakashi Iwai } 3917639a06cSTakashi Iwai } 3927639a06cSTakashi Iwai } 3937639a06cSTakashi Iwai 3947639a06cSTakashi Iwai /** 3957639a06cSTakashi Iwai * snd_hdac_refresh_widgets - Reset the widget start/end nodes 3967639a06cSTakashi Iwai * @codec: the codec object 3979780ded3STakashi Iwai * @sysfs: re-initialize sysfs tree, too 3987639a06cSTakashi Iwai */ 3999780ded3STakashi Iwai int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs) 4007639a06cSTakashi Iwai { 4017639a06cSTakashi Iwai hda_nid_t start_nid; 402*98482377SEvan Green int nums, err = 0; 4037639a06cSTakashi Iwai 404*98482377SEvan Green /* 405*98482377SEvan Green * Serialize against multiple threads trying to update the sysfs 406*98482377SEvan Green * widgets array. 407*98482377SEvan Green */ 408*98482377SEvan Green mutex_lock(&codec->widget_lock); 4097639a06cSTakashi Iwai nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid); 4107639a06cSTakashi Iwai if (!start_nid || nums <= 0 || nums >= 0xff) { 4117639a06cSTakashi Iwai dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n", 4127639a06cSTakashi Iwai codec->afg); 413*98482377SEvan Green err = -EINVAL; 414*98482377SEvan Green goto unlock; 4157639a06cSTakashi Iwai } 4167639a06cSTakashi Iwai 4179780ded3STakashi Iwai if (sysfs) { 4189780ded3STakashi Iwai err = hda_widget_sysfs_reinit(codec, start_nid, nums); 4199780ded3STakashi Iwai if (err < 0) 420*98482377SEvan Green goto unlock; 4219780ded3STakashi Iwai } 4229780ded3STakashi Iwai 4237639a06cSTakashi Iwai codec->num_nodes = nums; 4247639a06cSTakashi Iwai codec->start_nid = start_nid; 4257639a06cSTakashi Iwai codec->end_nid = start_nid + nums; 426*98482377SEvan Green unlock: 427*98482377SEvan Green mutex_unlock(&codec->widget_lock); 428*98482377SEvan Green return err; 4297639a06cSTakashi Iwai } 4307639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); 4317639a06cSTakashi Iwai 4327639a06cSTakashi Iwai /* return CONNLIST_LEN parameter of the given widget */ 4337639a06cSTakashi Iwai static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid) 4347639a06cSTakashi Iwai { 4357639a06cSTakashi Iwai unsigned int wcaps = get_wcaps(codec, nid); 4367639a06cSTakashi Iwai unsigned int parm; 4377639a06cSTakashi Iwai 4387639a06cSTakashi Iwai if (!(wcaps & AC_WCAP_CONN_LIST) && 4397639a06cSTakashi Iwai get_wcaps_type(wcaps) != AC_WID_VOL_KNB) 4407639a06cSTakashi Iwai return 0; 4417639a06cSTakashi Iwai 4427639a06cSTakashi Iwai parm = snd_hdac_read_parm(codec, nid, AC_PAR_CONNLIST_LEN); 4437639a06cSTakashi Iwai if (parm == -1) 4447639a06cSTakashi Iwai parm = 0; 4457639a06cSTakashi Iwai return parm; 4467639a06cSTakashi Iwai } 4477639a06cSTakashi Iwai 4487639a06cSTakashi Iwai /** 4497639a06cSTakashi Iwai * snd_hdac_get_connections - get a widget connection list 4507639a06cSTakashi Iwai * @codec: the codec object 4517639a06cSTakashi Iwai * @nid: NID 4527639a06cSTakashi Iwai * @conn_list: the array to store the results, can be NULL 4537639a06cSTakashi Iwai * @max_conns: the max size of the given array 4547639a06cSTakashi Iwai * 4557639a06cSTakashi Iwai * Returns the number of connected widgets, zero for no connection, or a 4567639a06cSTakashi Iwai * negative error code. When the number of elements don't fit with the 4577639a06cSTakashi Iwai * given array size, it returns -ENOSPC. 4587639a06cSTakashi Iwai * 4597639a06cSTakashi Iwai * When @conn_list is NULL, it just checks the number of connections. 4607639a06cSTakashi Iwai */ 4617639a06cSTakashi Iwai int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, 4627639a06cSTakashi Iwai hda_nid_t *conn_list, int max_conns) 4637639a06cSTakashi Iwai { 4647639a06cSTakashi Iwai unsigned int parm; 4657639a06cSTakashi Iwai int i, conn_len, conns, err; 4667639a06cSTakashi Iwai unsigned int shift, num_elems, mask; 4677639a06cSTakashi Iwai hda_nid_t prev_nid; 4687639a06cSTakashi Iwai int null_count = 0; 4697639a06cSTakashi Iwai 4707639a06cSTakashi Iwai parm = get_num_conns(codec, nid); 4717639a06cSTakashi Iwai if (!parm) 4727639a06cSTakashi Iwai return 0; 4737639a06cSTakashi Iwai 4747639a06cSTakashi Iwai if (parm & AC_CLIST_LONG) { 4757639a06cSTakashi Iwai /* long form */ 4767639a06cSTakashi Iwai shift = 16; 4777639a06cSTakashi Iwai num_elems = 2; 4787639a06cSTakashi Iwai } else { 4797639a06cSTakashi Iwai /* short form */ 4807639a06cSTakashi Iwai shift = 8; 4817639a06cSTakashi Iwai num_elems = 4; 4827639a06cSTakashi Iwai } 4837639a06cSTakashi Iwai conn_len = parm & AC_CLIST_LENGTH; 4847639a06cSTakashi Iwai mask = (1 << (shift-1)) - 1; 4857639a06cSTakashi Iwai 4867639a06cSTakashi Iwai if (!conn_len) 4877639a06cSTakashi Iwai return 0; /* no connection */ 4887639a06cSTakashi Iwai 4897639a06cSTakashi Iwai if (conn_len == 1) { 4907639a06cSTakashi Iwai /* single connection */ 4917639a06cSTakashi Iwai err = snd_hdac_read(codec, nid, AC_VERB_GET_CONNECT_LIST, 0, 4927639a06cSTakashi Iwai &parm); 4937639a06cSTakashi Iwai if (err < 0) 4947639a06cSTakashi Iwai return err; 4957639a06cSTakashi Iwai if (conn_list) 4967639a06cSTakashi Iwai conn_list[0] = parm & mask; 4977639a06cSTakashi Iwai return 1; 4987639a06cSTakashi Iwai } 4997639a06cSTakashi Iwai 5007639a06cSTakashi Iwai /* multi connection */ 5017639a06cSTakashi Iwai conns = 0; 5027639a06cSTakashi Iwai prev_nid = 0; 5037639a06cSTakashi Iwai for (i = 0; i < conn_len; i++) { 5047639a06cSTakashi Iwai int range_val; 5057639a06cSTakashi Iwai hda_nid_t val, n; 5067639a06cSTakashi Iwai 5077639a06cSTakashi Iwai if (i % num_elems == 0) { 5087639a06cSTakashi Iwai err = snd_hdac_read(codec, nid, 5097639a06cSTakashi Iwai AC_VERB_GET_CONNECT_LIST, i, 5107639a06cSTakashi Iwai &parm); 5117639a06cSTakashi Iwai if (err < 0) 5127639a06cSTakashi Iwai return -EIO; 5137639a06cSTakashi Iwai } 5147639a06cSTakashi Iwai range_val = !!(parm & (1 << (shift-1))); /* ranges */ 5157639a06cSTakashi Iwai val = parm & mask; 5167639a06cSTakashi Iwai if (val == 0 && null_count++) { /* no second chance */ 5177639a06cSTakashi Iwai dev_dbg(&codec->dev, 5187639a06cSTakashi Iwai "invalid CONNECT_LIST verb %x[%i]:%x\n", 5197639a06cSTakashi Iwai nid, i, parm); 5207639a06cSTakashi Iwai return 0; 5217639a06cSTakashi Iwai } 5227639a06cSTakashi Iwai parm >>= shift; 5237639a06cSTakashi Iwai if (range_val) { 5247639a06cSTakashi Iwai /* ranges between the previous and this one */ 5257639a06cSTakashi Iwai if (!prev_nid || prev_nid >= val) { 5267639a06cSTakashi Iwai dev_warn(&codec->dev, 5277639a06cSTakashi Iwai "invalid dep_range_val %x:%x\n", 5287639a06cSTakashi Iwai prev_nid, val); 5297639a06cSTakashi Iwai continue; 5307639a06cSTakashi Iwai } 5317639a06cSTakashi Iwai for (n = prev_nid + 1; n <= val; n++) { 5327639a06cSTakashi Iwai if (conn_list) { 5337639a06cSTakashi Iwai if (conns >= max_conns) 5347639a06cSTakashi Iwai return -ENOSPC; 5357639a06cSTakashi Iwai conn_list[conns] = n; 5367639a06cSTakashi Iwai } 5377639a06cSTakashi Iwai conns++; 5387639a06cSTakashi Iwai } 5397639a06cSTakashi Iwai } else { 5407639a06cSTakashi Iwai if (conn_list) { 5417639a06cSTakashi Iwai if (conns >= max_conns) 5427639a06cSTakashi Iwai return -ENOSPC; 5437639a06cSTakashi Iwai conn_list[conns] = val; 5447639a06cSTakashi Iwai } 5457639a06cSTakashi Iwai conns++; 5467639a06cSTakashi Iwai } 5477639a06cSTakashi Iwai prev_nid = val; 5487639a06cSTakashi Iwai } 5497639a06cSTakashi Iwai return conns; 5507639a06cSTakashi Iwai } 5517639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_get_connections); 5527639a06cSTakashi Iwai 5537639a06cSTakashi Iwai #ifdef CONFIG_PM 5547639a06cSTakashi Iwai /** 555664c7155STakashi Iwai * snd_hdac_power_up - power up the codec 5567639a06cSTakashi Iwai * @codec: the codec object 557664c7155STakashi Iwai * 558664c7155STakashi Iwai * This function calls the runtime PM helper to power up the given codec. 559664c7155STakashi Iwai * Unlike snd_hdac_power_up_pm(), you should call this only for the code 560664c7155STakashi Iwai * path that isn't included in PM path. Otherwise it gets stuck. 561fbce23a0STakashi Iwai * 562fbce23a0STakashi Iwai * Returns zero if successful, or a negative error code. 5637639a06cSTakashi Iwai */ 564fbce23a0STakashi Iwai int snd_hdac_power_up(struct hdac_device *codec) 5657639a06cSTakashi Iwai { 566fbce23a0STakashi Iwai return pm_runtime_get_sync(&codec->dev); 5677639a06cSTakashi Iwai } 5687639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_up); 5697639a06cSTakashi Iwai 5707639a06cSTakashi Iwai /** 571664c7155STakashi Iwai * snd_hdac_power_down - power down the codec 5727639a06cSTakashi Iwai * @codec: the codec object 573fbce23a0STakashi Iwai * 574fbce23a0STakashi Iwai * Returns zero if successful, or a negative error code. 5757639a06cSTakashi Iwai */ 576fbce23a0STakashi Iwai int snd_hdac_power_down(struct hdac_device *codec) 5777639a06cSTakashi Iwai { 5787639a06cSTakashi Iwai struct device *dev = &codec->dev; 5797639a06cSTakashi Iwai 5807639a06cSTakashi Iwai pm_runtime_mark_last_busy(dev); 581fbce23a0STakashi Iwai return pm_runtime_put_autosuspend(dev); 5827639a06cSTakashi Iwai } 5837639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_down); 584c3aeda62STakashi Iwai 585c3aeda62STakashi Iwai /** 586c3aeda62STakashi Iwai * snd_hdac_power_up_pm - power up the codec 587c3aeda62STakashi Iwai * @codec: the codec object 588c3aeda62STakashi Iwai * 589c3aeda62STakashi Iwai * This function can be called in a recursive code path like init code 590c3aeda62STakashi Iwai * which may be called by PM suspend/resume again. OTOH, if a power-up 591c3aeda62STakashi Iwai * call must wake up the sleeper (e.g. in a kctl callback), use 592c3aeda62STakashi Iwai * snd_hdac_power_up() instead. 593fbce23a0STakashi Iwai * 594fbce23a0STakashi Iwai * Returns zero if successful, or a negative error code. 595c3aeda62STakashi Iwai */ 596fbce23a0STakashi Iwai int snd_hdac_power_up_pm(struct hdac_device *codec) 597c3aeda62STakashi Iwai { 598c3aeda62STakashi Iwai if (!atomic_inc_not_zero(&codec->in_pm)) 599fbce23a0STakashi Iwai return snd_hdac_power_up(codec); 600fbce23a0STakashi Iwai return 0; 601c3aeda62STakashi Iwai } 602c3aeda62STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm); 603c3aeda62STakashi Iwai 604fc4f000bSTakashi Iwai /* like snd_hdac_power_up_pm(), but only increment the pm count when 605fc4f000bSTakashi Iwai * already powered up. Returns -1 if not powered up, 1 if incremented 606fc4f000bSTakashi Iwai * or 0 if unchanged. Only used in hdac_regmap.c 607fc4f000bSTakashi Iwai */ 608fc4f000bSTakashi Iwai int snd_hdac_keep_power_up(struct hdac_device *codec) 609fc4f000bSTakashi Iwai { 610fc4f000bSTakashi Iwai if (!atomic_inc_not_zero(&codec->in_pm)) { 611fc4f000bSTakashi Iwai int ret = pm_runtime_get_if_in_use(&codec->dev); 612fc4f000bSTakashi Iwai if (!ret) 613fc4f000bSTakashi Iwai return -1; 614fc4f000bSTakashi Iwai if (ret < 0) 615fc4f000bSTakashi Iwai return 0; 616fc4f000bSTakashi Iwai } 617fc4f000bSTakashi Iwai return 1; 618fc4f000bSTakashi Iwai } 619fc4f000bSTakashi Iwai 620c3aeda62STakashi Iwai /** 621c3aeda62STakashi Iwai * snd_hdac_power_down_pm - power down the codec 622c3aeda62STakashi Iwai * @codec: the codec object 623c3aeda62STakashi Iwai * 624c3aeda62STakashi Iwai * Like snd_hdac_power_up_pm(), this function is used in a recursive 625c3aeda62STakashi Iwai * code path like init code which may be called by PM suspend/resume again. 626fbce23a0STakashi Iwai * 627fbce23a0STakashi Iwai * Returns zero if successful, or a negative error code. 628c3aeda62STakashi Iwai */ 629fbce23a0STakashi Iwai int snd_hdac_power_down_pm(struct hdac_device *codec) 630c3aeda62STakashi Iwai { 631c3aeda62STakashi Iwai if (atomic_dec_if_positive(&codec->in_pm) < 0) 632fbce23a0STakashi Iwai return snd_hdac_power_down(codec); 633fbce23a0STakashi Iwai return 0; 634c3aeda62STakashi Iwai } 635c3aeda62STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm); 6367639a06cSTakashi Iwai #endif 6377639a06cSTakashi Iwai 6387639a06cSTakashi Iwai /* codec vendor labels */ 6397639a06cSTakashi Iwai struct hda_vendor_id { 6407639a06cSTakashi Iwai unsigned int id; 6417639a06cSTakashi Iwai const char *name; 6427639a06cSTakashi Iwai }; 6437639a06cSTakashi Iwai 6447639a06cSTakashi Iwai static struct hda_vendor_id hda_vendor_ids[] = { 6457639a06cSTakashi Iwai { 0x1002, "ATI" }, 6467639a06cSTakashi Iwai { 0x1013, "Cirrus Logic" }, 6477639a06cSTakashi Iwai { 0x1057, "Motorola" }, 6487639a06cSTakashi Iwai { 0x1095, "Silicon Image" }, 6497639a06cSTakashi Iwai { 0x10de, "Nvidia" }, 6507639a06cSTakashi Iwai { 0x10ec, "Realtek" }, 6517639a06cSTakashi Iwai { 0x1102, "Creative" }, 6527639a06cSTakashi Iwai { 0x1106, "VIA" }, 6537639a06cSTakashi Iwai { 0x111d, "IDT" }, 6547639a06cSTakashi Iwai { 0x11c1, "LSI" }, 6557639a06cSTakashi Iwai { 0x11d4, "Analog Devices" }, 6567639a06cSTakashi Iwai { 0x13f6, "C-Media" }, 6577639a06cSTakashi Iwai { 0x14f1, "Conexant" }, 6587639a06cSTakashi Iwai { 0x17e8, "Chrontel" }, 6597639a06cSTakashi Iwai { 0x1854, "LG" }, 6607639a06cSTakashi Iwai { 0x1aec, "Wolfson Microelectronics" }, 6617639a06cSTakashi Iwai { 0x1af4, "QEMU" }, 6627639a06cSTakashi Iwai { 0x434d, "C-Media" }, 6637639a06cSTakashi Iwai { 0x8086, "Intel" }, 6647639a06cSTakashi Iwai { 0x8384, "SigmaTel" }, 6657639a06cSTakashi Iwai {} /* terminator */ 6667639a06cSTakashi Iwai }; 6677639a06cSTakashi Iwai 6687639a06cSTakashi Iwai /* store the codec vendor name */ 6697639a06cSTakashi Iwai static int get_codec_vendor_name(struct hdac_device *codec) 6707639a06cSTakashi Iwai { 6717639a06cSTakashi Iwai const struct hda_vendor_id *c; 6727639a06cSTakashi Iwai u16 vendor_id = codec->vendor_id >> 16; 6737639a06cSTakashi Iwai 6747639a06cSTakashi Iwai for (c = hda_vendor_ids; c->id; c++) { 6757639a06cSTakashi Iwai if (c->id == vendor_id) { 6767639a06cSTakashi Iwai codec->vendor_name = kstrdup(c->name, GFP_KERNEL); 6777639a06cSTakashi Iwai return codec->vendor_name ? 0 : -ENOMEM; 6787639a06cSTakashi Iwai } 6797639a06cSTakashi Iwai } 6807639a06cSTakashi Iwai 6817639a06cSTakashi Iwai codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id); 6827639a06cSTakashi Iwai return codec->vendor_name ? 0 : -ENOMEM; 6837639a06cSTakashi Iwai } 684b7d023e1STakashi Iwai 685b7d023e1STakashi Iwai /* 686b7d023e1STakashi Iwai * stream formats 687b7d023e1STakashi Iwai */ 688b7d023e1STakashi Iwai struct hda_rate_tbl { 689b7d023e1STakashi Iwai unsigned int hz; 690b7d023e1STakashi Iwai unsigned int alsa_bits; 691b7d023e1STakashi Iwai unsigned int hda_fmt; 692b7d023e1STakashi Iwai }; 693b7d023e1STakashi Iwai 694b7d023e1STakashi Iwai /* rate = base * mult / div */ 695b7d023e1STakashi Iwai #define HDA_RATE(base, mult, div) \ 696b7d023e1STakashi Iwai (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ 697b7d023e1STakashi Iwai (((div) - 1) << AC_FMT_DIV_SHIFT)) 698b7d023e1STakashi Iwai 699b7d023e1STakashi Iwai static struct hda_rate_tbl rate_bits[] = { 700b7d023e1STakashi Iwai /* rate in Hz, ALSA rate bitmask, HDA format value */ 701b7d023e1STakashi Iwai 702b7d023e1STakashi Iwai /* autodetected value used in snd_hda_query_supported_pcm */ 703b7d023e1STakashi Iwai { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, 704b7d023e1STakashi Iwai { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, 705b7d023e1STakashi Iwai { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, 706b7d023e1STakashi Iwai { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, 707b7d023e1STakashi Iwai { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, 708b7d023e1STakashi Iwai { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, 709b7d023e1STakashi Iwai { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, 710b7d023e1STakashi Iwai { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, 711b7d023e1STakashi Iwai { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, 712b7d023e1STakashi Iwai { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, 713b7d023e1STakashi Iwai { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, 714b7d023e1STakashi Iwai #define AC_PAR_PCM_RATE_BITS 11 715b7d023e1STakashi Iwai /* up to bits 10, 384kHZ isn't supported properly */ 716b7d023e1STakashi Iwai 717b7d023e1STakashi Iwai /* not autodetected value */ 718b7d023e1STakashi Iwai { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, 719b7d023e1STakashi Iwai 720b7d023e1STakashi Iwai { 0 } /* terminator */ 721b7d023e1STakashi Iwai }; 722b7d023e1STakashi Iwai 723b7d023e1STakashi Iwai /** 724b7d023e1STakashi Iwai * snd_hdac_calc_stream_format - calculate the format bitset 725b7d023e1STakashi Iwai * @rate: the sample rate 726b7d023e1STakashi Iwai * @channels: the number of channels 727b7d023e1STakashi Iwai * @format: the PCM format (SNDRV_PCM_FORMAT_XXX) 728b7d023e1STakashi Iwai * @maxbps: the max. bps 729b7d023e1STakashi Iwai * @spdif_ctls: HD-audio SPDIF status bits (0 if irrelevant) 730b7d023e1STakashi Iwai * 731b7d023e1STakashi Iwai * Calculate the format bitset from the given rate, channels and th PCM format. 732b7d023e1STakashi Iwai * 733b7d023e1STakashi Iwai * Return zero if invalid. 734b7d023e1STakashi Iwai */ 735b7d023e1STakashi Iwai unsigned int snd_hdac_calc_stream_format(unsigned int rate, 736b7d023e1STakashi Iwai unsigned int channels, 737a6ea5fe9STakashi Iwai snd_pcm_format_t format, 738b7d023e1STakashi Iwai unsigned int maxbps, 739b7d023e1STakashi Iwai unsigned short spdif_ctls) 740b7d023e1STakashi Iwai { 741b7d023e1STakashi Iwai int i; 742b7d023e1STakashi Iwai unsigned int val = 0; 743b7d023e1STakashi Iwai 744b7d023e1STakashi Iwai for (i = 0; rate_bits[i].hz; i++) 745b7d023e1STakashi Iwai if (rate_bits[i].hz == rate) { 746b7d023e1STakashi Iwai val = rate_bits[i].hda_fmt; 747b7d023e1STakashi Iwai break; 748b7d023e1STakashi Iwai } 749b7d023e1STakashi Iwai if (!rate_bits[i].hz) 750b7d023e1STakashi Iwai return 0; 751b7d023e1STakashi Iwai 752b7d023e1STakashi Iwai if (channels == 0 || channels > 8) 753b7d023e1STakashi Iwai return 0; 754b7d023e1STakashi Iwai val |= channels - 1; 755b7d023e1STakashi Iwai 756b7d023e1STakashi Iwai switch (snd_pcm_format_width(format)) { 757b7d023e1STakashi Iwai case 8: 758b7d023e1STakashi Iwai val |= AC_FMT_BITS_8; 759b7d023e1STakashi Iwai break; 760b7d023e1STakashi Iwai case 16: 761b7d023e1STakashi Iwai val |= AC_FMT_BITS_16; 762b7d023e1STakashi Iwai break; 763b7d023e1STakashi Iwai case 20: 764b7d023e1STakashi Iwai case 24: 765b7d023e1STakashi Iwai case 32: 766b7d023e1STakashi Iwai if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) 767b7d023e1STakashi Iwai val |= AC_FMT_BITS_32; 768b7d023e1STakashi Iwai else if (maxbps >= 24) 769b7d023e1STakashi Iwai val |= AC_FMT_BITS_24; 770b7d023e1STakashi Iwai else 771b7d023e1STakashi Iwai val |= AC_FMT_BITS_20; 772b7d023e1STakashi Iwai break; 773b7d023e1STakashi Iwai default: 774b7d023e1STakashi Iwai return 0; 775b7d023e1STakashi Iwai } 776b7d023e1STakashi Iwai 777b7d023e1STakashi Iwai if (spdif_ctls & AC_DIG1_NONAUDIO) 778b7d023e1STakashi Iwai val |= AC_FMT_TYPE_NON_PCM; 779b7d023e1STakashi Iwai 780b7d023e1STakashi Iwai return val; 781b7d023e1STakashi Iwai } 782b7d023e1STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_calc_stream_format); 783b7d023e1STakashi Iwai 784b7d023e1STakashi Iwai static unsigned int query_pcm_param(struct hdac_device *codec, hda_nid_t nid) 785b7d023e1STakashi Iwai { 786b7d023e1STakashi Iwai unsigned int val = 0; 787b7d023e1STakashi Iwai 788b7d023e1STakashi Iwai if (nid != codec->afg && 789b7d023e1STakashi Iwai (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) 790b7d023e1STakashi Iwai val = snd_hdac_read_parm(codec, nid, AC_PAR_PCM); 791b7d023e1STakashi Iwai if (!val || val == -1) 792b7d023e1STakashi Iwai val = snd_hdac_read_parm(codec, codec->afg, AC_PAR_PCM); 793b7d023e1STakashi Iwai if (!val || val == -1) 794b7d023e1STakashi Iwai return 0; 795b7d023e1STakashi Iwai return val; 796b7d023e1STakashi Iwai } 797b7d023e1STakashi Iwai 798b7d023e1STakashi Iwai static unsigned int query_stream_param(struct hdac_device *codec, hda_nid_t nid) 799b7d023e1STakashi Iwai { 800b7d023e1STakashi Iwai unsigned int streams = snd_hdac_read_parm(codec, nid, AC_PAR_STREAM); 801b7d023e1STakashi Iwai 802b7d023e1STakashi Iwai if (!streams || streams == -1) 803b7d023e1STakashi Iwai streams = snd_hdac_read_parm(codec, codec->afg, AC_PAR_STREAM); 804b7d023e1STakashi Iwai if (!streams || streams == -1) 805b7d023e1STakashi Iwai return 0; 806b7d023e1STakashi Iwai return streams; 807b7d023e1STakashi Iwai } 808b7d023e1STakashi Iwai 809b7d023e1STakashi Iwai /** 810b7d023e1STakashi Iwai * snd_hdac_query_supported_pcm - query the supported PCM rates and formats 811b7d023e1STakashi Iwai * @codec: the codec object 812b7d023e1STakashi Iwai * @nid: NID to query 813b7d023e1STakashi Iwai * @ratesp: the pointer to store the detected rate bitflags 814b7d023e1STakashi Iwai * @formatsp: the pointer to store the detected formats 815b7d023e1STakashi Iwai * @bpsp: the pointer to store the detected format widths 816b7d023e1STakashi Iwai * 817b7d023e1STakashi Iwai * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp 818b7d023e1STakashi Iwai * or @bsps argument is ignored. 819b7d023e1STakashi Iwai * 820b7d023e1STakashi Iwai * Returns 0 if successful, otherwise a negative error code. 821b7d023e1STakashi Iwai */ 822b7d023e1STakashi Iwai int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid, 823b7d023e1STakashi Iwai u32 *ratesp, u64 *formatsp, unsigned int *bpsp) 824b7d023e1STakashi Iwai { 825b7d023e1STakashi Iwai unsigned int i, val, wcaps; 826b7d023e1STakashi Iwai 827b7d023e1STakashi Iwai wcaps = get_wcaps(codec, nid); 828b7d023e1STakashi Iwai val = query_pcm_param(codec, nid); 829b7d023e1STakashi Iwai 830b7d023e1STakashi Iwai if (ratesp) { 831b7d023e1STakashi Iwai u32 rates = 0; 832b7d023e1STakashi Iwai for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) { 833b7d023e1STakashi Iwai if (val & (1 << i)) 834b7d023e1STakashi Iwai rates |= rate_bits[i].alsa_bits; 835b7d023e1STakashi Iwai } 836b7d023e1STakashi Iwai if (rates == 0) { 837b7d023e1STakashi Iwai dev_err(&codec->dev, 838b7d023e1STakashi Iwai "rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)\n", 839b7d023e1STakashi Iwai nid, val, 840b7d023e1STakashi Iwai (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0); 841b7d023e1STakashi Iwai return -EIO; 842b7d023e1STakashi Iwai } 843b7d023e1STakashi Iwai *ratesp = rates; 844b7d023e1STakashi Iwai } 845b7d023e1STakashi Iwai 846b7d023e1STakashi Iwai if (formatsp || bpsp) { 847b7d023e1STakashi Iwai u64 formats = 0; 848b7d023e1STakashi Iwai unsigned int streams, bps; 849b7d023e1STakashi Iwai 850b7d023e1STakashi Iwai streams = query_stream_param(codec, nid); 851b7d023e1STakashi Iwai if (!streams) 852b7d023e1STakashi Iwai return -EIO; 853b7d023e1STakashi Iwai 854b7d023e1STakashi Iwai bps = 0; 855b7d023e1STakashi Iwai if (streams & AC_SUPFMT_PCM) { 856b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_8) { 857b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_U8; 858b7d023e1STakashi Iwai bps = 8; 859b7d023e1STakashi Iwai } 860b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_16) { 861b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_S16_LE; 862b7d023e1STakashi Iwai bps = 16; 863b7d023e1STakashi Iwai } 864b7d023e1STakashi Iwai if (wcaps & AC_WCAP_DIGITAL) { 865b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_32) 866b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; 867b7d023e1STakashi Iwai if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24)) 868b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_S32_LE; 869b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_24) 870b7d023e1STakashi Iwai bps = 24; 871b7d023e1STakashi Iwai else if (val & AC_SUPPCM_BITS_20) 872b7d023e1STakashi Iwai bps = 20; 873b7d023e1STakashi Iwai } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24| 874b7d023e1STakashi Iwai AC_SUPPCM_BITS_32)) { 875b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_S32_LE; 876b7d023e1STakashi Iwai if (val & AC_SUPPCM_BITS_32) 877b7d023e1STakashi Iwai bps = 32; 878b7d023e1STakashi Iwai else if (val & AC_SUPPCM_BITS_24) 879b7d023e1STakashi Iwai bps = 24; 880b7d023e1STakashi Iwai else if (val & AC_SUPPCM_BITS_20) 881b7d023e1STakashi Iwai bps = 20; 882b7d023e1STakashi Iwai } 883b7d023e1STakashi Iwai } 884b7d023e1STakashi Iwai #if 0 /* FIXME: CS4206 doesn't work, which is the only codec supporting float */ 885b7d023e1STakashi Iwai if (streams & AC_SUPFMT_FLOAT32) { 886b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_FLOAT_LE; 887b7d023e1STakashi Iwai if (!bps) 888b7d023e1STakashi Iwai bps = 32; 889b7d023e1STakashi Iwai } 890b7d023e1STakashi Iwai #endif 891b7d023e1STakashi Iwai if (streams == AC_SUPFMT_AC3) { 892b7d023e1STakashi Iwai /* should be exclusive */ 893b7d023e1STakashi Iwai /* temporary hack: we have still no proper support 894b7d023e1STakashi Iwai * for the direct AC3 stream... 895b7d023e1STakashi Iwai */ 896b7d023e1STakashi Iwai formats |= SNDRV_PCM_FMTBIT_U8; 897b7d023e1STakashi Iwai bps = 8; 898b7d023e1STakashi Iwai } 899b7d023e1STakashi Iwai if (formats == 0) { 900b7d023e1STakashi Iwai dev_err(&codec->dev, 901b7d023e1STakashi Iwai "formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)\n", 902b7d023e1STakashi Iwai nid, val, 903b7d023e1STakashi Iwai (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0, 904b7d023e1STakashi Iwai streams); 905b7d023e1STakashi Iwai return -EIO; 906b7d023e1STakashi Iwai } 907b7d023e1STakashi Iwai if (formatsp) 908b7d023e1STakashi Iwai *formatsp = formats; 909b7d023e1STakashi Iwai if (bpsp) 910b7d023e1STakashi Iwai *bpsp = bps; 911b7d023e1STakashi Iwai } 912b7d023e1STakashi Iwai 913b7d023e1STakashi Iwai return 0; 914b7d023e1STakashi Iwai } 915b7d023e1STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_query_supported_pcm); 916b7d023e1STakashi Iwai 917b7d023e1STakashi Iwai /** 918b7d023e1STakashi Iwai * snd_hdac_is_supported_format - Check the validity of the format 919b7d023e1STakashi Iwai * @codec: the codec object 920b7d023e1STakashi Iwai * @nid: NID to check 921b7d023e1STakashi Iwai * @format: the HD-audio format value to check 922b7d023e1STakashi Iwai * 923b7d023e1STakashi Iwai * Check whether the given node supports the format value. 924b7d023e1STakashi Iwai * 925b7d023e1STakashi Iwai * Returns true if supported, false if not. 926b7d023e1STakashi Iwai */ 927b7d023e1STakashi Iwai bool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid, 928b7d023e1STakashi Iwai unsigned int format) 929b7d023e1STakashi Iwai { 930b7d023e1STakashi Iwai int i; 931b7d023e1STakashi Iwai unsigned int val = 0, rate, stream; 932b7d023e1STakashi Iwai 933b7d023e1STakashi Iwai val = query_pcm_param(codec, nid); 934b7d023e1STakashi Iwai if (!val) 935b7d023e1STakashi Iwai return false; 936b7d023e1STakashi Iwai 937b7d023e1STakashi Iwai rate = format & 0xff00; 938b7d023e1STakashi Iwai for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) 939b7d023e1STakashi Iwai if (rate_bits[i].hda_fmt == rate) { 940b7d023e1STakashi Iwai if (val & (1 << i)) 941b7d023e1STakashi Iwai break; 942b7d023e1STakashi Iwai return false; 943b7d023e1STakashi Iwai } 944b7d023e1STakashi Iwai if (i >= AC_PAR_PCM_RATE_BITS) 945b7d023e1STakashi Iwai return false; 946b7d023e1STakashi Iwai 947b7d023e1STakashi Iwai stream = query_stream_param(codec, nid); 948b7d023e1STakashi Iwai if (!stream) 949b7d023e1STakashi Iwai return false; 950b7d023e1STakashi Iwai 951b7d023e1STakashi Iwai if (stream & AC_SUPFMT_PCM) { 952b7d023e1STakashi Iwai switch (format & 0xf0) { 953b7d023e1STakashi Iwai case 0x00: 954b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_8)) 955b7d023e1STakashi Iwai return false; 956b7d023e1STakashi Iwai break; 957b7d023e1STakashi Iwai case 0x10: 958b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_16)) 959b7d023e1STakashi Iwai return false; 960b7d023e1STakashi Iwai break; 961b7d023e1STakashi Iwai case 0x20: 962b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_20)) 963b7d023e1STakashi Iwai return false; 964b7d023e1STakashi Iwai break; 965b7d023e1STakashi Iwai case 0x30: 966b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_24)) 967b7d023e1STakashi Iwai return false; 968b7d023e1STakashi Iwai break; 969b7d023e1STakashi Iwai case 0x40: 970b7d023e1STakashi Iwai if (!(val & AC_SUPPCM_BITS_32)) 971b7d023e1STakashi Iwai return false; 972b7d023e1STakashi Iwai break; 973b7d023e1STakashi Iwai default: 974b7d023e1STakashi Iwai return false; 975b7d023e1STakashi Iwai } 976b7d023e1STakashi Iwai } else { 977b7d023e1STakashi Iwai /* FIXME: check for float32 and AC3? */ 978b7d023e1STakashi Iwai } 979b7d023e1STakashi Iwai 980b7d023e1STakashi Iwai return true; 981b7d023e1STakashi Iwai } 982b7d023e1STakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_is_supported_format); 9831b5e6167SSubhransu S. Prusty 9841b5e6167SSubhransu S. Prusty static unsigned int codec_read(struct hdac_device *hdac, hda_nid_t nid, 9851b5e6167SSubhransu S. Prusty int flags, unsigned int verb, unsigned int parm) 9861b5e6167SSubhransu S. Prusty { 9871b5e6167SSubhransu S. Prusty unsigned int cmd = snd_hdac_make_cmd(hdac, nid, verb, parm); 9881b5e6167SSubhransu S. Prusty unsigned int res; 9891b5e6167SSubhransu S. Prusty 9901b5e6167SSubhransu S. Prusty if (snd_hdac_exec_verb(hdac, cmd, flags, &res)) 9911b5e6167SSubhransu S. Prusty return -1; 9921b5e6167SSubhransu S. Prusty 9931b5e6167SSubhransu S. Prusty return res; 9941b5e6167SSubhransu S. Prusty } 9951b5e6167SSubhransu S. Prusty 9961b5e6167SSubhransu S. Prusty static int codec_write(struct hdac_device *hdac, hda_nid_t nid, 9971b5e6167SSubhransu S. Prusty int flags, unsigned int verb, unsigned int parm) 9981b5e6167SSubhransu S. Prusty { 9991b5e6167SSubhransu S. Prusty unsigned int cmd = snd_hdac_make_cmd(hdac, nid, verb, parm); 10001b5e6167SSubhransu S. Prusty 10011b5e6167SSubhransu S. Prusty return snd_hdac_exec_verb(hdac, cmd, flags, NULL); 10021b5e6167SSubhransu S. Prusty } 10031b5e6167SSubhransu S. Prusty 10041b5e6167SSubhransu S. Prusty /** 10051b5e6167SSubhransu S. Prusty * snd_hdac_codec_read - send a command and get the response 10061b5e6167SSubhransu S. Prusty * @hdac: the HDAC device 10071b5e6167SSubhransu S. Prusty * @nid: NID to send the command 10081b5e6167SSubhransu S. Prusty * @flags: optional bit flags 10091b5e6167SSubhransu S. Prusty * @verb: the verb to send 10101b5e6167SSubhransu S. Prusty * @parm: the parameter for the verb 10111b5e6167SSubhransu S. Prusty * 10121b5e6167SSubhransu S. Prusty * Send a single command and read the corresponding response. 10131b5e6167SSubhransu S. Prusty * 10141b5e6167SSubhransu S. Prusty * Returns the obtained response value, or -1 for an error. 10151b5e6167SSubhransu S. Prusty */ 10161b5e6167SSubhransu S. Prusty int snd_hdac_codec_read(struct hdac_device *hdac, hda_nid_t nid, 10171b5e6167SSubhransu S. Prusty int flags, unsigned int verb, unsigned int parm) 10181b5e6167SSubhransu S. Prusty { 10191b5e6167SSubhransu S. Prusty return codec_read(hdac, nid, flags, verb, parm); 10201b5e6167SSubhransu S. Prusty } 10211b5e6167SSubhransu S. Prusty EXPORT_SYMBOL_GPL(snd_hdac_codec_read); 10221b5e6167SSubhransu S. Prusty 10231b5e6167SSubhransu S. Prusty /** 10241b5e6167SSubhransu S. Prusty * snd_hdac_codec_write - send a single command without waiting for response 10251b5e6167SSubhransu S. Prusty * @hdac: the HDAC device 10261b5e6167SSubhransu S. Prusty * @nid: NID to send the command 10271b5e6167SSubhransu S. Prusty * @flags: optional bit flags 10281b5e6167SSubhransu S. Prusty * @verb: the verb to send 10291b5e6167SSubhransu S. Prusty * @parm: the parameter for the verb 10301b5e6167SSubhransu S. Prusty * 10311b5e6167SSubhransu S. Prusty * Send a single command without waiting for response. 10321b5e6167SSubhransu S. Prusty * 10331b5e6167SSubhransu S. Prusty * Returns 0 if successful, or a negative error code. 10341b5e6167SSubhransu S. Prusty */ 10351b5e6167SSubhransu S. Prusty int snd_hdac_codec_write(struct hdac_device *hdac, hda_nid_t nid, 10361b5e6167SSubhransu S. Prusty int flags, unsigned int verb, unsigned int parm) 10371b5e6167SSubhransu S. Prusty { 10381b5e6167SSubhransu S. Prusty return codec_write(hdac, nid, flags, verb, parm); 10391b5e6167SSubhransu S. Prusty } 10401b5e6167SSubhransu S. Prusty EXPORT_SYMBOL_GPL(snd_hdac_codec_write); 10411b5e6167SSubhransu S. Prusty 104278dd5e21STakashi Iwai /** 104378dd5e21STakashi Iwai * snd_hdac_check_power_state - check whether the actual power state matches 10441b5e6167SSubhransu S. Prusty * with the target state 10451b5e6167SSubhransu S. Prusty * 10461b5e6167SSubhransu S. Prusty * @hdac: the HDAC device 10471b5e6167SSubhransu S. Prusty * @nid: NID to send the command 10481b5e6167SSubhransu S. Prusty * @target_state: target state to check for 10491b5e6167SSubhransu S. Prusty * 10501b5e6167SSubhransu S. Prusty * Return true if state matches, false if not 10511b5e6167SSubhransu S. Prusty */ 10521b5e6167SSubhransu S. Prusty bool snd_hdac_check_power_state(struct hdac_device *hdac, 10531b5e6167SSubhransu S. Prusty hda_nid_t nid, unsigned int target_state) 10541b5e6167SSubhransu S. Prusty { 10551b5e6167SSubhransu S. Prusty unsigned int state = codec_read(hdac, nid, 0, 10561b5e6167SSubhransu S. Prusty AC_VERB_GET_POWER_STATE, 0); 10571b5e6167SSubhransu S. Prusty 10581b5e6167SSubhransu S. Prusty if (state & AC_PWRST_ERROR) 10591b5e6167SSubhransu S. Prusty return true; 10601b5e6167SSubhransu S. Prusty state = (state >> 4) & 0x0f; 10611b5e6167SSubhransu S. Prusty return (state == target_state); 10621b5e6167SSubhransu S. Prusty } 10631b5e6167SSubhransu S. Prusty EXPORT_SYMBOL_GPL(snd_hdac_check_power_state); 106409787492SAbhijeet Kumar /** 106509787492SAbhijeet Kumar * snd_hdac_sync_power_state - wait until actual power state matches 106609787492SAbhijeet Kumar * with the target state 106709787492SAbhijeet Kumar * 106809787492SAbhijeet Kumar * @hdac: the HDAC device 106909787492SAbhijeet Kumar * @nid: NID to send the command 107009787492SAbhijeet Kumar * @target_state: target state to check for 107109787492SAbhijeet Kumar * 107209787492SAbhijeet Kumar * Return power state or PS_ERROR if codec rejects GET verb. 107309787492SAbhijeet Kumar */ 107409787492SAbhijeet Kumar unsigned int snd_hdac_sync_power_state(struct hdac_device *codec, 107509787492SAbhijeet Kumar hda_nid_t nid, unsigned int power_state) 107609787492SAbhijeet Kumar { 107709787492SAbhijeet Kumar unsigned long end_time = jiffies + msecs_to_jiffies(500); 107809787492SAbhijeet Kumar unsigned int state, actual_state, count; 107909787492SAbhijeet Kumar 108009787492SAbhijeet Kumar for (count = 0; count < 500; count++) { 108109787492SAbhijeet Kumar state = snd_hdac_codec_read(codec, nid, 0, 108209787492SAbhijeet Kumar AC_VERB_GET_POWER_STATE, 0); 108309787492SAbhijeet Kumar if (state & AC_PWRST_ERROR) { 108409787492SAbhijeet Kumar msleep(20); 108509787492SAbhijeet Kumar break; 108609787492SAbhijeet Kumar } 108709787492SAbhijeet Kumar actual_state = (state >> 4) & 0x0f; 108809787492SAbhijeet Kumar if (actual_state == power_state) 108909787492SAbhijeet Kumar break; 109009787492SAbhijeet Kumar if (time_after_eq(jiffies, end_time)) 109109787492SAbhijeet Kumar break; 109209787492SAbhijeet Kumar /* wait until the codec reachs to the target state */ 109309787492SAbhijeet Kumar msleep(1); 109409787492SAbhijeet Kumar } 109509787492SAbhijeet Kumar return state; 109609787492SAbhijeet Kumar } 109709787492SAbhijeet Kumar EXPORT_SYMBOL_GPL(snd_hdac_sync_power_state); 1098