Merge remote-tracking branch 'asoc/topic/intel' into asoc-next
authorMark Brown <broonie@kernel.org>
Thu, 29 Sep 2016 19:43:59 +0000 (12:43 -0700)
committerMark Brown <broonie@kernel.org>
Thu, 29 Sep 2016 19:43:59 +0000 (12:43 -0700)
1  2 
sound/pci/hda/hda_intel.c
sound/soc/intel/skylake/skl-sst-utils.c
sound/soc/intel/skylake/skl.c

@@@ -54,6 -54,7 +54,7 @@@
  /* for snoop control */
  #include <asm/pgtable.h>
  #include <asm/cacheflush.h>
+ #include <asm/cpufeature.h>
  #endif
  #include <sound/core.h>
  #include <sound/initval.h>
@@@ -906,23 -907,20 +907,23 @@@ static int azx_resume(struct device *de
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip;
        struct hda_intel *hda;
 +      struct hdac_bus *bus;
  
        if (!card)
                return 0;
  
        chip = card->private_data;
        hda = container_of(chip, struct hda_intel, chip);
 +      bus = azx_bus(chip);
        if (chip->disabled || hda->init_failed || !chip->running)
                return 0;
  
 -      if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
 -              && hda->need_i915_power) {
 -              snd_hdac_display_power(azx_bus(chip), true);
 -              snd_hdac_i915_set_bclk(azx_bus(chip));
 +      if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
 +              snd_hdac_display_power(bus, true);
 +              if (hda->need_i915_power)
 +                      snd_hdac_i915_set_bclk(bus);
        }
 +
        if (chip->msi)
                if (pci_enable_msi(pci) < 0)
                        chip->msi = 0;
  
        hda_intel_init_chip(chip, true);
  
 +      /* power down again for link-controlled chips */
 +      if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
 +          !hda->need_i915_power)
 +              snd_hdac_display_power(bus, false);
 +
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
  
        trace_azx_resume(chip);
@@@ -1016,7 -1009,6 +1017,7 @@@ static int azx_runtime_resume(struct de
  
        chip = card->private_data;
        hda = container_of(chip, struct hda_intel, chip);
 +      bus = azx_bus(chip);
        if (chip->disabled || hda->init_failed)
                return 0;
  
                return 0;
  
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
 -              bus = azx_bus(chip);
 -              if (hda->need_i915_power) {
 -                      snd_hdac_display_power(bus, true);
 +              snd_hdac_display_power(bus, true);
 +              if (hda->need_i915_power)
                        snd_hdac_i915_set_bclk(bus);
 -              } else {
 -                      /* toggle codec wakeup bit for STATESTS read */
 -                      snd_hdac_set_codec_wakeup(bus, true);
 -                      snd_hdac_set_codec_wakeup(bus, false);
 -              }
        }
  
        /* Read STATESTS before controller reset */
        azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
                        ~STATESTS_INT_MASK);
  
 +      /* power down again for link-controlled chips */
 +      if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
 +          !hda->need_i915_power)
 +              snd_hdac_display_power(bus, false);
 +
        trace_azx_runtime_resume(chip);
        return 0;
  }
@@@ -1663,6 -1656,22 +1664,22 @@@ static int azx_first_init(struct azx *c
                return -ENXIO;
        }
  
+       if (IS_SKL_PLUS(pci))
+               snd_hdac_bus_parse_capabilities(bus);
+       /*
+        * Some Intel CPUs has always running timer (ART) feature and
+        * controller may have Global time sync reporting capability, so
+        * check both of these before declaring synchronized time reporting
+        * capability SNDRV_PCM_INFO_HAS_LINK_SYNCHRONIZED_ATIME
+        */
+       chip->gts_present = false;
+ #ifdef CONFIG_X86
+       if (bus->ppcap && boot_cpu_has(X86_FEATURE_ART))
+               chip->gts_present = true;
+ #endif
        if (chip->msi) {
                if (chip->driver_caps & AZX_DCAPS_NO_MSI64) {
                        dev_dbg(card->dev, "Disabling 64bit MSI\n");
  /* FW Extended Manifest Header id = $AE1 */
  #define SKL_EXT_MANIFEST_HEADER_MAGIC   0x31454124
  
- struct skl_dfw_module_mod {
-       char name[100];
-       struct skl_dfw_module skl_dfw_mod;
- };
  struct UUID {
        u8 id[16];
  };
@@@ -99,10 -94,15 +94,15 @@@ struct adsp_fw_hdr 
        u32 load_offset;
  } __packed;
  
+ #define MAX_INSTANCE_BUFF 2
  struct uuid_module {
        uuid_le uuid;
        int id;
        int is_loadable;
+       int max_instance;
+       u64 pvt_id[MAX_INSTANCE_BUFF];
+       int *instance_id;
  
        struct list_head list;
  };
@@@ -115,23 -115,18 +115,23 @@@ struct skl_ext_manifest_hdr 
        u32 entries;
  };
  
- int snd_skl_get_module_info(struct skl_sst *ctx, u8 *uuid,
-                       struct skl_dfw_module *dfw_config)
+ int snd_skl_get_module_info(struct skl_sst *ctx,
+                               struct skl_module_cfg *mconfig)
  {
        struct uuid_module *module;
        uuid_le *uuid_mod;
  
-       uuid_mod = (uuid_le *)uuid;
+       uuid_mod = (uuid_le *)mconfig->guid;
  
 +      if (list_empty(&ctx->uuid_list)) {
 +              dev_err(ctx->dev, "Module list is empty\n");
 +              return -EINVAL;
 +      }
 +
        list_for_each_entry(module, &ctx->uuid_list, list) {
                if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
-                       dfw_config->module_id = module->id;
-                       dfw_config->is_loadable = module->is_loadable;
+                       mconfig->id.module_id = module->id;
+                       mconfig->is_loadable = module->is_loadable;
  
                        return 0;
                }
  }
  EXPORT_SYMBOL_GPL(snd_skl_get_module_info);
  
+ static int skl_get_pvtid_map(struct uuid_module *module, int instance_id)
+ {
+       int pvt_id;
+       for (pvt_id = 0; pvt_id < module->max_instance; pvt_id++) {
+               if (module->instance_id[pvt_id] == instance_id)
+                       return pvt_id;
+       }
+       return -EINVAL;
+ }
+ int skl_get_pvt_instance_id_map(struct skl_sst *ctx,
+                               int module_id, int instance_id)
+ {
+       struct uuid_module *module;
+       list_for_each_entry(module, &ctx->uuid_list, list) {
+               if (module->id == module_id)
+                       return skl_get_pvtid_map(module, instance_id);
+       }
+       return -EINVAL;
+ }
+ EXPORT_SYMBOL_GPL(skl_get_pvt_instance_id_map);
+ static inline int skl_getid_32(struct uuid_module *module, u64 *val,
+                               int word1_mask, int word2_mask)
+ {
+       int index, max_inst, pvt_id;
+       u32 mask_val;
+       max_inst =  module->max_instance;
+       mask_val = (u32)(*val >> word1_mask);
+       if (mask_val != 0xffffffff) {
+               index = ffz(mask_val);
+               pvt_id = index + word1_mask + word2_mask;
+               if (pvt_id <= (max_inst - 1)) {
+                       *val |= 1 << (index + word1_mask);
+                       return pvt_id;
+               }
+       }
+       return -EINVAL;
+ }
+ static inline int skl_pvtid_128(struct uuid_module *module)
+ {
+       int j, i, word1_mask, word2_mask = 0, pvt_id;
+       for (j = 0; j < MAX_INSTANCE_BUFF; j++) {
+               word1_mask = 0;
+               for (i = 0; i < 2; i++) {
+                       pvt_id = skl_getid_32(module, &module->pvt_id[j],
+                                               word1_mask, word2_mask);
+                       if (pvt_id >= 0)
+                               return pvt_id;
+                       word1_mask += 32;
+                       if ((word1_mask + word2_mask) >= module->max_instance)
+                               return -EINVAL;
+               }
+               word2_mask += 64;
+               if (word2_mask >= module->max_instance)
+                       return -EINVAL;
+       }
+       return -EINVAL;
+ }
+ /**
+  * skl_get_pvt_id: generate a private id for use as module id
+  *
+  * @ctx: driver context
+  * @mconfig: module configuration data
+  *
+  * This generates a 128 bit private unique id for a module TYPE so that
+  * module instance is unique
+  */
+ int skl_get_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig)
+ {
+       struct uuid_module *module;
+       uuid_le *uuid_mod;
+       int pvt_id;
+       uuid_mod = (uuid_le *)mconfig->guid;
+       list_for_each_entry(module, &ctx->uuid_list, list) {
+               if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
+                       pvt_id = skl_pvtid_128(module);
+                       if (pvt_id >= 0) {
+                               module->instance_id[pvt_id] =
+                                               mconfig->id.instance_id;
+                               return pvt_id;
+                       }
+               }
+       }
+       return -EINVAL;
+ }
+ EXPORT_SYMBOL_GPL(skl_get_pvt_id);
+ /**
+  * skl_put_pvt_id: free up the private id allocated
+  *
+  * @ctx: driver context
+  * @mconfig: module configuration data
+  *
+  * This frees a 128 bit private unique id previously generated
+  */
+ int skl_put_pvt_id(struct skl_sst *ctx, struct skl_module_cfg *mconfig)
+ {
+       int i;
+       uuid_le *uuid_mod;
+       struct uuid_module *module;
+       uuid_mod = (uuid_le *)mconfig->guid;
+       list_for_each_entry(module, &ctx->uuid_list, list) {
+               if (uuid_le_cmp(*uuid_mod, module->uuid) == 0) {
+                       if (mconfig->id.pvt_id != 0)
+                               i = (mconfig->id.pvt_id) / 64;
+                       else
+                               i = 0;
+                       module->pvt_id[i] &= ~(1 << (mconfig->id.pvt_id));
+                       mconfig->id.pvt_id = -1;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+ }
+ EXPORT_SYMBOL_GPL(skl_put_pvt_id);
  /*
   * Parse the firmware binary to get the UUID, module id
   * and loadable flags
   */
- int snd_skl_parse_uuids(struct sst_dsp *ctx, unsigned int offset)
+ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw,
+                       unsigned int offset, int index)
  {
        struct adsp_fw_hdr *adsp_hdr;
        struct adsp_module_entry *mod_entry;
-       int i, num_entry;
+       int i, num_entry, size;
        uuid_le *uuid_bin;
        const char *buf;
        struct skl_sst *skl = ctx->thread_context;
        unsigned int safe_file;
  
        /* Get the FW pointer to derive ADSP header */
-       stripped_fw.data = ctx->fw->data;
-       stripped_fw.size = ctx->fw->size;
+       stripped_fw.data = fw->data;
+       stripped_fw.size = fw->size;
  
        skl_dsp_strip_extended_manifest(&stripped_fw);
  
                uuid_bin = (uuid_le *)mod_entry->uuid.id;
                memcpy(&module->uuid, uuid_bin, sizeof(module->uuid));
  
-               module->id = i;
+               module->id = (i | (index << 12));
                module->is_loadable = mod_entry->type.load_type;
+               module->max_instance = mod_entry->instance_max_count;
+               size = sizeof(int) * mod_entry->instance_max_count;
+               module->instance_id = devm_kzalloc(ctx->dev, size, GFP_KERNEL);
+               if (!module->instance_id) {
+                       kfree(module);
+                       return -ENOMEM;
+               }
  
                list_add_tail(&module->list, &skl->uuid_list);
  
@@@ -587,7 -587,7 +587,7 @@@ static int skl_first_init(struct hdac_e
                return -ENXIO;
        }
  
-       snd_hdac_ext_bus_parse_capabilities(ebus);
+       snd_hdac_bus_parse_capabilities(bus);
  
        if (skl_acquire_irq(ebus, 0) < 0)
                return -EBUSY;
@@@ -672,10 -672,8 +672,10 @@@ static int skl_probe(struct pci_dev *pc
  
        skl->nhlt = skl_nhlt_init(bus->dev);
  
 -      if (skl->nhlt == NULL)
 +      if (skl->nhlt == NULL) {
 +              err = -ENODEV;
                goto out_free;
 +      }
  
        skl_nhlt_update_topology_bin(skl);
  
        skl_dmic_data.dmic_num = skl_get_dmic_geo(skl);
  
        /* check if dsp is there */
-       if (ebus->ppcap) {
+       if (bus->ppcap) {
                err = skl_machine_device_register(skl,
                                  (void *)pci_id->driver_data);
                if (err < 0)
                skl->skl_sst->enable_miscbdcge = skl_enable_miscbdcge;
  
        }
-       if (ebus->mlcap)
+       if (bus->mlcap)
                snd_hdac_ext_bus_get_ml_capabilities(ebus);
  
        /* create device for soc dmic */