1*7639a06cSTakashi Iwai /* 2*7639a06cSTakashi Iwai * HD-audio codec core device 3*7639a06cSTakashi Iwai */ 4*7639a06cSTakashi Iwai 5*7639a06cSTakashi Iwai #include <linux/init.h> 6*7639a06cSTakashi Iwai #include <linux/device.h> 7*7639a06cSTakashi Iwai #include <linux/slab.h> 8*7639a06cSTakashi Iwai #include <linux/module.h> 9*7639a06cSTakashi Iwai #include <linux/export.h> 10*7639a06cSTakashi Iwai #include <linux/pm_runtime.h> 11*7639a06cSTakashi Iwai #include <sound/hdaudio.h> 12*7639a06cSTakashi Iwai #include "local.h" 13*7639a06cSTakashi Iwai 14*7639a06cSTakashi Iwai static void setup_fg_nodes(struct hdac_device *codec); 15*7639a06cSTakashi Iwai static int get_codec_vendor_name(struct hdac_device *codec); 16*7639a06cSTakashi Iwai 17*7639a06cSTakashi Iwai static void default_release(struct device *dev) 18*7639a06cSTakashi Iwai { 19*7639a06cSTakashi Iwai snd_hdac_device_exit(container_of(dev, struct hdac_device, dev)); 20*7639a06cSTakashi Iwai } 21*7639a06cSTakashi Iwai 22*7639a06cSTakashi Iwai /** 23*7639a06cSTakashi Iwai * snd_hdac_device_init - initialize the HD-audio codec base device 24*7639a06cSTakashi Iwai * @codec: device to initialize 25*7639a06cSTakashi Iwai * @bus: but to attach 26*7639a06cSTakashi Iwai * @name: device name string 27*7639a06cSTakashi Iwai * @addr: codec address 28*7639a06cSTakashi Iwai * 29*7639a06cSTakashi Iwai * Returns zero for success or a negative error code. 30*7639a06cSTakashi Iwai * 31*7639a06cSTakashi Iwai * This function increments the runtime PM counter and marks it active. 32*7639a06cSTakashi Iwai * The caller needs to turn it off appropriately later. 33*7639a06cSTakashi Iwai * 34*7639a06cSTakashi Iwai * The caller needs to set the device's release op properly by itself. 35*7639a06cSTakashi Iwai */ 36*7639a06cSTakashi Iwai int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus, 37*7639a06cSTakashi Iwai const char *name, unsigned int addr) 38*7639a06cSTakashi Iwai { 39*7639a06cSTakashi Iwai struct device *dev; 40*7639a06cSTakashi Iwai hda_nid_t fg; 41*7639a06cSTakashi Iwai int err; 42*7639a06cSTakashi Iwai 43*7639a06cSTakashi Iwai dev = &codec->dev; 44*7639a06cSTakashi Iwai device_initialize(dev); 45*7639a06cSTakashi Iwai dev->parent = bus->dev; 46*7639a06cSTakashi Iwai dev->bus = &snd_hda_bus_type; 47*7639a06cSTakashi Iwai dev->release = default_release; 48*7639a06cSTakashi Iwai dev_set_name(dev, "%s", name); 49*7639a06cSTakashi Iwai device_enable_async_suspend(dev); 50*7639a06cSTakashi Iwai 51*7639a06cSTakashi Iwai codec->bus = bus; 52*7639a06cSTakashi Iwai codec->addr = addr; 53*7639a06cSTakashi Iwai codec->type = HDA_DEV_CORE; 54*7639a06cSTakashi Iwai pm_runtime_set_active(&codec->dev); 55*7639a06cSTakashi Iwai pm_runtime_get_noresume(&codec->dev); 56*7639a06cSTakashi Iwai atomic_set(&codec->in_pm, 0); 57*7639a06cSTakashi Iwai 58*7639a06cSTakashi Iwai err = snd_hdac_bus_add_device(bus, codec); 59*7639a06cSTakashi Iwai if (err < 0) 60*7639a06cSTakashi Iwai goto error; 61*7639a06cSTakashi Iwai 62*7639a06cSTakashi Iwai /* fill parameters */ 63*7639a06cSTakashi Iwai codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 64*7639a06cSTakashi Iwai AC_PAR_VENDOR_ID); 65*7639a06cSTakashi Iwai if (codec->vendor_id == -1) { 66*7639a06cSTakashi Iwai /* read again, hopefully the access method was corrected 67*7639a06cSTakashi Iwai * in the last read... 68*7639a06cSTakashi Iwai */ 69*7639a06cSTakashi Iwai codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 70*7639a06cSTakashi Iwai AC_PAR_VENDOR_ID); 71*7639a06cSTakashi Iwai } 72*7639a06cSTakashi Iwai 73*7639a06cSTakashi Iwai codec->subsystem_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 74*7639a06cSTakashi Iwai AC_PAR_SUBSYSTEM_ID); 75*7639a06cSTakashi Iwai codec->revision_id = snd_hdac_read_parm(codec, AC_NODE_ROOT, 76*7639a06cSTakashi Iwai AC_PAR_REV_ID); 77*7639a06cSTakashi Iwai 78*7639a06cSTakashi Iwai setup_fg_nodes(codec); 79*7639a06cSTakashi Iwai if (!codec->afg && !codec->mfg) { 80*7639a06cSTakashi Iwai dev_err(dev, "no AFG or MFG node found\n"); 81*7639a06cSTakashi Iwai err = -ENODEV; 82*7639a06cSTakashi Iwai goto error; 83*7639a06cSTakashi Iwai } 84*7639a06cSTakashi Iwai 85*7639a06cSTakashi Iwai fg = codec->afg ? codec->afg : codec->mfg; 86*7639a06cSTakashi Iwai 87*7639a06cSTakashi Iwai err = snd_hdac_refresh_widgets(codec); 88*7639a06cSTakashi Iwai if (err < 0) 89*7639a06cSTakashi Iwai goto error; 90*7639a06cSTakashi Iwai 91*7639a06cSTakashi Iwai codec->power_caps = snd_hdac_read_parm(codec, fg, AC_PAR_POWER_STATE); 92*7639a06cSTakashi Iwai /* reread ssid if not set by parameter */ 93*7639a06cSTakashi Iwai if (codec->subsystem_id == -1) 94*7639a06cSTakashi Iwai snd_hdac_read(codec, fg, AC_VERB_GET_SUBSYSTEM_ID, 0, 95*7639a06cSTakashi Iwai &codec->subsystem_id); 96*7639a06cSTakashi Iwai 97*7639a06cSTakashi Iwai err = get_codec_vendor_name(codec); 98*7639a06cSTakashi Iwai if (err < 0) 99*7639a06cSTakashi Iwai goto error; 100*7639a06cSTakashi Iwai 101*7639a06cSTakashi Iwai codec->chip_name = kasprintf(GFP_KERNEL, "ID %x", 102*7639a06cSTakashi Iwai codec->vendor_id & 0xffff); 103*7639a06cSTakashi Iwai if (!codec->chip_name) { 104*7639a06cSTakashi Iwai err = -ENOMEM; 105*7639a06cSTakashi Iwai goto error; 106*7639a06cSTakashi Iwai } 107*7639a06cSTakashi Iwai 108*7639a06cSTakashi Iwai return 0; 109*7639a06cSTakashi Iwai 110*7639a06cSTakashi Iwai error: 111*7639a06cSTakashi Iwai pm_runtime_put_noidle(&codec->dev); 112*7639a06cSTakashi Iwai put_device(&codec->dev); 113*7639a06cSTakashi Iwai return err; 114*7639a06cSTakashi Iwai } 115*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_init); 116*7639a06cSTakashi Iwai 117*7639a06cSTakashi Iwai /** 118*7639a06cSTakashi Iwai * snd_hdac_device_exit - clean up the HD-audio codec base device 119*7639a06cSTakashi Iwai * @codec: device to clean up 120*7639a06cSTakashi Iwai */ 121*7639a06cSTakashi Iwai void snd_hdac_device_exit(struct hdac_device *codec) 122*7639a06cSTakashi Iwai { 123*7639a06cSTakashi Iwai /* pm_runtime_put_noidle(&codec->dev); */ 124*7639a06cSTakashi Iwai snd_hdac_bus_remove_device(codec->bus, codec); 125*7639a06cSTakashi Iwai kfree(codec->vendor_name); 126*7639a06cSTakashi Iwai kfree(codec->chip_name); 127*7639a06cSTakashi Iwai } 128*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_device_exit); 129*7639a06cSTakashi Iwai 130*7639a06cSTakashi Iwai /** 131*7639a06cSTakashi Iwai * snd_hdac_make_cmd - compose a 32bit command word to be sent to the 132*7639a06cSTakashi Iwai * HD-audio controller 133*7639a06cSTakashi Iwai * @codec: the codec object 134*7639a06cSTakashi Iwai * @nid: NID to encode 135*7639a06cSTakashi Iwai * @verb: verb to encode 136*7639a06cSTakashi Iwai * @parm: parameter to encode 137*7639a06cSTakashi Iwai * 138*7639a06cSTakashi Iwai * Return an encoded command verb or -1 for error. 139*7639a06cSTakashi Iwai */ 140*7639a06cSTakashi Iwai unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, 141*7639a06cSTakashi Iwai unsigned int verb, unsigned int parm) 142*7639a06cSTakashi Iwai { 143*7639a06cSTakashi Iwai u32 val, addr; 144*7639a06cSTakashi Iwai 145*7639a06cSTakashi Iwai addr = codec->addr; 146*7639a06cSTakashi Iwai if ((addr & ~0xf) || (nid & ~0x7f) || 147*7639a06cSTakashi Iwai (verb & ~0xfff) || (parm & ~0xffff)) { 148*7639a06cSTakashi Iwai dev_err(&codec->dev, "out of range cmd %x:%x:%x:%x\n", 149*7639a06cSTakashi Iwai addr, nid, verb, parm); 150*7639a06cSTakashi Iwai return -1; 151*7639a06cSTakashi Iwai } 152*7639a06cSTakashi Iwai 153*7639a06cSTakashi Iwai val = addr << 28; 154*7639a06cSTakashi Iwai val |= (u32)nid << 20; 155*7639a06cSTakashi Iwai val |= verb << 8; 156*7639a06cSTakashi Iwai val |= parm; 157*7639a06cSTakashi Iwai return val; 158*7639a06cSTakashi Iwai } 159*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_make_cmd); 160*7639a06cSTakashi Iwai 161*7639a06cSTakashi Iwai /** 162*7639a06cSTakashi Iwai * snd_hdac_read - execute a verb 163*7639a06cSTakashi Iwai * @codec: the codec object 164*7639a06cSTakashi Iwai * @nid: NID to execute a verb 165*7639a06cSTakashi Iwai * @verb: verb to execute 166*7639a06cSTakashi Iwai * @parm: parameter for a verb 167*7639a06cSTakashi Iwai * @res: the pointer to store the result, NULL if running async 168*7639a06cSTakashi Iwai * 169*7639a06cSTakashi Iwai * Returns zero if successful, or a negative error code. 170*7639a06cSTakashi Iwai */ 171*7639a06cSTakashi Iwai int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, 172*7639a06cSTakashi Iwai unsigned int verb, unsigned int parm, unsigned int *res) 173*7639a06cSTakashi Iwai { 174*7639a06cSTakashi Iwai unsigned int cmd = snd_hdac_make_cmd(codec, nid, verb, parm); 175*7639a06cSTakashi Iwai 176*7639a06cSTakashi Iwai return snd_hdac_bus_exec_verb(codec->bus, codec->addr, cmd, res); 177*7639a06cSTakashi Iwai } 178*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_read); 179*7639a06cSTakashi Iwai 180*7639a06cSTakashi Iwai /** 181*7639a06cSTakashi Iwai * snd_hdac_read_parm - read a codec parameter 182*7639a06cSTakashi Iwai * @codec: the codec object 183*7639a06cSTakashi Iwai * @nid: NID to read a parameter 184*7639a06cSTakashi Iwai * @parm: parameter to read 185*7639a06cSTakashi Iwai * 186*7639a06cSTakashi Iwai * Returns -1 for error. If you need to distinguish the error more 187*7639a06cSTakashi Iwai * strictly, use snd_hdac_read() directly. 188*7639a06cSTakashi Iwai */ 189*7639a06cSTakashi Iwai int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm) 190*7639a06cSTakashi Iwai { 191*7639a06cSTakashi Iwai int val; 192*7639a06cSTakashi Iwai 193*7639a06cSTakashi Iwai if (snd_hdac_read(codec, nid, AC_VERB_PARAMETERS, parm, &val)) 194*7639a06cSTakashi Iwai return -1; 195*7639a06cSTakashi Iwai return val; 196*7639a06cSTakashi Iwai } 197*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_read_parm); 198*7639a06cSTakashi Iwai 199*7639a06cSTakashi Iwai /** 200*7639a06cSTakashi Iwai * snd_hdac_get_sub_nodes - get start NID and number of subtree nodes 201*7639a06cSTakashi Iwai * @codec: the codec object 202*7639a06cSTakashi Iwai * @nid: NID to inspect 203*7639a06cSTakashi Iwai * @start_id: the pointer to store the starting NID 204*7639a06cSTakashi Iwai * 205*7639a06cSTakashi Iwai * Returns the number of subtree nodes or zero if not found. 206*7639a06cSTakashi Iwai */ 207*7639a06cSTakashi Iwai int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, 208*7639a06cSTakashi Iwai hda_nid_t *start_id) 209*7639a06cSTakashi Iwai { 210*7639a06cSTakashi Iwai unsigned int parm; 211*7639a06cSTakashi Iwai 212*7639a06cSTakashi Iwai parm = snd_hdac_read_parm(codec, nid, AC_PAR_NODE_COUNT); 213*7639a06cSTakashi Iwai if (parm == -1) { 214*7639a06cSTakashi Iwai *start_id = 0; 215*7639a06cSTakashi Iwai return 0; 216*7639a06cSTakashi Iwai } 217*7639a06cSTakashi Iwai *start_id = (parm >> 16) & 0x7fff; 218*7639a06cSTakashi Iwai return (int)(parm & 0x7fff); 219*7639a06cSTakashi Iwai } 220*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_get_sub_nodes); 221*7639a06cSTakashi Iwai 222*7639a06cSTakashi Iwai /* 223*7639a06cSTakashi Iwai * look for an AFG and MFG nodes 224*7639a06cSTakashi Iwai */ 225*7639a06cSTakashi Iwai static void setup_fg_nodes(struct hdac_device *codec) 226*7639a06cSTakashi Iwai { 227*7639a06cSTakashi Iwai int i, total_nodes, function_id; 228*7639a06cSTakashi Iwai hda_nid_t nid; 229*7639a06cSTakashi Iwai 230*7639a06cSTakashi Iwai total_nodes = snd_hdac_get_sub_nodes(codec, AC_NODE_ROOT, &nid); 231*7639a06cSTakashi Iwai for (i = 0; i < total_nodes; i++, nid++) { 232*7639a06cSTakashi Iwai function_id = snd_hdac_read_parm(codec, nid, 233*7639a06cSTakashi Iwai AC_PAR_FUNCTION_TYPE); 234*7639a06cSTakashi Iwai switch (function_id & 0xff) { 235*7639a06cSTakashi Iwai case AC_GRP_AUDIO_FUNCTION: 236*7639a06cSTakashi Iwai codec->afg = nid; 237*7639a06cSTakashi Iwai codec->afg_function_id = function_id & 0xff; 238*7639a06cSTakashi Iwai codec->afg_unsol = (function_id >> 8) & 1; 239*7639a06cSTakashi Iwai break; 240*7639a06cSTakashi Iwai case AC_GRP_MODEM_FUNCTION: 241*7639a06cSTakashi Iwai codec->mfg = nid; 242*7639a06cSTakashi Iwai codec->mfg_function_id = function_id & 0xff; 243*7639a06cSTakashi Iwai codec->mfg_unsol = (function_id >> 8) & 1; 244*7639a06cSTakashi Iwai break; 245*7639a06cSTakashi Iwai default: 246*7639a06cSTakashi Iwai break; 247*7639a06cSTakashi Iwai } 248*7639a06cSTakashi Iwai } 249*7639a06cSTakashi Iwai } 250*7639a06cSTakashi Iwai 251*7639a06cSTakashi Iwai /** 252*7639a06cSTakashi Iwai * snd_hdac_refresh_widgets - Reset the widget start/end nodes 253*7639a06cSTakashi Iwai * @codec: the codec object 254*7639a06cSTakashi Iwai */ 255*7639a06cSTakashi Iwai int snd_hdac_refresh_widgets(struct hdac_device *codec) 256*7639a06cSTakashi Iwai { 257*7639a06cSTakashi Iwai hda_nid_t start_nid; 258*7639a06cSTakashi Iwai int nums; 259*7639a06cSTakashi Iwai 260*7639a06cSTakashi Iwai nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid); 261*7639a06cSTakashi Iwai if (!start_nid || nums <= 0 || nums >= 0xff) { 262*7639a06cSTakashi Iwai dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n", 263*7639a06cSTakashi Iwai codec->afg); 264*7639a06cSTakashi Iwai return -EINVAL; 265*7639a06cSTakashi Iwai } 266*7639a06cSTakashi Iwai 267*7639a06cSTakashi Iwai codec->num_nodes = nums; 268*7639a06cSTakashi Iwai codec->start_nid = start_nid; 269*7639a06cSTakashi Iwai codec->end_nid = start_nid + nums; 270*7639a06cSTakashi Iwai return 0; 271*7639a06cSTakashi Iwai } 272*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets); 273*7639a06cSTakashi Iwai 274*7639a06cSTakashi Iwai /* return CONNLIST_LEN parameter of the given widget */ 275*7639a06cSTakashi Iwai static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid) 276*7639a06cSTakashi Iwai { 277*7639a06cSTakashi Iwai unsigned int wcaps = get_wcaps(codec, nid); 278*7639a06cSTakashi Iwai unsigned int parm; 279*7639a06cSTakashi Iwai 280*7639a06cSTakashi Iwai if (!(wcaps & AC_WCAP_CONN_LIST) && 281*7639a06cSTakashi Iwai get_wcaps_type(wcaps) != AC_WID_VOL_KNB) 282*7639a06cSTakashi Iwai return 0; 283*7639a06cSTakashi Iwai 284*7639a06cSTakashi Iwai parm = snd_hdac_read_parm(codec, nid, AC_PAR_CONNLIST_LEN); 285*7639a06cSTakashi Iwai if (parm == -1) 286*7639a06cSTakashi Iwai parm = 0; 287*7639a06cSTakashi Iwai return parm; 288*7639a06cSTakashi Iwai } 289*7639a06cSTakashi Iwai 290*7639a06cSTakashi Iwai /** 291*7639a06cSTakashi Iwai * snd_hdac_get_connections - get a widget connection list 292*7639a06cSTakashi Iwai * @codec: the codec object 293*7639a06cSTakashi Iwai * @nid: NID 294*7639a06cSTakashi Iwai * @conn_list: the array to store the results, can be NULL 295*7639a06cSTakashi Iwai * @max_conns: the max size of the given array 296*7639a06cSTakashi Iwai * 297*7639a06cSTakashi Iwai * Returns the number of connected widgets, zero for no connection, or a 298*7639a06cSTakashi Iwai * negative error code. When the number of elements don't fit with the 299*7639a06cSTakashi Iwai * given array size, it returns -ENOSPC. 300*7639a06cSTakashi Iwai * 301*7639a06cSTakashi Iwai * When @conn_list is NULL, it just checks the number of connections. 302*7639a06cSTakashi Iwai */ 303*7639a06cSTakashi Iwai int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, 304*7639a06cSTakashi Iwai hda_nid_t *conn_list, int max_conns) 305*7639a06cSTakashi Iwai { 306*7639a06cSTakashi Iwai unsigned int parm; 307*7639a06cSTakashi Iwai int i, conn_len, conns, err; 308*7639a06cSTakashi Iwai unsigned int shift, num_elems, mask; 309*7639a06cSTakashi Iwai hda_nid_t prev_nid; 310*7639a06cSTakashi Iwai int null_count = 0; 311*7639a06cSTakashi Iwai 312*7639a06cSTakashi Iwai parm = get_num_conns(codec, nid); 313*7639a06cSTakashi Iwai if (!parm) 314*7639a06cSTakashi Iwai return 0; 315*7639a06cSTakashi Iwai 316*7639a06cSTakashi Iwai if (parm & AC_CLIST_LONG) { 317*7639a06cSTakashi Iwai /* long form */ 318*7639a06cSTakashi Iwai shift = 16; 319*7639a06cSTakashi Iwai num_elems = 2; 320*7639a06cSTakashi Iwai } else { 321*7639a06cSTakashi Iwai /* short form */ 322*7639a06cSTakashi Iwai shift = 8; 323*7639a06cSTakashi Iwai num_elems = 4; 324*7639a06cSTakashi Iwai } 325*7639a06cSTakashi Iwai conn_len = parm & AC_CLIST_LENGTH; 326*7639a06cSTakashi Iwai mask = (1 << (shift-1)) - 1; 327*7639a06cSTakashi Iwai 328*7639a06cSTakashi Iwai if (!conn_len) 329*7639a06cSTakashi Iwai return 0; /* no connection */ 330*7639a06cSTakashi Iwai 331*7639a06cSTakashi Iwai if (conn_len == 1) { 332*7639a06cSTakashi Iwai /* single connection */ 333*7639a06cSTakashi Iwai err = snd_hdac_read(codec, nid, AC_VERB_GET_CONNECT_LIST, 0, 334*7639a06cSTakashi Iwai &parm); 335*7639a06cSTakashi Iwai if (err < 0) 336*7639a06cSTakashi Iwai return err; 337*7639a06cSTakashi Iwai if (conn_list) 338*7639a06cSTakashi Iwai conn_list[0] = parm & mask; 339*7639a06cSTakashi Iwai return 1; 340*7639a06cSTakashi Iwai } 341*7639a06cSTakashi Iwai 342*7639a06cSTakashi Iwai /* multi connection */ 343*7639a06cSTakashi Iwai conns = 0; 344*7639a06cSTakashi Iwai prev_nid = 0; 345*7639a06cSTakashi Iwai for (i = 0; i < conn_len; i++) { 346*7639a06cSTakashi Iwai int range_val; 347*7639a06cSTakashi Iwai hda_nid_t val, n; 348*7639a06cSTakashi Iwai 349*7639a06cSTakashi Iwai if (i % num_elems == 0) { 350*7639a06cSTakashi Iwai err = snd_hdac_read(codec, nid, 351*7639a06cSTakashi Iwai AC_VERB_GET_CONNECT_LIST, i, 352*7639a06cSTakashi Iwai &parm); 353*7639a06cSTakashi Iwai if (err < 0) 354*7639a06cSTakashi Iwai return -EIO; 355*7639a06cSTakashi Iwai } 356*7639a06cSTakashi Iwai range_val = !!(parm & (1 << (shift-1))); /* ranges */ 357*7639a06cSTakashi Iwai val = parm & mask; 358*7639a06cSTakashi Iwai if (val == 0 && null_count++) { /* no second chance */ 359*7639a06cSTakashi Iwai dev_dbg(&codec->dev, 360*7639a06cSTakashi Iwai "invalid CONNECT_LIST verb %x[%i]:%x\n", 361*7639a06cSTakashi Iwai nid, i, parm); 362*7639a06cSTakashi Iwai return 0; 363*7639a06cSTakashi Iwai } 364*7639a06cSTakashi Iwai parm >>= shift; 365*7639a06cSTakashi Iwai if (range_val) { 366*7639a06cSTakashi Iwai /* ranges between the previous and this one */ 367*7639a06cSTakashi Iwai if (!prev_nid || prev_nid >= val) { 368*7639a06cSTakashi Iwai dev_warn(&codec->dev, 369*7639a06cSTakashi Iwai "invalid dep_range_val %x:%x\n", 370*7639a06cSTakashi Iwai prev_nid, val); 371*7639a06cSTakashi Iwai continue; 372*7639a06cSTakashi Iwai } 373*7639a06cSTakashi Iwai for (n = prev_nid + 1; n <= val; n++) { 374*7639a06cSTakashi Iwai if (conn_list) { 375*7639a06cSTakashi Iwai if (conns >= max_conns) 376*7639a06cSTakashi Iwai return -ENOSPC; 377*7639a06cSTakashi Iwai conn_list[conns] = n; 378*7639a06cSTakashi Iwai } 379*7639a06cSTakashi Iwai conns++; 380*7639a06cSTakashi Iwai } 381*7639a06cSTakashi Iwai } else { 382*7639a06cSTakashi Iwai if (conn_list) { 383*7639a06cSTakashi Iwai if (conns >= max_conns) 384*7639a06cSTakashi Iwai return -ENOSPC; 385*7639a06cSTakashi Iwai conn_list[conns] = val; 386*7639a06cSTakashi Iwai } 387*7639a06cSTakashi Iwai conns++; 388*7639a06cSTakashi Iwai } 389*7639a06cSTakashi Iwai prev_nid = val; 390*7639a06cSTakashi Iwai } 391*7639a06cSTakashi Iwai return conns; 392*7639a06cSTakashi Iwai } 393*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_get_connections); 394*7639a06cSTakashi Iwai 395*7639a06cSTakashi Iwai #ifdef CONFIG_PM 396*7639a06cSTakashi Iwai /** 397*7639a06cSTakashi Iwai * snd_hdac_power_up - increment the runtime pm counter 398*7639a06cSTakashi Iwai * @codec: the codec object 399*7639a06cSTakashi Iwai */ 400*7639a06cSTakashi Iwai void snd_hdac_power_up(struct hdac_device *codec) 401*7639a06cSTakashi Iwai { 402*7639a06cSTakashi Iwai struct device *dev = &codec->dev; 403*7639a06cSTakashi Iwai 404*7639a06cSTakashi Iwai if (atomic_read(&codec->in_pm)) 405*7639a06cSTakashi Iwai return; 406*7639a06cSTakashi Iwai pm_runtime_get_sync(dev); 407*7639a06cSTakashi Iwai } 408*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_up); 409*7639a06cSTakashi Iwai 410*7639a06cSTakashi Iwai /** 411*7639a06cSTakashi Iwai * snd_hdac_power_up - decrement the runtime pm counter 412*7639a06cSTakashi Iwai * @codec: the codec object 413*7639a06cSTakashi Iwai */ 414*7639a06cSTakashi Iwai void snd_hdac_power_down(struct hdac_device *codec) 415*7639a06cSTakashi Iwai { 416*7639a06cSTakashi Iwai struct device *dev = &codec->dev; 417*7639a06cSTakashi Iwai 418*7639a06cSTakashi Iwai if (atomic_read(&codec->in_pm)) 419*7639a06cSTakashi Iwai return; 420*7639a06cSTakashi Iwai pm_runtime_mark_last_busy(dev); 421*7639a06cSTakashi Iwai pm_runtime_put_autosuspend(dev); 422*7639a06cSTakashi Iwai } 423*7639a06cSTakashi Iwai EXPORT_SYMBOL_GPL(snd_hdac_power_down); 424*7639a06cSTakashi Iwai #endif 425*7639a06cSTakashi Iwai 426*7639a06cSTakashi Iwai /* codec vendor labels */ 427*7639a06cSTakashi Iwai struct hda_vendor_id { 428*7639a06cSTakashi Iwai unsigned int id; 429*7639a06cSTakashi Iwai const char *name; 430*7639a06cSTakashi Iwai }; 431*7639a06cSTakashi Iwai 432*7639a06cSTakashi Iwai static struct hda_vendor_id hda_vendor_ids[] = { 433*7639a06cSTakashi Iwai { 0x1002, "ATI" }, 434*7639a06cSTakashi Iwai { 0x1013, "Cirrus Logic" }, 435*7639a06cSTakashi Iwai { 0x1057, "Motorola" }, 436*7639a06cSTakashi Iwai { 0x1095, "Silicon Image" }, 437*7639a06cSTakashi Iwai { 0x10de, "Nvidia" }, 438*7639a06cSTakashi Iwai { 0x10ec, "Realtek" }, 439*7639a06cSTakashi Iwai { 0x1102, "Creative" }, 440*7639a06cSTakashi Iwai { 0x1106, "VIA" }, 441*7639a06cSTakashi Iwai { 0x111d, "IDT" }, 442*7639a06cSTakashi Iwai { 0x11c1, "LSI" }, 443*7639a06cSTakashi Iwai { 0x11d4, "Analog Devices" }, 444*7639a06cSTakashi Iwai { 0x13f6, "C-Media" }, 445*7639a06cSTakashi Iwai { 0x14f1, "Conexant" }, 446*7639a06cSTakashi Iwai { 0x17e8, "Chrontel" }, 447*7639a06cSTakashi Iwai { 0x1854, "LG" }, 448*7639a06cSTakashi Iwai { 0x1aec, "Wolfson Microelectronics" }, 449*7639a06cSTakashi Iwai { 0x1af4, "QEMU" }, 450*7639a06cSTakashi Iwai { 0x434d, "C-Media" }, 451*7639a06cSTakashi Iwai { 0x8086, "Intel" }, 452*7639a06cSTakashi Iwai { 0x8384, "SigmaTel" }, 453*7639a06cSTakashi Iwai {} /* terminator */ 454*7639a06cSTakashi Iwai }; 455*7639a06cSTakashi Iwai 456*7639a06cSTakashi Iwai /* store the codec vendor name */ 457*7639a06cSTakashi Iwai static int get_codec_vendor_name(struct hdac_device *codec) 458*7639a06cSTakashi Iwai { 459*7639a06cSTakashi Iwai const struct hda_vendor_id *c; 460*7639a06cSTakashi Iwai u16 vendor_id = codec->vendor_id >> 16; 461*7639a06cSTakashi Iwai 462*7639a06cSTakashi Iwai for (c = hda_vendor_ids; c->id; c++) { 463*7639a06cSTakashi Iwai if (c->id == vendor_id) { 464*7639a06cSTakashi Iwai codec->vendor_name = kstrdup(c->name, GFP_KERNEL); 465*7639a06cSTakashi Iwai return codec->vendor_name ? 0 : -ENOMEM; 466*7639a06cSTakashi Iwai } 467*7639a06cSTakashi Iwai } 468*7639a06cSTakashi Iwai 469*7639a06cSTakashi Iwai codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id); 470*7639a06cSTakashi Iwai return codec->vendor_name ? 0 : -ENOMEM; 471*7639a06cSTakashi Iwai } 472