168 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2// Copyright(c) 2015-18 Intel Corporation.3 4/*5 * Machine Driver for SKL+ platforms with DSP and iDisp, HDA Codecs6 */7 8#include <linux/module.h>9#include <linux/platform_device.h>10#include <sound/core.h>11#include <sound/hda_codec.h>12#include <sound/jack.h>13#include <sound/pcm.h>14#include <sound/pcm_params.h>15#include <sound/soc.h>16#include <sound/soc-acpi.h>17#include "../../codecs/hdac_hda.h"18#include "../../sof/intel/hda.h"19#include "sof_board_helpers.h"20 21static int skl_hda_card_late_probe(struct snd_soc_card *card)22{23 return sof_intel_board_card_late_probe(card);24}25 26#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 100027 28static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)29{30 struct snd_soc_pcm_runtime *rtd;31 struct hdac_hda_priv *hda_pvt;32 struct snd_soc_dai *dai;33 34 for_each_card_rtds(card, rtd) {35 if (!strstr(rtd->dai_link->codecs->name, "ehdaudio0D0"))36 continue;37 dai = snd_soc_rtd_to_codec(rtd, 0);38 hda_pvt = snd_soc_component_get_drvdata(dai->component);39 if (hda_pvt) {40 /*41 * all codecs are on the same bus, so it's sufficient42 * to look up only the first one43 */44 snd_hda_set_power_save(hda_pvt->codec->bus,45 HDA_CODEC_AUTOSUSPEND_DELAY_MS);46 break;47 }48 }49}50 51#define IDISP_HDMI_BE_ID 152#define HDA_BE_ID 453#define DMIC01_BE_ID 654#define DMIC16K_BE_ID 755#define BT_OFFLOAD_BE_ID 856 57#define HDA_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_IDISP_HDMI, \58 SOF_LINK_HDA, \59 SOF_LINK_DMIC01, \60 SOF_LINK_DMIC16K, \61 SOF_LINK_BT_OFFLOAD, \62 SOF_LINK_NONE, \63 SOF_LINK_NONE)64 65#define HDA_LINK_IDS SOF_LINK_ORDER(IDISP_HDMI_BE_ID, \66 HDA_BE_ID, \67 DMIC01_BE_ID, \68 DMIC16K_BE_ID, \69 BT_OFFLOAD_BE_ID, \70 0, \71 0)72 73static unsigned long74skl_hda_get_board_quirk(struct snd_soc_acpi_mach_params *mach_params)75{76 unsigned long board_quirk = 0;77 int ssp_bt;78 79 if (hweight_long(mach_params->bt_link_mask) == 1) {80 ssp_bt = fls(mach_params->bt_link_mask) - 1;81 board_quirk |= SOF_SSP_PORT_BT_OFFLOAD(ssp_bt) |82 SOF_BT_OFFLOAD_PRESENT;83 }84 85 return board_quirk;86}87 88static int skl_hda_audio_probe(struct platform_device *pdev)89{90 struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;91 struct sof_card_private *ctx;92 struct snd_soc_card *card;93 unsigned long board_quirk = skl_hda_get_board_quirk(&mach->mach_params);94 int ret;95 96 card = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_card), GFP_KERNEL);97 if (!card)98 return -ENOMEM;99 100 card->name = "hda-dsp";101 card->owner = THIS_MODULE;102 card->fully_routed = true;103 card->late_probe = skl_hda_card_late_probe;104 105 dev_dbg(&pdev->dev, "board_quirk = %lx\n", board_quirk);106 107 /* initialize ctx with board quirk */108 ctx = sof_intel_board_get_ctx(&pdev->dev, board_quirk);109 if (!ctx)110 return -ENOMEM;111 112 if (HDA_EXT_CODEC(mach->mach_params.codec_mask))113 ctx->hda_codec_present = true;114 115 if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)116 ctx->hdmi.idisp_codec = true;117 118 ctx->link_order_overwrite = HDA_LINK_ORDER;119 ctx->link_id_overwrite = HDA_LINK_IDS;120 121 /* update dai_link */122 ret = sof_intel_board_set_dai_link(&pdev->dev, card, ctx);123 if (ret)124 return ret;125 126 card->dev = &pdev->dev;127 if (!snd_soc_acpi_sof_parent(&pdev->dev))128 card->disable_route_checks = true;129 130 if (mach->mach_params.dmic_num > 0) {131 card->components = devm_kasprintf(card->dev, GFP_KERNEL,132 "cfg-dmics:%d",133 mach->mach_params.dmic_num);134 if (!card->components)135 return -ENOMEM;136 }137 138 ret = snd_soc_fixup_dai_links_platform_name(card,139 mach->mach_params.platform);140 if (ret)141 return ret;142 143 snd_soc_card_set_drvdata(card, ctx);144 145 ret = devm_snd_soc_register_card(&pdev->dev, card);146 if (!ret)147 skl_set_hda_codec_autosuspend_delay(card);148 149 return ret;150}151 152static struct platform_driver skl_hda_audio = {153 .probe = skl_hda_audio_probe,154 .driver = {155 .name = "skl_hda_dsp_generic",156 .pm = &snd_soc_pm_ops,157 },158};159 160module_platform_driver(skl_hda_audio)161 162/* Module information */163MODULE_DESCRIPTION("SKL/KBL/BXT/APL HDA Generic Machine driver");164MODULE_AUTHOR("Rakesh Ughreja <rakesh.a.ughreja@intel.com>");165MODULE_LICENSE("GPL v2");166MODULE_ALIAS("platform:skl_hda_dsp_generic");167MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);168