ASoC: Intel: Skylake: Add api to retrieve dmic array info from nhlt
authorYong Zhi <yong.zhi@intel.com>
Fri, 27 May 2016 04:30:15 +0000 (21:30 -0700)
committerMark Brown <broonie@kernel.org>
Mon, 30 May 2016 17:16:44 +0000 (18:16 +0100)
Skylake can be configured with either both 2 and 4 channel DMIC
array, or 2 channel DMIC array only, this patch provides an API to
retrieve the DMIC info from nhlt.

Signed-off-by: Yong Zhi <yong.zhi@intel.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/skylake/skl-nhlt.c
sound/soc/intel/skylake/skl-nhlt.h
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.h

index 7d73648e5f9ab22570f67b5153fb74fd36d1985c..3f8e6f0b7eb5d10647f99efe3c1e5b9be751c2e3 100644 (file)
@@ -17,6 +17,7 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  */
+#include <linux/pci.h>
 #include "skl.h"
 
 /* Unique identification for getting NHLT blobs */
@@ -149,6 +150,45 @@ struct nhlt_specific_cfg
        return NULL;
 }
 
+int skl_get_dmic_geo(struct skl *skl)
+{
+       struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
+       struct nhlt_endpoint *epnt;
+       struct nhlt_dmic_array_config *cfg;
+       struct device *dev = &skl->pci->dev;
+       unsigned int dmic_geo = 0;
+       u8 j;
+
+       epnt = (struct nhlt_endpoint *)nhlt->desc;
+
+       for (j = 0; j < nhlt->endpoint_count; j++) {
+               if (epnt->linktype == NHLT_LINK_DMIC) {
+                       cfg = (struct nhlt_dmic_array_config  *)
+                                       (epnt->config.caps);
+                       switch (cfg->array_type) {
+                       case NHLT_MIC_ARRAY_2CH_SMALL:
+                       case NHLT_MIC_ARRAY_2CH_BIG:
+                               dmic_geo |= MIC_ARRAY_2CH;
+                               break;
+
+                       case NHLT_MIC_ARRAY_4CH_1ST_GEOM:
+                       case NHLT_MIC_ARRAY_4CH_L_SHAPED:
+                       case NHLT_MIC_ARRAY_4CH_2ND_GEOM:
+                               dmic_geo |= MIC_ARRAY_4CH;
+                               break;
+
+                       default:
+                               dev_warn(dev, "undefined DMIC array_type 0x%0x\n",
+                                               cfg->array_type);
+
+                       }
+               }
+               epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
+       }
+
+       return dmic_geo;
+}
+
 static void skl_nhlt_trim_space(struct skl *skl)
 {
        char *s = skl->tplg_name;
index 3769f9fefe2bb9f0af6d41c088c3f1755eb2df73..116534e7b3c53244b0eb82d0122ca41aaa4d84ed 100644 (file)
@@ -103,4 +103,26 @@ struct nhlt_resource_desc  {
        u64 length;
 } __packed;
 
+#define MIC_ARRAY_2CH 2
+#define MIC_ARRAY_4CH 4
+
+struct nhlt_tdm_config {
+       u8 virtual_slot;
+       u8 config_type;
+} __packed;
+
+struct nhlt_dmic_array_config {
+       struct nhlt_tdm_config tdm_config;
+       u8 array_type;
+} __packed;
+
+enum {
+       NHLT_MIC_ARRAY_2CH_SMALL = 0xa,
+       NHLT_MIC_ARRAY_2CH_BIG = 0xb,
+       NHLT_MIC_ARRAY_4CH_1ST_GEOM = 0xc,
+       NHLT_MIC_ARRAY_4CH_L_SHAPED = 0xd,
+       NHLT_MIC_ARRAY_4CH_2ND_GEOM = 0xe,
+       NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf,
+};
+
 #endif
index 06d8c263c68f93342931fbcfe447cd986408f2f3..b0f7226b878f856fd277f5c8b232640dfdbdc5f5 100644 (file)
@@ -35,6 +35,8 @@
 #include "skl-sst-dsp.h"
 #include "skl-sst-ipc.h"
 
+static struct skl_machine_pdata skl_dmic_data;
+
 /*
  * initialize the PCI registers
  */
@@ -397,6 +399,10 @@ static int skl_machine_device_register(struct skl *skl, void *driver_data)
                platform_device_put(pdev);
                return -EIO;
        }
+
+       if (mach->pdata)
+               dev_set_drvdata(&pdev->dev, mach->pdata);
+
        skl->i2s_dev = pdev;
 
        return 0;
@@ -666,6 +672,8 @@ static int skl_probe(struct pci_dev *pci,
 
        pci_set_drvdata(skl->pci, ebus);
 
+       skl_dmic_data.dmic_num = skl_get_dmic_geo(skl);
+
        /* check if dsp is there */
        if (ebus->ppcap) {
                err = skl_machine_device_register(skl,
@@ -787,9 +795,9 @@ static void skl_remove(struct pci_dev *pci)
 static struct sst_acpi_mach sst_skl_devdata[] = {
        { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL },
        { "INT343B", "skl_nau88l25_ssm4567_i2s", "intel/dsp_fw_release.bin",
-                               NULL, NULL, NULL },
+                               NULL, NULL, &skl_dmic_data },
        { "MX98357A", "skl_nau88l25_max98357a_i2s", "intel/dsp_fw_release.bin",
-                               NULL, NULL, NULL },
+                               NULL, NULL, &skl_dmic_data },
        {}
 };
 
index 4b4b3876aea9a9ab6a70e2bce86d822c5c30168b..f66be173f86b86c5d45421f124a1c4a97196140d 100644 (file)
@@ -90,6 +90,11 @@ struct skl_dma_params {
        u8 stream_tag;
 };
 
+/* to pass dmic data */
+struct skl_machine_pdata {
+       u32 dmic_num;
+};
+
 struct skl_dsp_ops {
        int id;
        struct skl_dsp_loader_ops (*loader_ops)(void);
@@ -108,6 +113,7 @@ void skl_nhlt_free(struct nhlt_acpi_table *addr);
 struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
                        u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn);
 
+int skl_get_dmic_geo(struct skl *skl);
 int skl_nhlt_update_topology_bin(struct skl *skl);
 int skl_init_dsp(struct skl *skl);
 int skl_free_dsp(struct skl *skl);