Merge branch 'topic/rt5677' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorMark Brown <broonie@kernel.org>
Fri, 16 Jun 2017 16:53:20 +0000 (17:53 +0100)
committerMark Brown <broonie@kernel.org>
Fri, 16 Jun 2017 16:53:20 +0000 (17:53 +0100)
27 files changed:
include/uapi/sound/snd_sst_tokens.h
sound/soc/intel/Kconfig
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/atom/sst/sst.c
sound/soc/intel/atom/sst/sst.h
sound/soc/intel/atom/sst/sst_acpi.c
sound/soc/intel/boards/Makefile
sound/soc/intel/boards/bxt_da7219_max98357a.c
sound/soc/intel/boards/bxt_rt298.c
sound/soc/intel/boards/byt-max98090.c
sound/soc/intel/boards/bytcht_es8316.c [new file with mode: 0644]
sound/soc/intel/boards/bytcht_nocodec.c
sound/soc/intel/boards/bytcr_rt5651.c
sound/soc/intel/boards/cht_bsw_max98090_ti.c
sound/soc/intel/boards/kbl_rt5663_max98927.c [new file with mode: 0644]
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c [new file with mode: 0644]
sound/soc/intel/boards/skl_nau88l25_max98357a.c
sound/soc/intel/boards/skl_nau88l25_ssm4567.c
sound/soc/intel/boards/skl_rt286.c
sound/soc/intel/common/sst-acpi.h
sound/soc/intel/common/sst-match-acpi.c
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl-topology.h
sound/soc/intel/skylake/skl-tplg-interface.h
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.h

index 93392bedcc5870d64514ae84ab00095de4b9971f..89b82f6256ad0a76d8a7d36daae24a9a5df4a434 100644 (file)
@@ -213,8 +213,9 @@ enum SKL_TKNS {
        SKL_TKN_U32_LIB_COUNT,
        SKL_TKN_STR_LIB_NAME,
        SKL_TKN_U32_PMODE,
-       SKL_TKL_U32_D0I3_CAPS,
-       SKL_TKN_MAX = SKL_TKL_U32_D0I3_CAPS,
+       SKL_TKL_U32_D0I3_CAPS, /* Typo added at v4.10 */
+       SKL_TKN_U32_D0I3_CAPS = SKL_TKL_U32_D0I3_CAPS,
+       SKL_TKN_MAX = SKL_TKN_U32_D0I3_CAPS,
 };
 
 #endif
index 67968ef3bbda48528c4bac723252b0cab2684cbb..b301bfff1c09ca06a10692c47352366aa096493b 100644 (file)
@@ -214,6 +214,18 @@ config SND_SOC_INTEL_BYT_CHT_DA7213_MACH
          platforms with DA7212/7213 audio codec.
          If unsure select "N".
 
+config SND_SOC_INTEL_BYT_CHT_ES8316_MACH
+       tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail with ES8316 codec"
+       depends on X86_INTEL_LPSS && I2C && ACPI
+       select SND_SOC_ES8316
+       select SND_SST_ATOM_HIFI2_PLATFORM
+       select SND_SST_IPC_ACPI
+       select SND_SOC_INTEL_SST_MATCH if ACPI
+       help
+         This adds support for ASoC machine driver for Intel(R) Baytrail &
+         Cherrytrail platforms with ES8316 audio codec.
+         If unsure select "N".
+
 config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH
        tristate "ASoC Audio driver for Intel Baytrail & Cherrytrail platform with no codec (MinnowBoard MAX, Up)"
        depends on X86_INTEL_LPSS && I2C && ACPI
@@ -226,6 +238,36 @@ config SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH
          connector
          If unsure select "N".
 
+config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH
+       tristate "ASoC Audio driver for KBL with RT5663 and MAX98927 in I2S Mode"
+       depends on X86_INTEL_LPSS && I2C
+       select SND_SOC_INTEL_SST
+       select SND_SOC_INTEL_SKYLAKE
+       select SND_SOC_RT5663
+       select SND_SOC_MAX98927
+       select SND_SOC_DMIC
+       select SND_SOC_HDAC_HDMI
+       help
+         This adds support for ASoC Onboard Codec I2S machine driver. This will
+         create an alsa sound card for RT5663 + MAX98927.
+         Say Y if you have such a device.
+         If unsure select "N".
+
+config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH
+        tristate "ASoC Audio driver for KBL with RT5663, RT5514 and MAX98927 in I2S Mode"
+        depends on X86_INTEL_LPSS && I2C
+        select SND_SOC_INTEL_SST
+        select SND_SOC_INTEL_SKYLAKE
+        select SND_SOC_RT5663
+        select SND_SOC_RT5514
+        select SND_SOC_MAX98927
+        select SND_SOC_HDAC_HDMI
+        help
+          This adds support for ASoC Onboard Codec I2S machine driver. This will
+          create an alsa sound card for RT5663 + RT5514 + MAX98927.
+          Say Y if you have such a device.
+          If unsure select "N".
+
 config SND_SOC_INTEL_SKYLAKE
        tristate
        select SND_HDA_EXT_CORE
index 21cac1c8dd4cb295cf9013386ea6f4549e14d1bf..b082b31023d59e648034c8d5ffc718c202a72e60 100644 (file)
@@ -690,7 +690,7 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
                        snd_dma_continuous_data(GFP_DMA),
                        SST_MIN_BUFFER, SST_MAX_BUFFER);
                if (retval) {
-                       dev_err(rtd->dev, "dma buffer allocationf fail\n");
+                       dev_err(rtd->dev, "dma buffer allocation failure\n");
                        return retval;
                }
        }
index f9ba71315e335021b34aa18b4030a29b861bcac1..8afdff457579fe9062089fcb6d364cd2185f45ee 100644 (file)
@@ -258,7 +258,7 @@ static ssize_t firmware_version_show(struct device *dev,
 
 }
 
-DEVICE_ATTR_RO(firmware_version);
+static DEVICE_ATTR_RO(firmware_version);
 
 static const struct attribute *sst_fw_version_attrs[] = {
        &dev_attr_firmware_version.attr,
@@ -382,37 +382,6 @@ void sst_context_cleanup(struct intel_sst_drv *ctx)
 }
 EXPORT_SYMBOL_GPL(sst_context_cleanup);
 
-static inline void sst_save_shim64(struct intel_sst_drv *ctx,
-                           void __iomem *shim,
-                           struct sst_shim_regs64 *shim_regs)
-{
-       unsigned long irq_flags;
-
-       spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
-
-       shim_regs->imrx = sst_shim_read64(shim, SST_IMRX);
-       shim_regs->csr = sst_shim_read64(shim, SST_CSR);
-
-
-       spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
-}
-
-static inline void sst_restore_shim64(struct intel_sst_drv *ctx,
-                                     void __iomem *shim,
-                                     struct sst_shim_regs64 *shim_regs)
-{
-       unsigned long irq_flags;
-
-       /*
-        * we only need to restore IMRX for this case, rest will be
-        * initialize by FW or driver when firmware is loaded
-        */
-       spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
-       sst_shim_write64(shim, SST_IMRX, shim_regs->imrx);
-       sst_shim_write64(shim, SST_CSR, shim_regs->csr);
-       spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
-}
-
 void sst_configure_runtime_pm(struct intel_sst_drv *ctx)
 {
        pm_runtime_set_autosuspend_delay(ctx->dev, SST_SUSPEND_DELAY);
@@ -432,8 +401,6 @@ void sst_configure_runtime_pm(struct intel_sst_drv *ctx)
                pm_runtime_set_active(ctx->dev);
        else
                pm_runtime_put_noidle(ctx->dev);
-
-       sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
 }
 EXPORT_SYMBOL_GPL(sst_configure_runtime_pm);
 
@@ -457,8 +424,6 @@ static int intel_sst_runtime_suspend(struct device *dev)
        flush_workqueue(ctx->post_msg_wq);
 
        ctx->ops->reset(ctx);
-       /* save the shim registers because PMC doesn't save state */
-       sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
 
        return ret;
 }
@@ -499,23 +464,23 @@ static int intel_sst_suspend(struct device *dev)
        fw_save = kzalloc(sizeof(*fw_save), GFP_KERNEL);
        if (!fw_save)
                return -ENOMEM;
-       fw_save->iram = kzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
+       fw_save->iram = kvzalloc(ctx->iram_end - ctx->iram_base, GFP_KERNEL);
        if (!fw_save->iram) {
                ret = -ENOMEM;
                goto iram;
        }
-       fw_save->dram = kzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
+       fw_save->dram = kvzalloc(ctx->dram_end - ctx->dram_base, GFP_KERNEL);
        if (!fw_save->dram) {
                ret = -ENOMEM;
                goto dram;
        }
-       fw_save->sram = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
+       fw_save->sram = kvzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
        if (!fw_save->sram) {
                ret = -ENOMEM;
                goto sram;
        }
 
-       fw_save->ddr = kzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
+       fw_save->ddr = kvzalloc(ctx->ddr_end - ctx->ddr_base, GFP_KERNEL);
        if (!fw_save->ddr) {
                ret = -ENOMEM;
                goto ddr;
@@ -530,11 +495,11 @@ static int intel_sst_suspend(struct device *dev)
        ctx->ops->reset(ctx);
        return 0;
 ddr:
-       kfree(fw_save->sram);
+       kvfree(fw_save->sram);
 sram:
-       kfree(fw_save->dram);
+       kvfree(fw_save->dram);
 dram:
-       kfree(fw_save->iram);
+       kvfree(fw_save->iram);
 iram:
        kfree(fw_save);
        return ret;
@@ -562,10 +527,10 @@ static int intel_sst_resume(struct device *dev)
        memcpy32_toio(ctx->mailbox, fw_save->sram, SST_MAILBOX_SIZE);
        memcpy32_toio(ctx->ddr, fw_save->ddr, ctx->ddr_end - ctx->ddr_base);
 
-       kfree(fw_save->sram);
-       kfree(fw_save->dram);
-       kfree(fw_save->iram);
-       kfree(fw_save->ddr);
+       kvfree(fw_save->sram);
+       kvfree(fw_save->dram);
+       kvfree(fw_save->iram);
+       kvfree(fw_save->ddr);
        kfree(fw_save);
 
        block = sst_create_block(ctx, 0, FW_DWNL_ID);
index 5c9a51cc77aa41e8efe123afc517a42867f16baf..e02e2b4cc08f0e657be5096fce99aa3d003db96d 100644 (file)
@@ -317,31 +317,11 @@ struct sst_ipc_reg {
        int ipcd;
 };
 
-struct sst_shim_regs64 {
-       u64 csr;
-       u64 pisr;
-       u64 pimr;
-       u64 isrx;
-       u64 isrd;
-       u64 imrx;
-       u64 imrd;
-       u64 ipcx;
-       u64 ipcd;
-       u64 isrsc;
-       u64 isrlpesc;
-       u64 imrsc;
-       u64 imrlpesc;
-       u64 ipcsc;
-       u64 ipclpesc;
-       u64 clkctl;
-       u64 csr2;
-};
-
 struct sst_fw_save {
-       void *iram;
-       void *dram;
-       void *sram;
-       void *ddr;
+       void *iram;     /* allocated via kvmalloc() */
+       void *dram;     /* allocated via kvmalloc() */
+       void *sram;     /* allocated via kvmalloc() */
+       void *ddr;      /* allocated via kvmalloc() */
 };
 
 /**
@@ -356,7 +336,6 @@ struct sst_fw_save {
  * @dram : SST DRAM pointer
  * @pdata : SST info passed as a part of pci platform data
  * @shim_phy_add : SST shim phy addr
- * @shim_regs64: Struct to save shim registers
  * @ipc_dispatch_list : ipc messages dispatched
  * @rx_list : to copy the process_reply/process_msg from DSP
  * @ipc_post_msg_wq : wq to post IPC messages context
@@ -398,7 +377,6 @@ struct intel_sst_drv {
        unsigned int            ddr_end;
        unsigned int            ddr_base;
        unsigned int            mailbox_recv_offset;
-       struct sst_shim_regs64  *shim_regs64;
        struct list_head        block_list;
        struct list_head        ipc_dispatch_list;
        struct sst_platform_info *pdata;
index dd250b8b26f24c2d09012f9a7a434ae661b5bf49..0e928d54305dad366586c6d2ec56829e5bb75ed2 100644 (file)
@@ -303,8 +303,6 @@ static int sst_acpi_probe(struct platform_device *pdev)
                dev_err(dev, "No matching machine driver found\n");
                return -ENODEV;
        }
-       if (mach->machine_quirk)
-               mach = mach->machine_quirk(mach);
 
        pdata = mach->pdata;
 
@@ -360,23 +358,9 @@ static int sst_acpi_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
-       /* need to save shim registers in BYT */
-       ctx->shim_regs64 = devm_kzalloc(ctx->dev, sizeof(*ctx->shim_regs64),
-                                       GFP_KERNEL);
-       if (!ctx->shim_regs64) {
-               ret = -ENOMEM;
-               goto do_sst_cleanup;
-       }
-
        sst_configure_runtime_pm(ctx);
        platform_set_drvdata(pdev, ctx);
        return ret;
-
-do_sst_cleanup:
-       sst_context_cleanup(ctx);
-       platform_set_drvdata(pdev, NULL);
-       dev_err(ctx->dev, "failed with %d\n", ret);
-       return ret;
 }
 
 /**
@@ -453,12 +437,20 @@ static const struct dmi_system_id cht_table[] = {
 
 
 static struct sst_acpi_mach cht_surface_mach = {
-       "10EC5640", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-                                                               &chv_platform_data };
+       .id = "10EC5640",
+       .drv_name = "cht-bsw-rt5645",
+       .fw_filename = "intel/fw_sst_22a8.bin",
+       .board = "cht-bsw",
+       .pdata = &chv_platform_data,
+};
 
 static struct sst_acpi_mach byt_thinkpad_10 = {
-       "10EC5640", "cht-bsw-rt5672", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
-                                                               &byt_rvp_platform_data };
+       .id = "10EC5640",
+       .drv_name = "cht-bsw-rt5672",
+       .fw_filename = "intel/fw_sst_0f28.bin",
+       .board = "cht-bsw",
+       .pdata = &byt_rvp_platform_data,
+};
 
 static struct sst_acpi_mach *cht_quirk(void *arg)
 {
@@ -486,68 +478,182 @@ static struct sst_acpi_mach *byt_quirk(void *arg)
 
 
 static struct sst_acpi_mach sst_acpi_bytcr[] = {
-       {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", byt_quirk,
-                                               &byt_rvp_platform_data },
-       {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
-                                               &byt_rvp_platform_data },
-       {"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL,
-                                               &byt_rvp_platform_data },
-       {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL,
-                                               &byt_rvp_platform_data },
-       {"DLGS7212", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL,
-                                               &byt_rvp_platform_data },
-       {"DLGS7213", "bytcht_da7213", "intel/fw_sst_0f28.bin", "bytcht_da7213", NULL,
-                                               &byt_rvp_platform_data },
+       {
+               .id = "10EC5640",
+               .drv_name = "bytcr_rt5640",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "bytcr_rt5640",
+               .machine_quirk = byt_quirk,
+               .pdata = &byt_rvp_platform_data,
+       },
+       {
+               .id = "10EC5642",
+               .drv_name = "bytcr_rt5640",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "bytcr_rt5640",
+               .pdata = &byt_rvp_platform_data
+       },
+       {
+               .id = "INTCCFFD",
+               .drv_name = "bytcr_rt5640",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "bytcr_rt5640",
+               .pdata = &byt_rvp_platform_data
+       },
+       {
+               .id = "10EC5651",
+               .drv_name = "bytcr_rt5651",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "bytcr_rt5651",
+               .pdata = &byt_rvp_platform_data
+       },
+       {
+               .id = "DLGS7212",
+               .drv_name = "bytcht_da7213",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "bytcht_da7213",
+               .pdata = &byt_rvp_platform_data
+       },
+       {
+               .id = "DLGS7213",
+               .drv_name = "bytcht_da7213",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "bytcht_da7213",
+               .pdata = &byt_rvp_platform_data
+       },
        /* some Baytrail platforms rely on RT5645, use CHT machine driver */
-       {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
-                                               &byt_rvp_platform_data },
-       {"10EC5648", "cht-bsw-rt5645", "intel/fw_sst_0f28.bin", "cht-bsw", NULL,
-                                               &byt_rvp_platform_data },
+       {
+               .id = "10EC5645",
+               .drv_name = "cht-bsw-rt5645",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "cht-bsw",
+               .pdata = &byt_rvp_platform_data
+       },
+       {
+               .id = "10EC5648",
+               .drv_name = "cht-bsw-rt5645",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "cht-bsw",
+               .pdata = &byt_rvp_platform_data
+       },
 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
        /*
         * This is always last in the table so that it is selected only when
         * enabled explicitly and there is no codec-related information in SSDT
         */
-       {"80860F28", "bytcht_nocodec", "intel/fw_sst_0f28.bin", "bytcht_nocodec", NULL,
-                                               &byt_rvp_platform_data },
+       {
+               .id = "80860F28",
+               .drv_name = "bytcht_nocodec",
+               .fw_filename = "intel/fw_sst_0f28.bin",
+               .board = "bytcht_nocodec",
+               .pdata = &byt_rvp_platform_data
+       },
 #endif
        {},
 };
 
 /* Cherryview-based platforms: CherryTrail and Braswell */
 static struct sst_acpi_mach sst_acpi_chv[] = {
-       {"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-                                               &chv_platform_data },
-       {"10EC5672", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-                                               &chv_platform_data },
-       {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-                                               &chv_platform_data },
-       {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-                                               &chv_platform_data },
-       {"10EC3270", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-                                               &chv_platform_data },
-
-       {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
-                                               &chv_platform_data },
-       {"DLGS7212", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL,
-                                               &chv_platform_data },
-       {"DLGS7213", "bytcht_da7213", "intel/fw_sst_22a8.bin", "bytcht_da7213", NULL,
-                                               &chv_platform_data },
+       {
+               .id = "10EC5670",
+               .drv_name = "cht-bsw-rt5672",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "cht-bsw",
+               .pdata = &chv_platform_data
+       },
+       {
+               .id = "10EC5672",
+               .drv_name = "cht-bsw-rt5672",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "cht-bsw",
+               .pdata = &chv_platform_data
+       },
+       {
+               .id = "10EC5645",
+               .drv_name = "cht-bsw-rt5645",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "cht-bsw",
+               .pdata = &chv_platform_data
+       },
+       {
+               .id = "10EC5650",
+               .drv_name = "cht-bsw-rt5645",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "cht-bsw",
+               .pdata = &chv_platform_data
+       },
+       {
+               .id = "10EC3270",
+               .drv_name = "cht-bsw-rt5645",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "cht-bsw",
+               .pdata = &chv_platform_data
+       },
+
+       {
+               .id = "193C9890",
+               .drv_name = "cht-bsw-max98090",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "cht-bsw",
+               .pdata = &chv_platform_data
+       },
+       {
+               .id = "DLGS7212",
+               .drv_name = "bytcht_da7213",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "bytcht_da7213",
+               .pdata = &chv_platform_data
+       },
+       {
+               .id = "DLGS7213",
+               .drv_name = "bytcht_da7213",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "bytcht_da7213",
+               .pdata = &chv_platform_data
+       },
+       {
+               .id = "ESSX8316",
+               .drv_name = "bytcht_es8316",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "bytcht_es8316",
+               .pdata = &chv_platform_data
+       },
        /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */
-       {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", cht_quirk,
-                                               &chv_platform_data },
-       {"10EC3276", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL,
-                                               &chv_platform_data },
+       {
+               .id = "10EC5640",
+               .drv_name = "bytcr_rt5640",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "bytcr_rt5640",
+               .machine_quirk = cht_quirk,
+               .pdata = &chv_platform_data
+       },
+       {
+               .id = "10EC3276",
+               .drv_name = "bytcr_rt5640",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "bytcr_rt5640",
+               .pdata = &chv_platform_data
+       },
        /* some CHT-T platforms rely on RT5651, use Baytrail machine driver */
-       {"10EC5651", "bytcr_rt5651", "intel/fw_sst_22a8.bin", "bytcr_rt5651", NULL,
-                                               &chv_platform_data },
+       {
+               .id = "10EC5651",
+               .drv_name = "bytcr_rt5651",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "bytcr_rt5651",
+               .pdata = &chv_platform_data
+       },
 #if IS_ENABLED(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH)
        /*
         * This is always last in the table so that it is selected only when
         * enabled explicitly and there is no codec-related information in SSDT
         */
-       {"808622A8", "bytcht_nocodec", "intel/fw_sst_22a8.bin", "bytcht_nocodec", NULL,
-                                               &chv_platform_data },
+       {
+               .id = "808622A8",
+               .drv_name = "bytcht_nocodec",
+               .fw_filename = "intel/fw_sst_22a8.bin",
+               .board = "bytcht_nocodec",
+               .pdata = &chv_platform_data
+       },
 #endif
        {},
 };
index 56896e09445df13f099956fd41852173ca6817cd..a5c5bc5732a2fc62c559fcf194827fce75da2bff 100644 (file)
@@ -11,7 +11,10 @@ snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o
 snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o
 snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o
 snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o
+snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o
 snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o
+snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o
+snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o
 snd-soc-skl_rt286-objs := skl_rt286.o
 snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o
 snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o
@@ -29,7 +32,10 @@ obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH) += snd-soc-sst-cht-bsw-rt5672.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH) += snd-soc-sst-cht-bsw-rt5645.o
 obj-$(CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH) += snd-soc-sst-cht-bsw-max98090_ti.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o
+obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o
 obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o
+obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o
+obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH) += snd-soc-kbl_rt5663_rt5514_max98927.o
 obj-$(CONFIG_SND_SOC_INTEL_SKL_RT286_MACH) += snd-soc-skl_rt286.o
 obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max98357a.o
 obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o
index 3a8c4d954a917ba28ef46caaa1f4c3a18109da34..1429eb391da857e109a17d4fb3ecc0a3f4671a52 100644 (file)
@@ -238,31 +238,31 @@ static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-static unsigned int rates[] = {
+static const unsigned int rates[] = {
        48000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_rates = {
+static const struct snd_pcm_hw_constraint_list constraints_rates = {
        .count = ARRAY_SIZE(rates),
        .list  = rates,
        .mask = 0,
 };
 
-static unsigned int channels[] = {
+static const unsigned int channels[] = {
        DUAL_CHANNEL,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
        .count = ARRAY_SIZE(channels),
        .list = channels,
        .mask = 0,
 };
 
-static unsigned int channels_quad[] = {
+static const unsigned int channels_quad[] = {
        QUAD_CHANNEL,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_channels_quad = {
+static const struct snd_pcm_hw_constraint_list constraints_channels_quad = {
        .count = ARRAY_SIZE(channels_quad),
        .list = channels_quad,
        .mask = 0,
index 1a68d043c803331afeb4c8acabacb3844816e02e..0c3a3cbcb884c080c24275551f5ee6d2e329ad98 100644 (file)
@@ -207,11 +207,11 @@ static const struct snd_soc_ops broxton_rt298_ops = {
        .hw_params = broxton_rt298_hw_params,
 };
 
-static unsigned int rates[] = {
+static const unsigned int rates[] = {
        48000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_rates = {
+static const struct snd_pcm_hw_constraint_list constraints_rates = {
        .count = ARRAY_SIZE(rates),
        .list  = rates,
        .mask = 0,
@@ -222,19 +222,16 @@ static int broxton_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
 {
        struct snd_interval *channels = hw_param_interval(params,
                                                SNDRV_PCM_HW_PARAM_CHANNELS);
-       if (params_channels(params) == 2)
-               channels->min = channels->max = 2;
-       else
-               channels->min = channels->max = 4;
+       channels->min = channels->max = 4;
 
        return 0;
 }
 
-static unsigned int channels_dmic[] = {
-       2, 4,
+static const unsigned int channels_dmic[] = {
+       1, 2, 3, 4,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
        .count = ARRAY_SIZE(channels_dmic),
        .list = channels_dmic,
        .mask = 0,
@@ -256,11 +253,11 @@ static const struct snd_soc_ops broxton_dmic_ops = {
        .startup = broxton_dmic_startup,
 };
 
-static unsigned int channels[] = {
+static const unsigned int channels[] = {
        2,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
        .count = ARRAY_SIZE(channels),
        .list = channels,
        .mask = 0,
index d9f81b8d915dfc268ac53e366d060fd86e5edea8..047be7fa0ce9f86a1462063b18184a8d984e1404 100644 (file)
@@ -67,20 +67,27 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
 
 static struct snd_soc_jack_gpio hs_jack_gpios[] = {
        {
-               .name           = "hp-gpio",
-               .idx            = 0,
+               .name           = "hp",
                .report         = SND_JACK_HEADPHONE | SND_JACK_LINEOUT,
                .debounce_time  = 200,
        },
        {
-               .name           = "mic-gpio",
-               .idx            = 1,
+               .name           = "mic",
                .invert         = 1,
                .report         = SND_JACK_MICROPHONE,
                .debounce_time  = 200,
        },
 };
 
+static const struct acpi_gpio_params hp_gpios = { 0, 0, false };
+static const struct acpi_gpio_params mic_gpios = { 1, 0, false };
+
+static const struct acpi_gpio_mapping acpi_byt_max98090_gpios[] = {
+       { "hp-gpios", &hp_gpios, 1 },
+       { "mic-gpios", &mic_gpios, 1 },
+       {},
+};
+
 static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime)
 {
        int ret;
@@ -140,8 +147,9 @@ static struct snd_soc_card byt_max98090_card = {
 
 static int byt_max98090_probe(struct platform_device *pdev)
 {
-       int ret_val = 0;
+       struct device *dev = &pdev->dev;
        struct byt_max98090_private *priv;
+       int ret_val;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
        if (!priv) {
@@ -149,6 +157,10 @@ static int byt_max98090_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       ret_val = devm_acpi_dev_add_driver_gpios(dev->parent, acpi_byt_max98090_gpios);
+       if (ret_val)
+               dev_dbg(dev, "Unable to add GPIO mapping table\n");
+
        byt_max98090_card.dev = &pdev->dev;
        snd_soc_card_set_drvdata(&byt_max98090_card, priv);
        ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_max98090_card);
@@ -158,7 +170,7 @@ static int byt_max98090_probe(struct platform_device *pdev)
                return ret_val;
        }
 
-       return ret_val;
+       return 0;
 }
 
 static int byt_max98090_remove(struct platform_device *pdev)
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
new file mode 100644 (file)
index 0000000..5263546
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ *  bytcht_es8316.c - ASoc Machine driver for Intel Baytrail/Cherrytrail
+ *                    platforms with Everest ES8316 SoC
+ *
+ *  Copyright (C) 2017 Endless Mobile, Inc.
+ *  Authors: David Yang <yangxiaohua@everest-semi.com>,
+ *           Daniel Drake <drake@endlessm.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <asm/platform_sst_audio.h>
+#include <linux/clk.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "../atom/sst-atom-controls.h"
+#include "../common/sst-acpi.h"
+#include "../common/sst-dsp.h"
+
+struct byt_cht_es8316_private {
+       struct clk *mclk;
+};
+
+#define CODEC_DAI1     "ES8316 HiFi"
+
+static inline struct snd_soc_dai *get_codec_dai(struct snd_soc_card *card)
+{
+       struct snd_soc_pcm_runtime *rtd;
+
+       list_for_each_entry(rtd, &card->rtd_list, list) {
+               if (!strncmp(rtd->codec_dai->name, CODEC_DAI1,
+                            strlen(CODEC_DAI1)))
+                       return rtd->codec_dai;
+       }
+       return NULL;
+}
+
+static const struct snd_soc_dapm_widget byt_cht_es8316_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone", NULL),
+
+       /*
+        * The codec supports two analog microphone inputs. I have only
+        * tested MIC1. A DMIC route could also potentially be added
+        * if such functionality is found on another platform.
+        */
+       SND_SOC_DAPM_MIC("Microphone 1", NULL),
+       SND_SOC_DAPM_MIC("Microphone 2", NULL),
+};
+
+static const struct snd_soc_dapm_route byt_cht_es8316_audio_map[] = {
+       {"MIC1", NULL, "Microphone 1"},
+       {"MIC2", NULL, "Microphone 2"},
+
+       {"Headphone", NULL, "HPOL"},
+       {"Headphone", NULL, "HPOR"},
+
+       {"Playback", NULL, "ssp2 Tx"},
+       {"ssp2 Tx", NULL, "codec_out0"},
+       {"ssp2 Tx", NULL, "codec_out1"},
+       {"codec_in0", NULL, "ssp2 Rx" },
+       {"codec_in1", NULL, "ssp2 Rx" },
+       {"ssp2 Rx", NULL, "Capture"},
+};
+
+static const struct snd_kcontrol_new byt_cht_es8316_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Headphone"),
+       SOC_DAPM_PIN_SWITCH("Microphone 1"),
+       SOC_DAPM_PIN_SWITCH("Microphone 2"),
+};
+
+static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+{
+       struct snd_soc_card *card = runtime->card;
+       struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+       int ret;
+
+       card->dapm.idle_bias_off = true;
+
+       /*
+        * The firmware might enable the clock at boot (this information
+        * may or may not be reflected in the enable clock register).
+        * To change the rate we must disable the clock first to cover these
+        * cases. Due to common clock framework restrictions that do not allow
+        * to disable a clock that has not been enabled, we need to enable
+        * the clock first.
+        */
+       ret = clk_prepare_enable(priv->mclk);
+       if (!ret)
+               clk_disable_unprepare(priv->mclk);
+
+       ret = clk_set_rate(priv->mclk, 19200000);
+       if (ret)
+               dev_err(card->dev, "unable to set MCLK rate\n");
+
+       ret = clk_prepare_enable(priv->mclk);
+       if (ret)
+               dev_err(card->dev, "unable to enable MCLK\n");
+
+       ret = snd_soc_dai_set_sysclk(runtime->codec_dai, 0, 19200000,
+                                    SND_SOC_CLOCK_IN);
+       if (ret < 0) {
+               dev_err(card->dev, "can't set codec clock %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct snd_soc_pcm_stream byt_cht_es8316_dai_params = {
+       .formats = SNDRV_PCM_FMTBIT_S24_LE,
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+};
+
+static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+                           struct snd_pcm_hw_params *params)
+{
+       struct snd_interval *rate = hw_param_interval(params,
+                       SNDRV_PCM_HW_PARAM_RATE);
+       struct snd_interval *channels = hw_param_interval(params,
+                                               SNDRV_PCM_HW_PARAM_CHANNELS);
+       int ret;
+
+       /* The DSP will covert the FE rate to 48k, stereo */
+       rate->min = rate->max = 48000;
+       channels->min = channels->max = 2;
+
+       /* set SSP2 to 24-bit */
+       params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
+
+       /*
+        * Default mode for SSP configuration is TDM 4 slot, override config
+        * with explicit setting to I2S 2ch 24-bit. The word length is set with
+        * dai_set_tdm_slot() since there is no other API exposed
+        */
+       ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
+                               SND_SOC_DAIFMT_I2S     |
+                               SND_SOC_DAIFMT_NB_NF   |
+                               SND_SOC_DAIFMT_CBS_CFS
+               );
+       if (ret < 0) {
+               dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
+       if (ret < 0) {
+               dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int byt_cht_es8316_aif1_startup(struct snd_pcm_substream *substream)
+{
+       return snd_pcm_hw_constraint_single(substream->runtime,
+                       SNDRV_PCM_HW_PARAM_RATE, 48000);
+}
+
+static const struct snd_soc_ops byt_cht_es8316_aif1_ops = {
+       .startup = byt_cht_es8316_aif1_startup,
+};
+
+static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
+       [MERR_DPCM_AUDIO] = {
+               .name = "Audio Port",
+               .stream_name = "Audio",
+               .cpu_dai_name = "media-cpu-dai",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .codec_name = "snd-soc-dummy",
+               .platform_name = "sst-mfld-platform",
+               .nonatomic = true,
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               .dpcm_capture = 1,
+               .ops = &byt_cht_es8316_aif1_ops,
+       },
+
+       [MERR_DPCM_DEEP_BUFFER] = {
+               .name = "Deep-Buffer Audio Port",
+               .stream_name = "Deep-Buffer Audio",
+               .cpu_dai_name = "deepbuffer-cpu-dai",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .codec_name = "snd-soc-dummy",
+               .platform_name = "sst-mfld-platform",
+               .nonatomic = true,
+               .dynamic = 1,
+               .dpcm_playback = 1,
+               .ops = &byt_cht_es8316_aif1_ops,
+       },
+
+       [MERR_DPCM_COMPR] = {
+               .name = "Compressed Port",
+               .stream_name = "Compress",
+               .cpu_dai_name = "compress-cpu-dai",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .codec_name = "snd-soc-dummy",
+               .platform_name = "sst-mfld-platform",
+       },
+
+               /* back ends */
+       {
+               /* Only SSP2 has been tested here, so BYT-CR platforms that
+                * require SSP0 will not work.
+                */
+               .name = "SSP2-Codec",
+               .id = 1,
+               .cpu_dai_name = "ssp2-port",
+               .platform_name = "sst-mfld-platform",
+               .no_pcm = 1,
+               .codec_dai_name = "ES8316 HiFi",
+               .codec_name = "i2c-ESSX8316:00",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                                               | SND_SOC_DAIFMT_CBS_CFS,
+               .be_hw_params_fixup = byt_cht_es8316_codec_fixup,
+               .nonatomic = true,
+               .dpcm_playback = 1,
+               .dpcm_capture = 1,
+               .init = byt_cht_es8316_init,
+       },
+};
+
+
+/* SoC card */
+static struct snd_soc_card byt_cht_es8316_card = {
+       .name = "bytcht-es8316",
+       .owner = THIS_MODULE,
+       .dai_link = byt_cht_es8316_dais,
+       .num_links = ARRAY_SIZE(byt_cht_es8316_dais),
+       .dapm_widgets = byt_cht_es8316_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(byt_cht_es8316_widgets),
+       .dapm_routes = byt_cht_es8316_audio_map,
+       .num_dapm_routes = ARRAY_SIZE(byt_cht_es8316_audio_map),
+       .controls = byt_cht_es8316_controls,
+       .num_controls = ARRAY_SIZE(byt_cht_es8316_controls),
+       .fully_routed = true,
+};
+
+static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       struct byt_cht_es8316_private *priv;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_ATOMIC);
+       if (!priv)
+               return -ENOMEM;
+
+       /* register the soc card */
+       byt_cht_es8316_card.dev = &pdev->dev;
+       snd_soc_card_set_drvdata(&byt_cht_es8316_card, priv);
+
+       priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
+       if (IS_ERR(priv->mclk)) {
+               ret = PTR_ERR(priv->mclk);
+               dev_err(&pdev->dev,
+                       "Failed to get MCLK from pmc_plt_clk_3: %d\n",
+                       ret);
+               return ret;
+       }
+
+       ret = devm_snd_soc_register_card(&pdev->dev, &byt_cht_es8316_card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret);
+               return ret;
+       }
+       platform_set_drvdata(pdev, &byt_cht_es8316_card);
+       return ret;
+}
+
+static struct platform_driver snd_byt_cht_es8316_mc_driver = {
+       .driver = {
+               .name = "bytcht_es8316",
+       },
+       .probe = snd_byt_cht_es8316_mc_probe,
+};
+
+module_platform_driver(snd_byt_cht_es8316_mc_driver);
+MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Machine driver");
+MODULE_AUTHOR("David Yang <yangxiaohua@everest-semi.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:bytcht_es8316");
index 89853eeaaf9dd4f20bdcd61acc10e43c3eb29839..1dd9441806fa31d02c7d3808a35d2d3e8fd304f1 100644 (file)
@@ -85,11 +85,11 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd,
        return 0;
 }
 
-static unsigned int rates_48000[] = {
+static const unsigned int rates_48000[] = {
        48000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_48000 = {
+static const struct snd_pcm_hw_constraint_list constraints_48000 = {
        .count = ARRAY_SIZE(rates_48000),
        .list  = rates_48000,
 };
index 8164bec63bf15b874da49a4406ae9f6124cd776c..4a3516b38c2c9727f7138054cee367ab5ede1205 100644 (file)
@@ -203,11 +203,11 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd,
        return 0;
 }
 
-static unsigned int rates_48000[] = {
+static const unsigned int rates_48000[] = {
        48000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_48000 = {
+static const struct snd_pcm_hw_constraint_list constraints_48000 = {
        .count = ARRAY_SIZE(rates_48000),
        .list  = rates_48000,
 };
index 742bc0d4e681646c969e4c9563decbb291843517..20755ecc7f9ea7e17d1fcdd5096f577929bb1957 100644 (file)
@@ -39,18 +39,6 @@ struct cht_mc_private {
        bool ts3a227e_present;
 };
 
-static inline struct snd_soc_dai *cht_get_codec_dai(struct snd_soc_card *card)
-{
-       struct snd_soc_pcm_runtime *rtd;
-
-       list_for_each_entry(rtd, &card->rtd_list, list) {
-               if (!strncmp(rtd->codec_dai->name, CHT_CODEC_DAI,
-                            strlen(CHT_CODEC_DAI)))
-                       return rtd->codec_dai;
-       }
-       return NULL;
-}
-
 static const struct snd_soc_dapm_widget cht_dapm_widgets[] = {
        SND_SOC_DAPM_HP("Headphone", NULL),
        SND_SOC_DAPM_MIC("Headset Mic", NULL),
diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c
new file mode 100644 (file)
index 0000000..f9ba977
--- /dev/null
@@ -0,0 +1,687 @@
+/*
+ * Intel Kabylake I2S Machine Driver with MAXIM98927
+ * and RT5663 Codecs
+ *
+ * Copyright (C) 2017, Intel Corporation. All rights reserved.
+ *
+ * Modified from:
+ *   Intel Skylake I2S Machine driver
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "../../codecs/rt5663.h"
+#include "../../codecs/hdac_hdmi.h"
+#include "../skylake/skl.h"
+
+#define KBL_REALTEK_CODEC_DAI "rt5663-aif"
+#define KBL_MAXIM_CODEC_DAI "max98927-aif1"
+#define DMIC_CH(p) p->list[p->count-1]
+#define MAXIM_DEV0_NAME "i2c-MX98927:00"
+#define MAXIM_DEV1_NAME "i2c-MX98927:01"
+
+static struct snd_soc_card kabylake_audio_card;
+static const struct snd_pcm_hw_constraint_list *dmic_constraints;
+static struct snd_soc_jack skylake_hdmi[3];
+
+struct kbl_hdmi_pcm {
+       struct list_head head;
+       struct snd_soc_dai *codec_dai;
+       int device;
+};
+
+struct kbl_rt5663_private {
+       struct snd_soc_jack kabylake_headset;
+       struct list_head hdmi_pcm_list;
+};
+
+enum {
+       KBL_DPCM_AUDIO_PB = 0,
+       KBL_DPCM_AUDIO_CP,
+       KBL_DPCM_AUDIO_REF_CP,
+       KBL_DPCM_AUDIO_DMIC_CP,
+       KBL_DPCM_AUDIO_HDMI1_PB,
+       KBL_DPCM_AUDIO_HDMI2_PB,
+       KBL_DPCM_AUDIO_HDMI3_PB,
+};
+
+static const struct snd_kcontrol_new kabylake_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+       SOC_DAPM_PIN_SWITCH("Headset Mic"),
+       SOC_DAPM_PIN_SWITCH("Left Spk"),
+       SOC_DAPM_PIN_SWITCH("Right Spk"),
+};
+
+static const struct snd_soc_dapm_widget kabylake_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+       SND_SOC_DAPM_SPK("Left Spk", NULL),
+       SND_SOC_DAPM_SPK("Right Spk", NULL),
+       SND_SOC_DAPM_MIC("SoC DMIC", NULL),
+       SND_SOC_DAPM_SPK("DP", NULL),
+       SND_SOC_DAPM_SPK("HDMI", NULL),
+
+};
+
+static const struct snd_soc_dapm_route kabylake_map[] = {
+       /* HP jack connectors - unknown if we have jack detection */
+       { "Headphone Jack", NULL, "HPOL" },
+       { "Headphone Jack", NULL, "HPOR" },
+
+       /* speaker */
+       { "Left Spk", NULL, "Left BE_OUT" },
+       { "Right Spk", NULL, "Right BE_OUT" },
+
+       /* other jacks */
+       { "IN1P", NULL, "Headset Mic" },
+       { "IN1N", NULL, "Headset Mic" },
+       { "DMic", NULL, "SoC DMIC" },
+
+       { "HDMI", NULL, "hif5 Output" },
+       { "DP", NULL, "hif6 Output" },
+
+       /* CODEC BE connections */
+       { "Left HiFi Playback", NULL, "ssp0 Tx" },
+       { "Right HiFi Playback", NULL, "ssp0 Tx" },
+       { "ssp0 Tx", NULL, "codec0_out" },
+
+       { "AIF Playback", NULL, "ssp1 Tx" },
+       { "ssp1 Tx", NULL, "codec1_out" },
+
+       { "codec0_in", NULL, "ssp1 Rx" },
+       { "ssp1 Rx", NULL, "AIF Capture" },
+
+       /* DMIC */
+       { "dmic01_hifi", NULL, "DMIC01 Rx" },
+       { "DMIC01 Rx", NULL, "DMIC AIF" },
+
+       { "hifi3", NULL, "iDisp3 Tx"},
+       { "iDisp3 Tx", NULL, "iDisp3_out"},
+       { "hifi2", NULL, "iDisp2 Tx"},
+       { "iDisp2 Tx", NULL, "iDisp2_out"},
+       { "hifi1", NULL, "iDisp1 Tx"},
+       { "iDisp1 Tx", NULL, "iDisp1_out"},
+};
+
+static struct snd_soc_codec_conf max98927_codec_conf[] = {
+       {
+               .dev_name = MAXIM_DEV0_NAME,
+               .name_prefix = "Right",
+       },
+       {
+               .dev_name = MAXIM_DEV1_NAME,
+               .name_prefix = "Left",
+       },
+};
+
+static struct snd_soc_dai_link_component max98927_codec_components[] = {
+       { /* Left */
+               .name = MAXIM_DEV0_NAME,
+               .dai_name = KBL_MAXIM_CODEC_DAI,
+       },
+       { /* Right */
+               .name = MAXIM_DEV1_NAME,
+               .dai_name = KBL_MAXIM_CODEC_DAI,
+       },
+};
+
+static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd)
+{
+       int ret;
+       struct snd_soc_dapm_context *dapm;
+       struct snd_soc_component *component = rtd->cpu_dai->component;
+
+       dapm = snd_soc_component_get_dapm(component);
+       ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
+       if (ret) {
+               dev_err(rtd->dev, "Ref Cap ignore suspend failed %d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+       int ret;
+       struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_codec *codec = rtd->codec;
+
+       /*
+        * Headset buttons map to the google Reference headset.
+        * These can be configured by userspace.
+        */
+       ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack",
+                       SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                       SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset,
+                       NULL, 0);
+       if (ret) {
+               dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
+               return ret;
+       }
+
+       rt5663_set_jack_detect(codec, &ctx->kabylake_headset);
+       ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
+       if (ret) {
+               dev_err(rtd->dev, "SoC DMIC ignore suspend failed %d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_dai *dai = rtd->codec_dai;
+       struct kbl_hdmi_pcm *pcm;
+
+       pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
+       if (!pcm)
+               return -ENOMEM;
+
+       pcm->device = KBL_DPCM_AUDIO_HDMI1_PB;
+       pcm->codec_dai = dai;
+
+       list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
+
+       return 0;
+}
+
+static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_dai *dai = rtd->codec_dai;
+       struct kbl_hdmi_pcm *pcm;
+
+       pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
+       if (!pcm)
+               return -ENOMEM;
+
+       pcm->device = KBL_DPCM_AUDIO_HDMI2_PB;
+       pcm->codec_dai = dai;
+
+       list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
+
+       return 0;
+}
+
+static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_dai *dai = rtd->codec_dai;
+       struct kbl_hdmi_pcm *pcm;
+
+       pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
+       if (!pcm)
+               return -ENOMEM;
+
+       pcm->device = KBL_DPCM_AUDIO_HDMI3_PB;
+       pcm->codec_dai = dai;
+
+       list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
+
+       return 0;
+}
+
+static unsigned int rates[] = {
+       48000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_rates = {
+       .count = ARRAY_SIZE(rates),
+       .list  = rates,
+       .mask = 0,
+};
+
+static unsigned int channels[] = {
+       2,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_channels = {
+       .count = ARRAY_SIZE(channels),
+       .list = channels,
+       .mask = 0,
+};
+
+static int kbl_fe_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       /*
+        * On this platform for PCM device we support,
+        * 48Khz
+        * stereo
+        * 16 bit audio
+        */
+
+       runtime->hw.channels_max = 2;
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                                          &constraints_channels);
+
+       runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+       snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+
+       snd_pcm_hw_constraint_list(runtime, 0,
+                               SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+
+       return 0;
+}
+
+static const struct snd_soc_ops kabylake_rt5663_fe_ops = {
+       .startup = kbl_fe_startup,
+};
+
+static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_interval *rate = hw_param_interval(params,
+                       SNDRV_PCM_HW_PARAM_RATE);
+       struct snd_interval *channels = hw_param_interval(params,
+                       SNDRV_PCM_HW_PARAM_CHANNELS);
+       struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+       /* The ADSP will convert the FE rate to 48k, stereo */
+       rate->min = rate->max = 48000;
+       channels->min = channels->max = 2;
+       /* set SSP1 to 24 bit */
+       snd_mask_none(fmt);
+       snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
+
+       return 0;
+}
+
+static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       int ret;
+
+       ret = snd_soc_dai_set_sysclk(codec_dai,
+                       RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN);
+       /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */
+       rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1);
+
+       if (ret < 0)
+               dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
+
+       return ret;
+}
+
+static struct snd_soc_ops kabylake_rt5663_ops = {
+       .hw_params = kabylake_rt5663_hw_params,
+};
+
+static int kabylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
+               struct snd_pcm_hw_params *params)
+{
+       struct snd_interval *channels = hw_param_interval(params,
+                               SNDRV_PCM_HW_PARAM_CHANNELS);
+
+       if (params_channels(params) == 2 || DMIC_CH(dmic_constraints) == 2)
+               channels->min = channels->max = 2;
+       else
+               channels->min = channels->max = 4;
+
+       return 0;
+}
+
+static unsigned int channels_dmic[] = {
+       2, 4,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+       .count = ARRAY_SIZE(channels_dmic),
+       .list = channels_dmic,
+       .mask = 0,
+};
+
+static const unsigned int dmic_2ch[] = {
+       2,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = {
+       .count = ARRAY_SIZE(dmic_2ch),
+       .list = dmic_2ch,
+       .mask = 0,
+};
+
+static int kabylake_dmic_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->hw.channels_max = DMIC_CH(dmic_constraints);
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                       dmic_constraints);
+
+       return snd_pcm_hw_constraint_list(substream->runtime, 0,
+                       SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+}
+
+static struct snd_soc_ops kabylake_dmic_ops = {
+       .startup = kabylake_dmic_startup,
+};
+
+static unsigned int rates_16000[] = {
+       16000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_16000 = {
+       .count = ARRAY_SIZE(rates_16000),
+       .list  = rates_16000,
+};
+
+static const unsigned int ch_mono[] = {
+       1,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_refcap = {
+       .count = ARRAY_SIZE(ch_mono),
+       .list  = ch_mono,
+};
+
+static int kabylake_refcap_startup(struct snd_pcm_substream *substream)
+{
+       substream->runtime->hw.channels_max = 1;
+       snd_pcm_hw_constraint_list(substream->runtime, 0,
+                                       SNDRV_PCM_HW_PARAM_CHANNELS,
+                                       &constraints_refcap);
+
+       return snd_pcm_hw_constraint_list(substream->runtime, 0,
+                               SNDRV_PCM_HW_PARAM_RATE,
+                               &constraints_16000);
+}
+
+static struct snd_soc_ops skylaye_refcap_ops = {
+       .startup = kabylake_refcap_startup,
+};
+
+/* kabylake digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link kabylake_dais[] = {
+       /* Front End DAI links */
+       [KBL_DPCM_AUDIO_PB] = {
+               .name = "Kbl Audio Port",
+               .stream_name = "Audio",
+               .cpu_dai_name = "System Pin",
+               .platform_name = "0000:00:1f.3",
+               .dynamic = 1,
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .nonatomic = 1,
+               .init = kabylake_rt5663_fe_init,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dpcm_playback = 1,
+               .ops = &kabylake_rt5663_fe_ops,
+       },
+       [KBL_DPCM_AUDIO_CP] = {
+               .name = "Kbl Audio Capture Port",
+               .stream_name = "Audio Record",
+               .cpu_dai_name = "System Pin",
+               .platform_name = "0000:00:1f.3",
+               .dynamic = 1,
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .nonatomic = 1,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dpcm_capture = 1,
+               .ops = &kabylake_rt5663_fe_ops,
+       },
+       [KBL_DPCM_AUDIO_REF_CP] = {
+               .name = "Kbl Audio Reference cap",
+               .stream_name = "Wake on Voice",
+               .cpu_dai_name = "Reference Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .init = NULL,
+               .dpcm_capture = 1,
+               .nonatomic = 1,
+               .dynamic = 1,
+               .ops = &skylaye_refcap_ops,
+       },
+       [KBL_DPCM_AUDIO_DMIC_CP] = {
+               .name = "Kbl Audio DMIC cap",
+               .stream_name = "dmiccap",
+               .cpu_dai_name = "DMIC Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .init = NULL,
+               .dpcm_capture = 1,
+               .nonatomic = 1,
+               .dynamic = 1,
+               .ops = &kabylake_dmic_ops,
+       },
+       [KBL_DPCM_AUDIO_HDMI1_PB] = {
+               .name = "Kbl HDMI Port1",
+               .stream_name = "Hdmi1",
+               .cpu_dai_name = "HDMI1 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [KBL_DPCM_AUDIO_HDMI2_PB] = {
+               .name = "Kbl HDMI Port2",
+               .stream_name = "Hdmi2",
+               .cpu_dai_name = "HDMI2 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [KBL_DPCM_AUDIO_HDMI3_PB] = {
+               .name = "Kbl HDMI Port3",
+               .stream_name = "Hdmi3",
+               .cpu_dai_name = "HDMI3 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dpcm_playback = 1,
+               .init = NULL,
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+
+       /* Back End DAI links */
+       {
+               /* SSP0 - Codec */
+               .name = "SSP0-Codec",
+               .id = 0,
+               .cpu_dai_name = "SSP0 Pin",
+               .platform_name = "0000:00:1f.3",
+               .no_pcm = 1,
+               .codecs = max98927_codec_components,
+               .num_codecs = ARRAY_SIZE(max98927_codec_components),
+               .dai_fmt = SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .ignore_pmdown_time = 1,
+               .be_hw_params_fixup = kabylake_ssp_fixup,
+               .dpcm_playback = 1,
+       },
+       {
+               /* SSP1 - Codec */
+               .name = "SSP1-Codec",
+               .id = 1,
+               .cpu_dai_name = "SSP1 Pin",
+               .platform_name = "0000:00:1f.3",
+               .no_pcm = 1,
+               .codec_name = "i2c-10EC5663:00",
+               .codec_dai_name = KBL_REALTEK_CODEC_DAI,
+               .init = kabylake_rt5663_codec_init,
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .ignore_pmdown_time = 1,
+               .be_hw_params_fixup = kabylake_ssp_fixup,
+               .ops = &kabylake_rt5663_ops,
+               .dpcm_playback = 1,
+               .dpcm_capture = 1,
+       },
+       {
+               .name = "dmic01",
+               .id = 2,
+               .cpu_dai_name = "DMIC01 Pin",
+               .codec_name = "dmic-codec",
+               .codec_dai_name = "dmic-hifi",
+               .platform_name = "0000:00:1f.3",
+               .be_hw_params_fixup = kabylake_dmic_fixup,
+               .ignore_suspend = 1,
+               .dpcm_capture = 1,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp1",
+               .id = 3,
+               .cpu_dai_name = "iDisp1 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi1",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = kabylake_hdmi1_init,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp2",
+               .id = 4,
+               .cpu_dai_name = "iDisp2 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi2",
+               .platform_name = "0000:00:1f.3",
+               .init = kabylake_hdmi2_init,
+               .dpcm_playback = 1,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp3",
+               .id = 5,
+               .cpu_dai_name = "iDisp3 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi3",
+               .platform_name = "0000:00:1f.3",
+               .init = kabylake_hdmi3_init,
+               .dpcm_playback = 1,
+               .no_pcm = 1,
+       },
+};
+
+#define NAME_SIZE      32
+static int kabylake_card_late_probe(struct snd_soc_card *card)
+{
+       struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(card);
+       struct kbl_hdmi_pcm *pcm;
+       int err, i = 0;
+       char jack_name[NAME_SIZE];
+
+       list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
+               snprintf(jack_name, sizeof(jack_name),
+                       "HDMI/DP, pcm=%d Jack", pcm->device);
+               err = snd_soc_card_jack_new(card, jack_name,
+                                       SND_JACK_AVOUT, &skylake_hdmi[i],
+                                       NULL, 0);
+
+               if (err)
+                       return err;
+
+               err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
+                                               &skylake_hdmi[i]);
+               if (err < 0)
+                       return err;
+
+               i++;
+       }
+
+       return 0;
+}
+
+/* kabylake audio machine driver for SPT + RT5663 */
+static struct snd_soc_card kabylake_audio_card = {
+       .name = "kblrt5663max",
+       .owner = THIS_MODULE,
+       .dai_link = kabylake_dais,
+       .num_links = ARRAY_SIZE(kabylake_dais),
+       .controls = kabylake_controls,
+       .num_controls = ARRAY_SIZE(kabylake_controls),
+       .dapm_widgets = kabylake_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets),
+       .dapm_routes = kabylake_map,
+       .num_dapm_routes = ARRAY_SIZE(kabylake_map),
+       .codec_conf = max98927_codec_conf,
+       .num_configs = ARRAY_SIZE(max98927_codec_conf),
+       .fully_routed = true,
+       .late_probe = kabylake_card_late_probe,
+};
+
+static int kabylake_audio_probe(struct platform_device *pdev)
+{
+       struct kbl_rt5663_private *ctx;
+       struct skl_machine_pdata *pdata;
+
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
+       if (!ctx)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
+
+       kabylake_audio_card.dev = &pdev->dev;
+       snd_soc_card_set_drvdata(&kabylake_audio_card, ctx);
+
+       pdata = dev_get_drvdata(&pdev->dev);
+       if (pdata)
+               dmic_constraints = pdata->dmic_num == 2 ?
+                       &constraints_dmic_2ch : &constraints_dmic_channels;
+
+       return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card);
+}
+
+static const struct platform_device_id kbl_board_ids[] = {
+       { .name = "kbl_rt5663_m98927" },
+       { }
+};
+
+static struct platform_driver kabylake_audio = {
+       .probe = kabylake_audio_probe,
+       .driver = {
+               .name = "kbl_rt5663_m98927",
+               .pm = &snd_soc_pm_ops,
+       },
+       .id_table = kbl_board_ids,
+};
+
+module_platform_driver(kabylake_audio)
+
+/* Module information */
+MODULE_DESCRIPTION("Audio Machine driver-RT5663 & MAX98927 in I2S mode");
+MODULE_AUTHOR("Naveen M <naveen.m@intel.com>");
+MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:kbl_rt5663_m98927");
diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
new file mode 100644 (file)
index 0000000..3fe4a08
--- /dev/null
@@ -0,0 +1,640 @@
+/*
+ * Intel Kabylake I2S Machine Driver with MAXIM98927
+ * RT5514 and RT5663 Codecs
+ *
+ * Copyright (C) 2017, Intel Corporation. All rights reserved.
+ *
+ * Modified from:
+ *   Intel Kabylake I2S Machine driver supporting MAXIM98927 and
+ *   RT5663 codecs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "../../codecs/rt5514.h"
+#include "../../codecs/rt5663.h"
+#include "../../codecs/hdac_hdmi.h"
+#include "../skylake/skl.h"
+
+#define KBL_REALTEK_CODEC_DAI "rt5663-aif"
+#define KBL_REALTEK_DMIC_CODEC_DAI "rt5514-aif1"
+#define KBL_MAXIM_CODEC_DAI "max98927-aif1"
+#define MAXIM_DEV0_NAME "i2c-MX98927:00"
+#define MAXIM_DEV1_NAME "i2c-MX98927:01"
+#define RT5514_DEV_NAME "i2c-10EC5514:00"
+#define RT5663_DEV_NAME "i2c-10EC5663:00"
+#define RT5514_AIF1_BCLK_FREQ (48000 * 8 * 16)
+#define RT5514_AIF1_SYSCLK_FREQ 12288000
+#define NAME_SIZE 32
+
+#define DMIC_CH(p) p->list[p->count-1]
+
+
+static struct snd_soc_card kabylake_audio_card;
+static const struct snd_pcm_hw_constraint_list *dmic_constraints;
+
+struct kbl_hdmi_pcm {
+       struct list_head head;
+       struct snd_soc_dai *codec_dai;
+       int device;
+};
+
+struct kbl_codec_private {
+       struct snd_soc_jack kabylake_headset;
+       struct list_head hdmi_pcm_list;
+       struct snd_soc_jack kabylake_hdmi[2];
+};
+
+enum {
+       KBL_DPCM_AUDIO_PB = 0,
+       KBL_DPCM_AUDIO_CP,
+       KBL_DPCM_AUDIO_DMIC_CP,
+       KBL_DPCM_AUDIO_HDMI1_PB,
+       KBL_DPCM_AUDIO_HDMI2_PB,
+};
+
+static const struct snd_kcontrol_new kabylake_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+       SOC_DAPM_PIN_SWITCH("Headset Mic"),
+       SOC_DAPM_PIN_SWITCH("Left Spk"),
+       SOC_DAPM_PIN_SWITCH("Right Spk"),
+       SOC_DAPM_PIN_SWITCH("DMIC"),
+};
+
+static const struct snd_soc_dapm_widget kabylake_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+       SND_SOC_DAPM_SPK("Left Spk", NULL),
+       SND_SOC_DAPM_SPK("Right Spk", NULL),
+       SND_SOC_DAPM_MIC("DMIC", NULL),
+       SND_SOC_DAPM_SPK("DP", NULL),
+       SND_SOC_DAPM_SPK("HDMI", NULL),
+
+};
+
+static const struct snd_soc_dapm_route kabylake_map[] = {
+       /* Headphones */
+       { "Headphone Jack", NULL, "HPOL" },
+       { "Headphone Jack", NULL, "HPOR" },
+
+       /* speaker */
+       { "Left Spk", NULL, "Left BE_OUT" },
+       { "Right Spk", NULL, "Right BE_OUT" },
+
+       /* other jacks */
+       { "IN1P", NULL, "Headset Mic" },
+       { "IN1N", NULL, "Headset Mic" },
+
+       { "HDMI", NULL, "hif5 Output" },
+       { "DP", NULL, "hif6 Output" },
+
+       /* CODEC BE connections */
+       { "Left HiFi Playback", NULL, "ssp0 Tx" },
+       { "Right HiFi Playback", NULL, "ssp0 Tx" },
+       { "ssp0 Tx", NULL, "codec0_out" },
+
+       { "AIF Playback", NULL, "ssp1 Tx" },
+       { "ssp1 Tx", NULL, "codec1_out" },
+
+       { "codec0_in", NULL, "ssp1 Rx" },
+       { "ssp1 Rx", NULL, "AIF Capture" },
+
+       { "codec1_in", NULL, "ssp0 Rx" },
+       { "ssp0 Rx", NULL, "AIF1 Capture" },
+
+       /* DMIC */
+       { "DMIC1L", NULL, "DMIC" },
+       { "DMIC1R", NULL, "DMIC" },
+       { "DMIC2L", NULL, "DMIC" },
+       { "DMIC2R", NULL, "DMIC" },
+
+       { "hifi2", NULL, "iDisp2 Tx" },
+       { "iDisp2 Tx", NULL, "iDisp2_out" },
+       { "hifi1", NULL, "iDisp1 Tx" },
+       { "iDisp1 Tx", NULL, "iDisp1_out" },
+};
+
+static struct snd_soc_codec_conf max98927_codec_conf[] = {
+       {
+               .dev_name = MAXIM_DEV0_NAME,
+               .name_prefix = "Right",
+       },
+       {
+               .dev_name = MAXIM_DEV1_NAME,
+               .name_prefix = "Left",
+       },
+};
+
+static struct snd_soc_dai_link_component ssp0_codec_components[] = {
+       { /* Left */
+               .name = MAXIM_DEV0_NAME,
+               .dai_name = KBL_MAXIM_CODEC_DAI,
+       },
+       { /* Right */
+               .name = MAXIM_DEV1_NAME,
+               .dai_name = KBL_MAXIM_CODEC_DAI,
+       },
+       { /*dmic */
+               .name = RT5514_DEV_NAME,
+               .dai_name = KBL_REALTEK_DMIC_CODEC_DAI,
+       },
+};
+
+static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_dapm_context *dapm;
+       struct snd_soc_component *component = rtd->cpu_dai->component;
+       int ret;
+
+       dapm = snd_soc_component_get_dapm(component);
+       ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture");
+       if (ret)
+               dev_err(rtd->dev, "Ref Cap -Ignore suspend failed = %d\n", ret);
+
+       return ret;
+}
+
+static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+       int ret;
+       struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_codec *codec = rtd->codec;
+
+       /*
+        * Headset buttons map to the google Reference headset.
+        * These can be configured by userspace.
+        */
+       ret = snd_soc_card_jack_new(&kabylake_audio_card, "Headset Jack",
+                       SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                       SND_JACK_BTN_2 | SND_JACK_BTN_3, &ctx->kabylake_headset,
+                       NULL, 0);
+       if (ret) {
+               dev_err(rtd->dev, "Headset Jack creation failed %d\n", ret);
+               return ret;
+       }
+
+       rt5663_set_jack_detect(codec, &ctx->kabylake_headset);
+
+       ret = snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "DMIC");
+       if (ret)
+               dev_err(rtd->dev, "DMIC - Ignore suspend failed = %d\n", ret);
+
+       return ret;
+}
+
+static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device)
+{
+       struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card);
+       struct snd_soc_dai *dai = rtd->codec_dai;
+       struct kbl_hdmi_pcm *pcm;
+
+       pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
+       if (!pcm)
+               return -ENOMEM;
+
+       pcm->device = device;
+       pcm->codec_dai = dai;
+
+       list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
+
+       return 0;
+}
+
+static int kabylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
+{
+       return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI1_PB);
+}
+
+static int kabylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
+{
+       return kabylake_hdmi_init(rtd, KBL_DPCM_AUDIO_HDMI2_PB);
+}
+
+static const unsigned int rates[] = {
+       48000,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_rates = {
+       .count = ARRAY_SIZE(rates),
+       .list  = rates,
+       .mask = 0,
+};
+
+static const unsigned int channels[] = {
+       2,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
+       .count = ARRAY_SIZE(channels),
+       .list = channels,
+       .mask = 0,
+};
+
+static int kbl_fe_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       /*
+        * On this platform for PCM device we support,
+        * 48Khz
+        * stereo
+        * 16 bit audio
+        */
+
+       runtime->hw.channels_max = 2;
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                                          &constraints_channels);
+
+       runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+       snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
+
+       snd_pcm_hw_constraint_list(runtime, 0,
+                               SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+
+       return 0;
+}
+
+static const struct snd_soc_ops kabylake_rt5663_fe_ops = {
+       .startup = kbl_fe_startup,
+};
+
+static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd,
+                                       struct snd_pcm_hw_params *params)
+{
+       struct snd_interval *rate = hw_param_interval(params,
+                       SNDRV_PCM_HW_PARAM_RATE);
+       struct snd_interval *channels = hw_param_interval(params,
+                       SNDRV_PCM_HW_PARAM_CHANNELS);
+       struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+       struct snd_soc_dpcm *dpcm = container_of(
+                       params, struct snd_soc_dpcm, hw_params);
+       struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link;
+       struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link;
+
+       /*
+        * The ADSP will convert the FE rate to 48k, stereo, 24 bit
+        */
+       if (!strcmp(fe_dai_link->name, "Kbl Audio Port") ||
+           !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) {
+               rate->min = rate->max = 48000;
+               channels->min = channels->max = 2;
+               snd_mask_none(fmt);
+               snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
+       } else if (!strcmp(fe_dai_link->name, "Kbl Audio DMIC cap")) {
+               if (params_channels(params) == 2 ||
+                               DMIC_CH(dmic_constraints) == 2)
+                       channels->min = channels->max = 2;
+               else
+                       channels->min = channels->max = 4;
+       }
+       /*
+        * The speaker on the SSP0 supports S16_LE and not S24_LE.
+        * thus changing the mask here
+        */
+       if (!strcmp(be_dai_link->name, "SSP0-Codec"))
+               snd_mask_set(fmt, SNDRV_PCM_FORMAT_S16_LE);
+
+       return 0;
+}
+
+static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       int ret;
+
+       /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */
+       rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1);
+
+       ret = snd_soc_dai_set_sysclk(codec_dai,
+                       RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
+
+       return ret;
+}
+
+static struct snd_soc_ops kabylake_rt5663_ops = {
+       .hw_params = kabylake_rt5663_hw_params,
+};
+
+static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int ret = 0, j;
+
+       for (j = 0; j < rtd->num_codecs; j++) {
+               struct snd_soc_dai *codec_dai = rtd->codec_dais[j];
+
+               if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) {
+                       ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16);
+                       if (ret < 0) {
+                               dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
+                               return ret;
+                       }
+
+                       ret = snd_soc_dai_set_pll(codec_dai, 0,
+                               RT5514_PLL1_S_BCLK, RT5514_AIF1_BCLK_FREQ,
+                                               RT5514_AIF1_SYSCLK_FREQ);
+                       if (ret < 0) {
+                               dev_err(rtd->dev, "set bclk err: %d\n", ret);
+                               return ret;
+                       }
+
+                       ret = snd_soc_dai_set_sysclk(codec_dai,
+                               RT5514_SCLK_S_PLL1, RT5514_AIF1_SYSCLK_FREQ,
+                                                       SND_SOC_CLOCK_IN);
+                       if (ret < 0) {
+                               dev_err(rtd->dev, "set sclk err: %d\n", ret);
+                               return ret;
+                       }
+               }
+               if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME) ||
+                       !strcmp(codec_dai->component->name, MAXIM_DEV1_NAME)) {
+                       ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF0, 3, 8, 16);
+                       if (ret < 0) {
+                               dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
+                               return ret;
+                       }
+               }
+       }
+       return ret;
+}
+
+static struct snd_soc_ops kabylake_ssp0_ops = {
+       .hw_params = kabylake_ssp0_hw_params,
+};
+
+static const unsigned int channels_dmic[] = {
+       4,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+       .count = ARRAY_SIZE(channels_dmic),
+       .list = channels_dmic,
+       .mask = 0,
+};
+
+static const unsigned int dmic_2ch[] = {
+       4,
+};
+
+static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = {
+       .count = ARRAY_SIZE(dmic_2ch),
+       .list = dmic_2ch,
+       .mask = 0,
+};
+
+static int kabylake_dmic_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->hw.channels_max = DMIC_CH(dmic_constraints);
+       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                       dmic_constraints);
+
+       return snd_pcm_hw_constraint_list(substream->runtime, 0,
+                       SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
+}
+
+static struct snd_soc_ops kabylake_dmic_ops = {
+       .startup = kabylake_dmic_startup,
+};
+
+/* kabylake digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link kabylake_dais[] = {
+       /* Front End DAI links */
+       [KBL_DPCM_AUDIO_PB] = {
+               .name = "Kbl Audio Port",
+               .stream_name = "Audio",
+               .cpu_dai_name = "System Pin",
+               .platform_name = "0000:00:1f.3",
+               .dynamic = 1,
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .nonatomic = 1,
+               .init = kabylake_rt5663_fe_init,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dpcm_playback = 1,
+               .ops = &kabylake_rt5663_fe_ops,
+       },
+       [KBL_DPCM_AUDIO_CP] = {
+               .name = "Kbl Audio Capture Port",
+               .stream_name = "Audio Record",
+               .cpu_dai_name = "System Pin",
+               .platform_name = "0000:00:1f.3",
+               .dynamic = 1,
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .nonatomic = 1,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .dpcm_capture = 1,
+               .ops = &kabylake_rt5663_fe_ops,
+       },
+       [KBL_DPCM_AUDIO_DMIC_CP] = {
+               .name = "Kbl Audio DMIC cap",
+               .stream_name = "dmiccap",
+               .cpu_dai_name = "DMIC Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .init = NULL,
+               .dpcm_capture = 1,
+               .nonatomic = 1,
+               .dynamic = 1,
+               .ops = &kabylake_dmic_ops,
+       },
+       [KBL_DPCM_AUDIO_HDMI1_PB] = {
+               .name = "Kbl HDMI Port1",
+               .stream_name = "Hdmi1",
+               .cpu_dai_name = "HDMI1 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       [KBL_DPCM_AUDIO_HDMI2_PB] = {
+               .name = "Kbl HDMI Port2",
+               .stream_name = "Hdmi2",
+               .cpu_dai_name = "HDMI2 Pin",
+               .codec_name = "snd-soc-dummy",
+               .codec_dai_name = "snd-soc-dummy-dai",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = NULL,
+               .trigger = {
+                       SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+               .nonatomic = 1,
+               .dynamic = 1,
+       },
+       /* Back End DAI links */
+       /* single Back end dai for both max speakers and dmic */
+       {
+               /* SSP0 - Codec */
+               .name = "SSP0-Codec",
+               .id = 0,
+               .cpu_dai_name = "SSP0 Pin",
+               .platform_name = "0000:00:1f.3",
+               .no_pcm = 1,
+               .codecs = ssp0_codec_components,
+               .num_codecs = ARRAY_SIZE(ssp0_codec_components),
+               .dai_fmt = SND_SOC_DAIFMT_DSP_B |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .ignore_pmdown_time = 1,
+               .be_hw_params_fixup = kabylake_ssp_fixup,
+               .dpcm_playback = 1,
+               .dpcm_capture = 1,
+               .ops = &kabylake_ssp0_ops,
+       },
+       {
+               .name = "SSP1-Codec",
+               .id = 1,
+               .cpu_dai_name = "SSP1 Pin",
+               .platform_name = "0000:00:1f.3",
+               .no_pcm = 1,
+               .codec_name = RT5663_DEV_NAME,
+               .codec_dai_name = KBL_REALTEK_CODEC_DAI,
+               .init = kabylake_rt5663_codec_init,
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBS_CFS,
+               .ignore_pmdown_time = 1,
+               .be_hw_params_fixup = kabylake_ssp_fixup,
+               .ops = &kabylake_rt5663_ops,
+               .dpcm_playback = 1,
+               .dpcm_capture = 1,
+       },
+       {
+               .name = "iDisp1",
+               .id = 3,
+               .cpu_dai_name = "iDisp1 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi1",
+               .platform_name = "0000:00:1f.3",
+               .dpcm_playback = 1,
+               .init = kabylake_hdmi1_init,
+               .no_pcm = 1,
+       },
+       {
+               .name = "iDisp2",
+               .id = 4,
+               .cpu_dai_name = "iDisp2 Pin",
+               .codec_name = "ehdaudio0D2",
+               .codec_dai_name = "intel-hdmi-hifi2",
+               .platform_name = "0000:00:1f.3",
+               .init = kabylake_hdmi2_init,
+               .dpcm_playback = 1,
+               .no_pcm = 1,
+       },
+};
+
+static int kabylake_card_late_probe(struct snd_soc_card *card)
+{
+       struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(card);
+       struct kbl_hdmi_pcm *pcm;
+       int err, i = 0;
+       char jack_name[NAME_SIZE];
+
+       list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
+               err = snd_soc_card_jack_new(card, jack_name,
+                               SND_JACK_AVOUT, &ctx->kabylake_hdmi[i],
+                               NULL, 0);
+
+               if (err)
+                       return err;
+               err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
+                                               &ctx->kabylake_hdmi[i]);
+               if (err < 0)
+                       return err;
+               i++;
+       }
+
+       return 0;
+}
+
+/*
+ * kabylake audio machine driver for  MAX98927 + RT5514 + RT5663
+ */
+static struct snd_soc_card kabylake_audio_card = {
+       .name = "kbl_r5514_5663_max",
+       .owner = THIS_MODULE,
+       .dai_link = kabylake_dais,
+       .num_links = ARRAY_SIZE(kabylake_dais),
+       .controls = kabylake_controls,
+       .num_controls = ARRAY_SIZE(kabylake_controls),
+       .dapm_widgets = kabylake_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(kabylake_widgets),
+       .dapm_routes = kabylake_map,
+       .num_dapm_routes = ARRAY_SIZE(kabylake_map),
+       .codec_conf = max98927_codec_conf,
+       .num_configs = ARRAY_SIZE(max98927_codec_conf),
+       .fully_routed = true,
+       .late_probe = kabylake_card_late_probe,
+};
+
+static int kabylake_audio_probe(struct platform_device *pdev)
+{
+       struct kbl_codec_private *ctx;
+       struct skl_machine_pdata *pdata;
+
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC);
+       if (!ctx)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
+
+       kabylake_audio_card.dev = &pdev->dev;
+       snd_soc_card_set_drvdata(&kabylake_audio_card, ctx);
+
+       pdata = dev_get_drvdata(&pdev->dev);
+       if (pdata)
+               dmic_constraints = pdata->dmic_num == 2 ?
+                       &constraints_dmic_2ch : &constraints_dmic_channels;
+
+       return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card);
+}
+
+static const struct platform_device_id kbl_board_ids[] = {
+       { .name = "kbl_r5514_5663_max" },
+       { }
+};
+
+static struct platform_driver kabylake_audio = {
+       .probe = kabylake_audio_probe,
+       .driver = {
+               .name = "kbl_r5514_5663_max",
+               .pm = &snd_soc_pm_ops,
+       },
+       .id_table = kbl_board_ids,
+};
+
+module_platform_driver(kabylake_audio)
+
+/* Module information */
+MODULE_DESCRIPTION("Audio Machine driver-RT5663 RT5514 & MAX98927");
+MODULE_AUTHOR("Harsha Priya <harshapriya.n@intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:kbl_r5514_5663_max");
index 3b12bc1fa518e66409764b22b261d0c532af0b9b..5ed0aa27b467d0e4807a6fefecfb216334d49daf 100644 (file)
@@ -266,21 +266,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-static unsigned int rates[] = {
+static const unsigned int rates[] = {
        48000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_rates = {
+static const struct snd_pcm_hw_constraint_list constraints_rates = {
        .count = ARRAY_SIZE(rates),
        .list  = rates,
        .mask = 0,
 };
 
-static unsigned int channels[] = {
+static const unsigned int channels[] = {
        2,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
        .count = ARRAY_SIZE(channels),
        .list = channels,
        .mask = 0,
@@ -348,11 +348,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
        return 0;
 }
 
-static unsigned int channels_dmic[] = {
+static const unsigned int channels_dmic[] = {
        2, 4,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
        .count = ARRAY_SIZE(channels_dmic),
        .list = channels_dmic,
        .mask = 0,
@@ -384,11 +384,11 @@ static const struct snd_soc_ops skylake_dmic_ops = {
        .startup = skylake_dmic_startup,
 };
 
-static unsigned int rates_16000[] = {
+static const unsigned int rates_16000[] = {
        16000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_16000 = {
+static const struct snd_pcm_hw_constraint_list constraints_16000 = {
        .count = ARRAY_SIZE(rates_16000),
        .list  = rates_16000,
 };
index eb7751b0599bbcb1ea343b7c284f5b28ce238aae..01b8b140bb0874af87fa3ef98a4213bf7f6c74a5 100644 (file)
@@ -297,21 +297,21 @@ static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-static unsigned int rates[] = {
+static const unsigned int rates[] = {
        48000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_rates = {
+static const struct snd_pcm_hw_constraint_list constraints_rates = {
        .count = ARRAY_SIZE(rates),
        .list  = rates,
        .mask = 0,
 };
 
-static unsigned int channels[] = {
+static const unsigned int channels[] = {
        2,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
        .count = ARRAY_SIZE(channels),
        .list = channels,
        .mask = 0,
@@ -397,11 +397,11 @@ static const struct snd_soc_ops skylake_nau8825_ops = {
        .hw_params = skylake_nau8825_hw_params,
 };
 
-static unsigned int channels_dmic[] = {
+static const unsigned int channels_dmic[] = {
        2, 4,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
        .count = ARRAY_SIZE(channels_dmic),
        .list = channels_dmic,
        .mask = 0,
@@ -433,11 +433,11 @@ static const struct snd_soc_ops skylake_dmic_ops = {
        .startup = skylake_dmic_startup,
 };
 
-static unsigned int rates_16000[] = {
+static const unsigned int rates_16000[] = {
        16000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_16000 = {
+static const struct snd_pcm_hw_constraint_list constraints_16000 = {
        .count = ARRAY_SIZE(rates_16000),
        .list  = rates_16000,
 };
index f5ab7b8d51d1ceedb1e2e09033d5a68e97aad435..e08c71625fd0d4d418620a7bd958d5b7eb6fe78f 100644 (file)
@@ -165,21 +165,21 @@ static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-static unsigned int rates[] = {
+static const unsigned int rates[] = {
        48000,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_rates = {
+static const struct snd_pcm_hw_constraint_list constraints_rates = {
        .count = ARRAY_SIZE(rates),
        .list  = rates,
        .mask = 0,
 };
 
-static unsigned int channels[] = {
+static const unsigned int channels[] = {
        2,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_channels = {
        .count = ARRAY_SIZE(channels),
        .list = channels,
        .mask = 0,
@@ -264,11 +264,11 @@ static int skylake_dmic_fixup(struct snd_soc_pcm_runtime *rtd,
        return 0;
 }
 
-static unsigned int channels_dmic[] = {
+static const unsigned int channels_dmic[] = {
        2, 4,
 };
 
-static struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
+static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
        .count = ARRAY_SIZE(channels_dmic),
        .list = channels_dmic,
        .mask = 0,
index 214e000667ae0a2725f951e0956a39dbc37d8f10..afe9b87b8bd558065153da3a5c7ac4e7a7b536e7 100644 (file)
@@ -43,6 +43,9 @@ static inline bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
 /* acpi match */
 struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines);
 
+/* acpi check hid */
+bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN]);
+
 /* Descriptor for SST ASoC machine driver */
 struct sst_acpi_mach {
        /* ACPI ID for the matching machine driver. Audio codec for instance */
@@ -55,5 +58,25 @@ struct sst_acpi_mach {
        /* board name */
        const char *board;
        struct sst_acpi_mach * (*machine_quirk)(void *arg);
+       const void *quirk_data;
        void *pdata;
 };
+
+#define SST_ACPI_MAX_CODECS 3
+
+/**
+ * struct sst_codecs: Structure to hold secondary codec information apart from
+ * the matched one, this data will be passed to the quirk function to match
+ * with the ACPI detected devices
+ *
+ * @num_codecs: number of secondary codecs used in the platform
+ * @codecs: holds the codec IDs
+ *
+ */
+struct sst_codecs {
+       int num_codecs;
+       u8 codecs[SST_ACPI_MAX_CODECS][ACPI_ID_LEN];
+};
+
+/* check all codecs */
+struct sst_acpi_mach *sst_acpi_codec_list(void *arg);
index 1070f3ad23e50e1e495824ca13f8d7176ca0b05e..56d26f36a3cba16f25217b465cfe4704c674e3c9 100644 (file)
@@ -63,16 +63,33 @@ static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
        return AE_OK;
 }
 
+bool sst_acpi_check_hid(const u8 hid[ACPI_ID_LEN])
+{
+       acpi_status status;
+       bool found = false;
+
+       status = acpi_get_devices(hid, sst_acpi_mach_match, &found, NULL);
+
+       if (ACPI_FAILURE(status))
+               return false;
+
+       return found;
+}
+EXPORT_SYMBOL_GPL(sst_acpi_check_hid);
+
 struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines)
 {
        struct sst_acpi_mach *mach;
-       bool found = false;
 
-       for (mach = machines; mach->id[0]; mach++)
-               if (ACPI_SUCCESS(acpi_get_devices(mach->id,
-                                                 sst_acpi_mach_match,
-                                                 &found, NULL)) && found)
-                       return mach;
+       for (mach = machines; mach->id[0]; mach++) {
+               if (sst_acpi_check_hid(mach->id) == true) {
+                       if (mach->machine_quirk == NULL)
+                               return mach;
+
+                       if (mach->machine_quirk(mach) != NULL)
+                               return mach;
+               }
+       }
        return NULL;
 }
 EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
@@ -134,5 +151,23 @@ bool sst_acpi_find_package_from_hid(const u8 hid[ACPI_ID_LEN],
 }
 EXPORT_SYMBOL_GPL(sst_acpi_find_package_from_hid);
 
+struct sst_acpi_mach *sst_acpi_codec_list(void *arg)
+{
+       struct sst_acpi_mach *mach = arg;
+       struct sst_codecs *codec_list = (struct sst_codecs *) mach->quirk_data;
+       int i;
+
+       if (mach->quirk_data == NULL)
+               return mach;
+
+       for (i = 0; i < codec_list->num_codecs; i++) {
+               if (sst_acpi_check_hid(codec_list->codecs[i]) != true)
+                       return NULL;
+       }
+
+       return mach;
+}
+EXPORT_SYMBOL_GPL(sst_acpi_codec_list);
+
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Intel Common ACPI Match module");
index ab1adc0c9cc3296e1f6d28d270916f36f8b41dd8..5a465020ebd883fbaea8a25d4c9f4be3b4be205e 100644 (file)
@@ -707,6 +707,7 @@ static u16 skl_get_module_param_size(struct skl_sst *ctx,
                return param_size;
 
        case SKL_MODULE_TYPE_BASE_OUTFMT:
+       case SKL_MODULE_TYPE_MIC_SELECT:
        case SKL_MODULE_TYPE_KPB:
                return sizeof(struct skl_base_outfmt_cfg);
 
@@ -761,6 +762,7 @@ static int skl_set_module_format(struct skl_sst *ctx,
                break;
 
        case SKL_MODULE_TYPE_BASE_OUTFMT:
+       case SKL_MODULE_TYPE_MIC_SELECT:
        case SKL_MODULE_TYPE_KPB:
                skl_set_base_outfmt_format(ctx, module_config, *param_data);
                break;
index 3a99712e44a80df81f7ad27d52e69501f617e948..212cee71d5869ac2a7829602f4496b423561ca80 100644 (file)
 #define SKL_IN_DIR_BIT_MASK            BIT(0)
 #define SKL_PIN_COUNT_MASK             GENMASK(7, 4)
 
+static const int mic_mono_list[] = {
+0, 1, 2, 3,
+};
+static const int mic_stereo_list[][SKL_CH_STEREO] = {
+{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3},
+};
+static const int mic_trio_list[][SKL_CH_TRIO] = {
+{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3},
+};
+static const int mic_quatro_list[][SKL_CH_QUATRO] = {
+{0, 1, 2, 3},
+};
+
 void skl_tplg_d0i3_get(struct skl *skl, enum d0i3_capability caps)
 {
        struct skl_d0i3_data *d0i3 =  &skl->skl_sst->d0i3;
@@ -1314,6 +1327,111 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int skl_tplg_mic_control_get(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+       struct skl_module_cfg *mconfig = w->priv;
+       struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
+       u32 ch_type = *((u32 *)ec->dobj.private);
+
+       if (mconfig->dmic_ch_type == ch_type)
+               ucontrol->value.enumerated.item[0] =
+                                       mconfig->dmic_ch_combo_index;
+       else
+               ucontrol->value.enumerated.item[0] = 0;
+
+       return 0;
+}
+
+static int skl_fill_mic_sel_params(struct skl_module_cfg *mconfig,
+       struct skl_mic_sel_config *mic_cfg, struct device *dev)
+{
+       struct skl_specific_cfg *sp_cfg = &mconfig->formats_config;
+
+       sp_cfg->caps_size = sizeof(struct skl_mic_sel_config);
+       sp_cfg->set_params = SKL_PARAM_SET;
+       sp_cfg->param_id = 0x00;
+       if (!sp_cfg->caps) {
+               sp_cfg->caps = devm_kzalloc(dev, sp_cfg->caps_size, GFP_KERNEL);
+               if (!sp_cfg->caps)
+                       return -ENOMEM;
+       }
+
+       mic_cfg->mic_switch = SKL_MIC_SEL_SWITCH;
+       mic_cfg->flags = 0;
+       memcpy(sp_cfg->caps, mic_cfg, sp_cfg->caps_size);
+
+       return 0;
+}
+
+static int skl_tplg_mic_control_set(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol);
+       struct skl_module_cfg *mconfig = w->priv;
+       struct skl_mic_sel_config mic_cfg = {0};
+       struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
+       u32 ch_type = *((u32 *)ec->dobj.private);
+       const int *list;
+       u8 in_ch, out_ch, index;
+
+       mconfig->dmic_ch_type = ch_type;
+       mconfig->dmic_ch_combo_index = ucontrol->value.enumerated.item[0];
+
+       /* enum control index 0 is INVALID, so no channels to be set */
+       if (mconfig->dmic_ch_combo_index == 0)
+               return 0;
+
+       /* No valid channel selection map for index 0, so offset by 1 */
+       index = mconfig->dmic_ch_combo_index - 1;
+
+       switch (ch_type) {
+       case SKL_CH_MONO:
+               if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_mono_list))
+                       return -EINVAL;
+
+               list = &mic_mono_list[index];
+               break;
+
+       case SKL_CH_STEREO:
+               if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_stereo_list))
+                       return -EINVAL;
+
+               list = mic_stereo_list[index];
+               break;
+
+       case SKL_CH_TRIO:
+               if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_trio_list))
+                       return -EINVAL;
+
+               list = mic_trio_list[index];
+               break;
+
+       case SKL_CH_QUATRO:
+               if (mconfig->dmic_ch_combo_index > ARRAY_SIZE(mic_quatro_list))
+                       return -EINVAL;
+
+               list = mic_quatro_list[index];
+               break;
+
+       default:
+               dev_err(w->dapm->dev,
+                               "Invalid channel %d for mic_select module\n",
+                               ch_type);
+               return -EINVAL;
+
+       }
+
+       /* channel type enum map to number of chanels for that type */
+       for (out_ch = 0; out_ch < ch_type; out_ch++) {
+               in_ch = list[out_ch];
+               mic_cfg.blob[out_ch][in_ch] = SKL_DEFAULT_MIC_SEL_GAIN;
+       }
+
+       return skl_fill_mic_sel_params(mconfig, &mic_cfg, w->dapm->dev);
+}
+
 /*
  * Fill the dma id for host and link. In case of passthrough
  * pipeline, this will both host and link in the same
@@ -1666,6 +1784,14 @@ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = {
                                        skl_tplg_tlv_control_set},
 };
 
+static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
+       {
+               .id = SKL_CONTROL_TYPE_MIC_SELECT,
+               .get = skl_tplg_mic_control_get,
+               .put = skl_tplg_mic_control_set,
+       },
+};
+
 static int skl_tplg_fill_pipe_tkn(struct device *dev,
                        struct skl_pipe *pipe, u32 tkn,
                        u32 tkn_val)
@@ -1995,7 +2121,7 @@ static int skl_tplg_get_token(struct device *dev,
                mconfig->converter = tkn_elem->value;
                break;
 
-       case SKL_TKL_U32_D0I3_CAPS:
+       case SKL_TKN_U32_D0I3_CAPS:
                mconfig->d0i3_caps = tkn_elem->value;
                break;
 
@@ -2070,6 +2196,16 @@ static int skl_tplg_get_token(struct device *dev,
 
                break;
 
+       case SKL_TKN_U32_CAPS_SET_PARAMS:
+               mconfig->formats_config.set_params =
+                               tkn_elem->value;
+               break;
+
+       case SKL_TKN_U32_CAPS_PARAMS_ID:
+               mconfig->formats_config.param_id =
+                               tkn_elem->value;
+               break;
+
        case SKL_TKN_U32_PROC_DOMAIN:
                mconfig->domain =
                        tkn_elem->value;
@@ -2147,7 +2283,7 @@ static int skl_tplg_get_tokens(struct device *dev,
                tuple_size += tkn_count * sizeof(*tkn_elem);
        }
 
-       return 0;
+       return off;
 }
 
 /*
@@ -2198,10 +2334,11 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
        num_blocks = ret;
 
        off += array->size;
-       array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off);
-
        /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */
        while (num_blocks > 0) {
+               array = (struct snd_soc_tplg_vendor_array *)
+                               (tplg_w->priv.data + off);
+
                ret = skl_tplg_get_desc_blocks(dev, array);
 
                if (ret < 0)
@@ -2237,7 +2374,9 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w,
                                memcpy(mconfig->formats_config.caps, data,
                                        mconfig->formats_config.caps_size);
                        --num_blocks;
+                       ret = mconfig->formats_config.caps_size;
                }
+               off += ret;
        }
 
        return 0;
@@ -2377,14 +2516,34 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
        return 0;
 }
 
+static int skl_init_enum_data(struct device *dev, struct soc_enum *se,
+                               struct snd_soc_tplg_enum_control *ec)
+{
+
+       void *data;
+
+       if (ec->priv.size) {
+               data = devm_kzalloc(dev, sizeof(ec->priv.size), GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+               memcpy(data, ec->priv.data, ec->priv.size);
+               se->dobj.private = data;
+       }
+
+       return 0;
+
+}
+
 static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
                                struct snd_kcontrol_new *kctl,
                                struct snd_soc_tplg_ctl_hdr *hdr)
 {
        struct soc_bytes_ext *sb;
        struct snd_soc_tplg_bytes_control *tplg_bc;
+       struct snd_soc_tplg_enum_control *tplg_ec;
        struct hdac_ext_bus *ebus  = snd_soc_component_get_drvdata(cmpnt);
        struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct soc_enum *se;
 
        switch (hdr->ops.info) {
        case SND_SOC_TPLG_CTL_BYTES:
@@ -2398,6 +2557,17 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
                }
                break;
 
+       case SND_SOC_TPLG_CTL_ENUM:
+               tplg_ec = container_of(hdr,
+                               struct snd_soc_tplg_enum_control, hdr);
+               if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) {
+                       se = (struct soc_enum *)kctl->private_value;
+                       if (tplg_ec->priv.size)
+                               return skl_init_enum_data(bus->dev, se,
+                                               tplg_ec);
+               }
+               break;
+
        default:
                dev_warn(bus->dev, "Control load not supported %d:%d:%d\n",
                        hdr->ops.get, hdr->ops.put, hdr->ops.info);
@@ -2626,6 +2796,8 @@ static struct snd_soc_tplg_ops skl_tplg_ops  = {
        .control_load = skl_tplg_control_load,
        .bytes_ext_ops = skl_tlv_ops,
        .bytes_ext_ops_count = ARRAY_SIZE(skl_tlv_ops),
+       .io_ops = skl_tplg_kcontrol_ops,
+       .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops),
        .manifest = skl_manifest_load,
 };
 
index cc64d6bdb4f6c4859621619daa3a9077a96a8dc7..3f51a0a00093c73a8ba63f369e4d30aa58980995 100644 (file)
 #define MODULE_MAX_IN_PINS     8
 #define MODULE_MAX_OUT_PINS    8
 
+#define SKL_MIC_CH_SUPPORT     4
+#define SKL_MIC_MAX_CH_SUPPORT 8
+#define SKL_DEFAULT_MIC_SEL_GAIN       0x3FF
+#define SKL_MIC_SEL_SWITCH     0x3
+
 enum skl_channel_index {
        SKL_CHANNEL_LEFT = 0,
        SKL_CHANNEL_RIGHT = 1,
@@ -309,6 +314,8 @@ struct skl_module_cfg {
        u8 dev_type;
        u8 dma_id;
        u8 time_slot;
+       u8 dmic_ch_combo_index;
+       u32 dmic_ch_type;
        u32 params_fixup;
        u32 converter;
        u32 vbus_id;
@@ -342,6 +349,19 @@ struct skl_module_deferred_bind {
        struct list_head node;
 };
 
+struct skl_mic_sel_config {
+       u16 mic_switch;
+       u16 flags;
+       u16 blob[SKL_MIC_MAX_CH_SUPPORT][SKL_MIC_MAX_CH_SUPPORT];
+} __packed;
+
+enum skl_channel {
+       SKL_CH_MONO = 1,
+       SKL_CH_STEREO = 2,
+       SKL_CH_TRIO = 3,
+       SKL_CH_QUATRO = 4,
+};
+
 static inline struct skl *get_skl_ctx(struct device *dev)
 {
        struct hdac_ext_bus *ebus = dev_get_drvdata(dev);
index 7a2febf99019be78f3f9c47c9c69edebafbefc20..f8d1749a2e0c89df8b1a95fd8b6729623ba8b8a1 100644 (file)
@@ -24,6 +24,7 @@
  * SST types start at higher to avoid any overlapping in future
  */
 #define SKL_CONTROL_TYPE_BYTE_TLV      0x100
+#define SKL_CONTROL_TYPE_MIC_SELECT    0x102
 
 #define HDA_SST_CFG_MAX        900 /* size of copier cfg*/
 #define MAX_IN_QUEUE 8
@@ -82,6 +83,7 @@ enum skl_module_type {
        SKL_MODULE_TYPE_ALGO,
        SKL_MODULE_TYPE_BASE_OUTFMT,
        SKL_MODULE_TYPE_KPB,
+       SKL_MODULE_TYPE_MIC_SELECT,
 };
 
 enum skl_core_affinity {
index 6df3b317a4768e008b539f0a619308e9545a3992..e761550c6dad5baec9dee1ae18a22744e61443ba 100644 (file)
@@ -410,7 +410,7 @@ static int skl_free(struct hdac_ext_bus *ebus)
        struct skl *skl  = ebus_to_skl(ebus);
        struct hdac_bus *bus = ebus_to_hbus(ebus);
 
-       skl->init_failed = 1; /* to be sure */
+       skl->init_done = 0; /* to be sure */
 
        snd_hdac_ext_stop_streams(ebus);
 
@@ -428,8 +428,10 @@ static int skl_free(struct hdac_ext_bus *ebus)
 
        snd_hdac_ext_bus_exit(ebus);
 
+       cancel_work_sync(&skl->probe_work);
        if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
                snd_hdac_i915_exit(&ebus->bus);
+
        return 0;
 }
 
@@ -566,6 +568,84 @@ static const struct hdac_bus_ops bus_core_ops = {
        .get_response = snd_hdac_bus_get_response,
 };
 
+static int skl_i915_init(struct hdac_bus *bus)
+{
+       int err;
+
+       /*
+        * The HDMI codec is in GPU so we need to ensure that it is powered
+        * up and ready for probe
+        */
+       err = snd_hdac_i915_init(bus);
+       if (err < 0)
+               return err;
+
+       err = snd_hdac_display_power(bus, true);
+       if (err < 0)
+               dev_err(bus->dev, "Cannot turn on display power on i915\n");
+
+       return err;
+}
+
+static void skl_probe_work(struct work_struct *work)
+{
+       struct skl *skl = container_of(work, struct skl, probe_work);
+       struct hdac_ext_bus *ebus = &skl->ebus;
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct hdac_ext_link *hlink = NULL;
+       int err;
+
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               err = skl_i915_init(bus);
+               if (err < 0)
+                       return;
+       }
+
+       err = skl_init_chip(bus, true);
+       if (err < 0) {
+               dev_err(bus->dev, "Init chip failed with err: %d\n", err);
+               goto out_err;
+       }
+
+       /* codec detection */
+       if (!bus->codec_mask)
+               dev_info(bus->dev, "no hda codecs found!\n");
+
+       /* create codec instances */
+       err = skl_codec_create(ebus);
+       if (err < 0)
+               goto out_err;
+
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               err = snd_hdac_display_power(bus, false);
+               if (err < 0) {
+                       dev_err(bus->dev, "Cannot turn off display power on i915\n");
+                       return;
+               }
+       }
+
+       /* register platform dai and controls */
+       err = skl_platform_register(bus->dev);
+       if (err < 0)
+               return;
+       /*
+        * we are done probing so decrement link counts
+        */
+       list_for_each_entry(hlink, &ebus->hlink_list, list)
+               snd_hdac_ext_bus_link_put(ebus, hlink);
+
+       /* configure PM */
+       pm_runtime_put_noidle(bus->dev);
+       pm_runtime_allow(bus->dev);
+       skl->init_done = 1;
+
+       return;
+
+out_err:
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+               err = snd_hdac_display_power(bus, false);
+}
+
 /*
  * constructor
  */
@@ -593,6 +673,7 @@ static int skl_create(struct pci_dev *pci,
        snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops);
        ebus->bus.use_posbuf = 1;
        skl->pci = pci;
+       INIT_WORK(&skl->probe_work, skl_probe_work);
 
        ebus->bus.bdl_pos_adj = 0;
 
@@ -601,27 +682,6 @@ static int skl_create(struct pci_dev *pci,
        return 0;
 }
 
-static int skl_i915_init(struct hdac_bus *bus)
-{
-       int err;
-
-       /*
-        * The HDMI codec is in GPU so we need to ensure that it is powered
-        * up and ready for probe
-        */
-       err = snd_hdac_i915_init(bus);
-       if (err < 0)
-               return err;
-
-       err = snd_hdac_display_power(bus, true);
-       if (err < 0) {
-               dev_err(bus->dev, "Cannot turn on display power on i915\n");
-               return err;
-       }
-
-       return err;
-}
-
 static int skl_first_init(struct hdac_ext_bus *ebus)
 {
        struct skl *skl = ebus_to_skl(ebus);
@@ -684,20 +744,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
        /* initialize chip */
        skl_init_pci(skl);
 
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-               err = skl_i915_init(bus);
-               if (err < 0)
-                       return err;
-       }
-
-       skl_init_chip(bus, true);
-
-       /* codec detection */
-       if (!bus->codec_mask) {
-               dev_info(bus->dev, "no hda codecs found!\n");
-       }
-
-       return 0;
+       return skl_init_chip(bus, true);
 }
 
 static int skl_probe(struct pci_dev *pci,
@@ -706,7 +753,6 @@ static int skl_probe(struct pci_dev *pci,
        struct skl *skl;
        struct hdac_ext_bus *ebus = NULL;
        struct hdac_bus *bus = NULL;
-       struct hdac_ext_link *hlink = NULL;
        int err;
 
        /* we use ext core ops, so provide NULL for ops here */
@@ -729,7 +775,7 @@ static int skl_probe(struct pci_dev *pci,
 
        if (skl->nhlt == NULL) {
                err = -ENODEV;
-               goto out_display_power_off;
+               goto out_free;
        }
 
        err = skl_nhlt_create_sysfs(skl);
@@ -760,56 +806,24 @@ static int skl_probe(struct pci_dev *pci,
        if (bus->mlcap)
                snd_hdac_ext_bus_get_ml_capabilities(ebus);
 
+       snd_hdac_bus_stop_chip(bus);
+
        /* create device for soc dmic */
        err = skl_dmic_device_register(skl);
        if (err < 0)
                goto out_dsp_free;
 
-       /* register platform dai and controls */
-       err = skl_platform_register(bus->dev);
-       if (err < 0)
-               goto out_dmic_free;
-
-       /* create codec instances */
-       err = skl_codec_create(ebus);
-       if (err < 0)
-               goto out_unregister;
-
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-               err = snd_hdac_display_power(bus, false);
-               if (err < 0) {
-                       dev_err(bus->dev, "Cannot turn off display power on i915\n");
-                       return err;
-               }
-       }
-
-       /*
-        * we are done probling so decrement link counts
-        */
-       list_for_each_entry(hlink, &ebus->hlink_list, list)
-               snd_hdac_ext_bus_link_put(ebus, hlink);
-
-       /* configure PM */
-       pm_runtime_put_noidle(bus->dev);
-       pm_runtime_allow(bus->dev);
+       schedule_work(&skl->probe_work);
 
        return 0;
 
-out_unregister:
-       skl_platform_unregister(bus->dev);
-out_dmic_free:
-       skl_dmic_device_unregister(skl);
 out_dsp_free:
        skl_free_dsp(skl);
 out_mach_free:
        skl_machine_device_unregister(skl);
 out_nhlt_free:
        skl_nhlt_free(skl->nhlt);
-out_display_power_off:
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, false);
 out_free:
-       skl->init_failed = 1;
        skl_free(ebus);
 
        return err;
@@ -828,7 +842,7 @@ static void skl_shutdown(struct pci_dev *pci)
 
        skl = ebus_to_skl(ebus);
 
-       if (skl->init_failed)
+       if (!skl->init_done)
                return;
 
        snd_hdac_ext_stop_streams(ebus);
@@ -862,29 +876,120 @@ static void skl_remove(struct pci_dev *pci)
        dev_set_drvdata(&pci->dev, NULL);
 }
 
+static struct sst_codecs skl_codecs = {
+       .num_codecs = 1,
+       .codecs = {"NAU88L25"}
+};
+
+static struct sst_codecs kbl_codecs = {
+       .num_codecs = 1,
+       .codecs = {"NAU88L25"}
+};
+
+static struct sst_codecs bxt_codecs = {
+       .num_codecs = 1,
+       .codecs = {"MX98357A"}
+};
+
+static struct sst_codecs kbl_poppy_codecs = {
+       .num_codecs = 1,
+       .codecs = {"10EC5663"}
+};
+
+static struct sst_codecs kbl_5663_5514_codecs = {
+       .num_codecs = 2,
+       .codecs = {"10EC5663", "10EC5514"}
+};
+
+
 static struct sst_acpi_mach sst_skl_devdata[] = {
-       { "INT343A", "skl_alc286s_i2s", "intel/dsp_fw_release.bin", NULL, NULL, NULL },
-       { "INT343B", "skl_n88l25_s4567", "intel/dsp_fw_release.bin",
-                               NULL, NULL, &skl_dmic_data },
-       { "MX98357A", "skl_n88l25_m98357a", "intel/dsp_fw_release.bin",
-                               NULL, NULL, &skl_dmic_data },
+       {
+               .id = "INT343A",
+               .drv_name = "skl_alc286s_i2s",
+               .fw_filename = "intel/dsp_fw_release.bin",
+       },
+       {
+               .id = "INT343B",
+               .drv_name = "skl_n88l25_s4567",
+               .fw_filename = "intel/dsp_fw_release.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &skl_codecs,
+               .pdata = &skl_dmic_data
+       },
+       {
+               .id = "MX98357A",
+               .drv_name = "skl_n88l25_m98357a",
+               .fw_filename = "intel/dsp_fw_release.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &skl_codecs,
+               .pdata = &skl_dmic_data
+       },
        {}
 };
 
 static struct sst_acpi_mach sst_bxtp_devdata[] = {
-       { "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL },
-       { "DLGS7219", "bxt_da7219_max98357a_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL },
+       {
+               .id = "INT343A",
+               .drv_name = "bxt_alc298s_i2s",
+               .fw_filename = "intel/dsp_fw_bxtn.bin",
+       },
+       {
+               .id = "DLGS7219",
+               .drv_name = "bxt_da7219_max98357a_i2s",
+               .fw_filename = "intel/dsp_fw_bxtn.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &bxt_codecs,
+       },
 };
 
 static struct sst_acpi_mach sst_kbl_devdata[] = {
-       { "INT343A", "kbl_alc286s_i2s", "intel/dsp_fw_kbl.bin", NULL, NULL, NULL },
-       { "INT343B", "kbl_n88l25_s4567", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data },
-       { "MX98357A", "kbl_n88l25_m98357a", "intel/dsp_fw_kbl.bin", NULL, NULL, &skl_dmic_data },
+       {
+               .id = "INT343A",
+               .drv_name = "kbl_alc286s_i2s",
+               .fw_filename = "intel/dsp_fw_kbl.bin",
+       },
+       {
+               .id = "INT343B",
+               .drv_name = "kbl_n88l25_s4567",
+               .fw_filename = "intel/dsp_fw_kbl.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &kbl_codecs,
+               .pdata = &skl_dmic_data
+       },
+       {
+               .id = "MX98357A",
+               .drv_name = "kbl_n88l25_m98357a",
+               .fw_filename = "intel/dsp_fw_kbl.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &kbl_codecs,
+               .pdata = &skl_dmic_data
+       },
+       {
+               .id = "MX98927",
+               .drv_name = "kbl_r5514_5663_max",
+               .fw_filename = "intel/dsp_fw_kbl.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &kbl_5663_5514_codecs,
+               .pdata = &skl_dmic_data
+       },
+       {
+               .id = "MX98927",
+               .drv_name = "kbl_rt5663_m98927",
+               .fw_filename = "intel/dsp_fw_kbl.bin",
+               .machine_quirk = sst_acpi_codec_list,
+               .quirk_data = &kbl_poppy_codecs,
+               .pdata = &skl_dmic_data
+       },
+
        {}
 };
 
 static struct sst_acpi_mach sst_glk_devdata[] = {
-       { "INT343A", "glk_alc298s_i2s", "intel/dsp_fw_glk.bin", NULL, NULL, NULL },
+       {
+               .id = "INT343A",
+               .drv_name = "glk_alc298s_i2s",
+               .fw_filename = "intel/dsp_fw_glk.bin",
+       },
 };
 
 /* PCI IDs */
index a454f6035f3e64b3be01ea4c53153c141e3a9561..2a630fcb7f088c1d548f06de31933ca662eafca2 100644 (file)
@@ -46,7 +46,7 @@ struct skl {
        struct hdac_ext_bus ebus;
        struct pci_dev *pci;
 
-       unsigned int init_failed:1; /* delayed init failed */
+       unsigned int init_done:1; /* delayed init status */
        struct platform_device *dmic_dev;
        struct platform_device *i2s_dev;
        struct snd_soc_platform *platform;
@@ -64,6 +64,8 @@ struct skl {
        const struct firmware *tplg;
 
        int supend_active;
+
+       struct work_struct probe_work;
 };
 
 #define skl_to_ebus(s) (&(s)->ebus)