2020-05-01 07:58:50 -07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2018-08-22 13:24:59 -07:00
|
|
|
// Copyright(c) 2015-18 Intel Corporation.
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Machine Driver for SKL+ platforms with DSP and iDisp, HDA Codecs
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <sound/core.h>
|
2024-09-12 05:03:03 -07:00
|
|
|
#include <sound/hda_codec.h>
|
2018-08-22 13:24:59 -07:00
|
|
|
#include <sound/jack.h>
|
|
|
|
#include <sound/pcm.h>
|
|
|
|
#include <sound/pcm_params.h>
|
|
|
|
#include <sound/soc.h>
|
2018-11-01 14:34:49 -07:00
|
|
|
#include <sound/soc-acpi.h>
|
2024-09-12 05:03:03 -07:00
|
|
|
#include "../../codecs/hdac_hda.h"
|
|
|
|
#include "../../sof/intel/hda.h"
|
|
|
|
#include "sof_board_helpers.h"
|
2018-08-22 13:24:59 -07:00
|
|
|
|
|
|
|
static int skl_hda_card_late_probe(struct snd_soc_card *card)
|
|
|
|
{
|
2024-09-12 05:03:03 -07:00
|
|
|
return sof_intel_board_card_late_probe(card);
|
2018-08-22 13:24:59 -07:00
|
|
|
}
|
|
|
|
|
2020-04-09 11:58:16 -07:00
|
|
|
#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000
|
|
|
|
|
|
|
|
static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)
|
|
|
|
{
|
2020-04-20 13:54:31 -07:00
|
|
|
struct snd_soc_pcm_runtime *rtd;
|
2020-04-09 11:58:16 -07:00
|
|
|
struct hdac_hda_priv *hda_pvt;
|
2020-04-20 13:54:31 -07:00
|
|
|
struct snd_soc_dai *dai;
|
|
|
|
|
|
|
|
for_each_card_rtds(card, rtd) {
|
2020-07-22 10:35:24 -07:00
|
|
|
if (!strstr(rtd->dai_link->codecs->name, "ehdaudio0D0"))
|
2020-04-20 13:54:31 -07:00
|
|
|
continue;
|
2023-09-25 23:24:24 -07:00
|
|
|
dai = snd_soc_rtd_to_codec(rtd, 0);
|
2020-04-20 13:54:31 -07:00
|
|
|
hda_pvt = snd_soc_component_get_drvdata(dai->component);
|
|
|
|
if (hda_pvt) {
|
|
|
|
/*
|
|
|
|
* all codecs are on the same bus, so it's sufficient
|
|
|
|
* to look up only the first one
|
|
|
|
*/
|
2022-08-16 04:17:24 -07:00
|
|
|
snd_hda_set_power_save(hda_pvt->codec->bus,
|
2020-04-20 13:54:31 -07:00
|
|
|
HDA_CODEC_AUTOSUSPEND_DELAY_MS);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-04-09 11:58:16 -07:00
|
|
|
}
|
|
|
|
|
2024-09-12 05:03:03 -07:00
|
|
|
#define IDISP_HDMI_BE_ID 1
|
|
|
|
#define HDA_BE_ID 4
|
|
|
|
#define DMIC01_BE_ID 6
|
|
|
|
#define DMIC16K_BE_ID 7
|
|
|
|
#define BT_OFFLOAD_BE_ID 8
|
|
|
|
|
|
|
|
#define HDA_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_IDISP_HDMI, \
|
|
|
|
SOF_LINK_HDA, \
|
|
|
|
SOF_LINK_DMIC01, \
|
|
|
|
SOF_LINK_DMIC16K, \
|
|
|
|
SOF_LINK_BT_OFFLOAD, \
|
|
|
|
SOF_LINK_NONE, \
|
|
|
|
SOF_LINK_NONE)
|
|
|
|
|
|
|
|
#define HDA_LINK_IDS SOF_LINK_ORDER(IDISP_HDMI_BE_ID, \
|
|
|
|
HDA_BE_ID, \
|
|
|
|
DMIC01_BE_ID, \
|
|
|
|
DMIC16K_BE_ID, \
|
|
|
|
BT_OFFLOAD_BE_ID, \
|
|
|
|
0, \
|
|
|
|
0)
|
|
|
|
|
|
|
|
static unsigned long
|
|
|
|
skl_hda_get_board_quirk(struct snd_soc_acpi_mach_params *mach_params)
|
|
|
|
{
|
|
|
|
unsigned long board_quirk = 0;
|
|
|
|
int ssp_bt;
|
|
|
|
|
|
|
|
if (hweight_long(mach_params->bt_link_mask) == 1) {
|
|
|
|
ssp_bt = fls(mach_params->bt_link_mask) - 1;
|
|
|
|
board_quirk |= SOF_SSP_PORT_BT_OFFLOAD(ssp_bt) |
|
|
|
|
SOF_BT_OFFLOAD_PRESENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return board_quirk;
|
|
|
|
}
|
|
|
|
|
2018-08-22 13:24:59 -07:00
|
|
|
static int skl_hda_audio_probe(struct platform_device *pdev)
|
|
|
|
{
|
2024-08-27 05:32:10 -07:00
|
|
|
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
|
2024-09-12 05:03:03 -07:00
|
|
|
struct sof_card_private *ctx;
|
2024-04-26 08:21:12 -07:00
|
|
|
struct snd_soc_card *card;
|
2024-09-12 05:03:03 -07:00
|
|
|
unsigned long board_quirk = skl_hda_get_board_quirk(&mach->mach_params);
|
2018-08-22 13:24:59 -07:00
|
|
|
int ret;
|
|
|
|
|
2024-09-12 05:03:03 -07:00
|
|
|
card = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_card), GFP_KERNEL);
|
|
|
|
if (!card)
|
2018-08-22 13:24:59 -07:00
|
|
|
return -ENOMEM;
|
|
|
|
|
2024-09-04 19:20:17 -07:00
|
|
|
card->name = "hda-dsp";
|
|
|
|
card->owner = THIS_MODULE;
|
|
|
|
card->fully_routed = true;
|
|
|
|
card->late_probe = skl_hda_card_late_probe;
|
2024-04-26 08:21:12 -07:00
|
|
|
|
2024-09-12 05:03:03 -07:00
|
|
|
dev_dbg(&pdev->dev, "board_quirk = %lx\n", board_quirk);
|
|
|
|
|
|
|
|
/* initialize ctx with board quirk */
|
|
|
|
ctx = sof_intel_board_get_ctx(&pdev->dev, board_quirk);
|
|
|
|
if (!ctx)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
if (HDA_EXT_CODEC(mach->mach_params.codec_mask))
|
|
|
|
ctx->hda_codec_present = true;
|
2020-07-14 06:28:04 -07:00
|
|
|
|
2024-08-27 05:32:11 -07:00
|
|
|
if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
|
|
|
|
ctx->hdmi.idisp_codec = true;
|
|
|
|
|
2024-09-12 05:03:03 -07:00
|
|
|
ctx->link_order_overwrite = HDA_LINK_ORDER;
|
|
|
|
ctx->link_id_overwrite = HDA_LINK_IDS;
|
2024-08-27 05:32:07 -07:00
|
|
|
|
2024-09-12 05:03:03 -07:00
|
|
|
/* update dai_link */
|
|
|
|
ret = sof_intel_board_set_dai_link(&pdev->dev, card, ctx);
|
|
|
|
if (ret)
|
2018-08-22 13:24:59 -07:00
|
|
|
return ret;
|
|
|
|
|
2024-04-26 08:21:12 -07:00
|
|
|
card->dev = &pdev->dev;
|
2024-03-08 02:04:58 -07:00
|
|
|
if (!snd_soc_acpi_sof_parent(&pdev->dev))
|
2024-04-26 08:21:12 -07:00
|
|
|
card->disable_route_checks = true;
|
2018-08-22 13:24:59 -07:00
|
|
|
|
2019-12-04 14:15:44 -07:00
|
|
|
if (mach->mach_params.dmic_num > 0) {
|
2024-04-26 08:21:13 -07:00
|
|
|
card->components = devm_kasprintf(card->dev, GFP_KERNEL,
|
|
|
|
"cfg-dmics:%d",
|
|
|
|
mach->mach_params.dmic_num);
|
|
|
|
if (!card->components)
|
|
|
|
return -ENOMEM;
|
2019-12-04 14:15:44 -07:00
|
|
|
}
|
|
|
|
|
2024-09-12 05:03:03 -07:00
|
|
|
ret = snd_soc_fixup_dai_links_platform_name(card,
|
|
|
|
mach->mach_params.platform);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
snd_soc_card_set_drvdata(card, ctx);
|
|
|
|
|
2024-04-26 08:21:12 -07:00
|
|
|
ret = devm_snd_soc_register_card(&pdev->dev, card);
|
2020-04-09 11:58:16 -07:00
|
|
|
if (!ret)
|
2024-04-26 08:21:12 -07:00
|
|
|
skl_set_hda_codec_autosuspend_delay(card);
|
2020-04-09 11:58:16 -07:00
|
|
|
|
|
|
|
return ret;
|
2018-08-22 13:24:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct platform_driver skl_hda_audio = {
|
|
|
|
.probe = skl_hda_audio_probe,
|
|
|
|
.driver = {
|
|
|
|
.name = "skl_hda_dsp_generic",
|
|
|
|
.pm = &snd_soc_pm_ops,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
module_platform_driver(skl_hda_audio)
|
|
|
|
|
|
|
|
/* Module information */
|
|
|
|
MODULE_DESCRIPTION("SKL/KBL/BXT/APL HDA Generic Machine driver");
|
|
|
|
MODULE_AUTHOR("Rakesh Ughreja <rakesh.a.ughreja@intel.com>");
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
|
|
MODULE_ALIAS("platform:skl_hda_dsp_generic");
|
2024-09-12 05:03:03 -07:00
|
|
|
MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
|