Commit df91a210 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/intel' into asoc-next

parents a1eb3000 e2304803
...@@ -403,6 +403,18 @@ static inline int drm_eld_size(const uint8_t *eld) ...@@ -403,6 +403,18 @@ static inline int drm_eld_size(const uint8_t *eld)
return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4;
} }
/**
* drm_eld_get_conn_type - Get device type hdmi/dp connected
* @eld: pointer to an ELD memory structure
*
* The caller need to use %DRM_ELD_CONN_TYPE_HDMI or %DRM_ELD_CONN_TYPE_DP to
* identify the display type connected.
*/
static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
{
return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK;
}
struct edid *drm_do_get_edid(struct drm_connector *connector, struct edid *drm_do_get_edid(struct drm_connector *connector,
int (*get_edid_block)(void *data, u8 *buf, unsigned int block, int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
size_t len), size_t len),
......
...@@ -490,6 +490,7 @@ config SND_SOC_GTM601 ...@@ -490,6 +490,7 @@ config SND_SOC_GTM601
config SND_SOC_HDAC_HDMI config SND_SOC_HDAC_HDMI
tristate tristate
select SND_HDA_EXT_CORE select SND_HDA_EXT_CORE
select SND_PCM_ELD
select HDMI select HDMI
config SND_SOC_ICS43432 config SND_SOC_ICS43432
......
This diff is collapsed.
#ifndef __HDAC_HDMI_H__
#define __HDAC_HDMI_H__
int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm);
#endif /* __HDAC_HDMI_H__ */
...@@ -163,6 +163,7 @@ config SND_SOC_INTEL_SKYLAKE ...@@ -163,6 +163,7 @@ config SND_SOC_INTEL_SKYLAKE
tristate tristate
select SND_HDA_EXT_CORE select SND_HDA_EXT_CORE
select SND_SOC_TOPOLOGY select SND_SOC_TOPOLOGY
select SND_HDA_I915
select SND_SOC_INTEL_SST select SND_SOC_INTEL_SST
config SND_SOC_INTEL_SKL_RT286_MACH config SND_SOC_INTEL_SKL_RT286_MACH
...@@ -172,6 +173,7 @@ config SND_SOC_INTEL_SKL_RT286_MACH ...@@ -172,6 +173,7 @@ config SND_SOC_INTEL_SKL_RT286_MACH
select SND_SOC_INTEL_SKYLAKE select SND_SOC_INTEL_SKYLAKE
select SND_SOC_RT286 select SND_SOC_RT286
select SND_SOC_DMIC select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help help
This adds support for ASoC machine driver for Skylake platforms This adds support for ASoC machine driver for Skylake platforms
with RT286 I2S audio codec. with RT286 I2S audio codec.
...@@ -186,6 +188,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH ...@@ -186,6 +188,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH
select SND_SOC_NAU8825 select SND_SOC_NAU8825
select SND_SOC_SSM4567 select SND_SOC_SSM4567
select SND_SOC_DMIC select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help help
This adds support for ASoC Onboard Codec I2S machine driver. This will This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for NAU88L25 + SSM4567. create an alsa sound card for NAU88L25 + SSM4567.
...@@ -200,6 +203,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH ...@@ -200,6 +203,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH
select SND_SOC_NAU8825 select SND_SOC_NAU8825
select SND_SOC_MAX98357A select SND_SOC_MAX98357A
select SND_SOC_DMIC select SND_SOC_DMIC
select SND_SOC_HDAC_HDMI
help help
This adds support for ASoC Onboard Codec I2S machine driver. This will This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for NAU88L25 + MAX98357A. create an alsa sound card for NAU88L25 + MAX98357A.
......
...@@ -342,6 +342,10 @@ static struct sst_acpi_mach sst_acpi_chv[] = { ...@@ -342,6 +342,10 @@ static struct sst_acpi_mach sst_acpi_chv[] = {
&chv_platform_data }, &chv_platform_data },
{"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL,
&chv_platform_data }, &chv_platform_data },
/* some CHT-T platforms rely on RT5640, use Baytrail machine driver */
{"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL,
&chv_platform_data },
{}, {},
}; };
......
...@@ -318,7 +318,6 @@ void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx, ...@@ -318,7 +318,6 @@ void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx,
union ipc_header_high msg_high; union ipc_header_high msg_high;
u32 msg_low; u32 msg_low;
struct ipc_dsp_hdr *dsp_hdr; struct ipc_dsp_hdr *dsp_hdr;
unsigned int cmd_id;
msg_high = msg->mrfld_header.p.header_high; msg_high = msg->mrfld_header.p.header_high;
msg_low = msg->mrfld_header.p.header_low_payload; msg_low = msg->mrfld_header.p.header_low_payload;
...@@ -357,7 +356,6 @@ void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx, ...@@ -357,7 +356,6 @@ void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx,
return; return;
/* Copy command id so that we can use to put sst to reset */ /* Copy command id so that we can use to put sst to reset */
dsp_hdr = (struct ipc_dsp_hdr *)data; dsp_hdr = (struct ipc_dsp_hdr *)data;
cmd_id = dsp_hdr->cmd_id;
dev_dbg(sst_drv_ctx->dev, "cmd_id %d\n", dsp_hdr->cmd_id); dev_dbg(sst_drv_ctx->dev, "cmd_id %d\n", dsp_hdr->cmd_id);
if (sst_wake_up_block(sst_drv_ctx, msg_high.part.result, if (sst_wake_up_block(sst_drv_ctx, msg_high.part.result,
msg_high.part.drv_id, msg_high.part.drv_id,
......
...@@ -32,6 +32,18 @@ ...@@ -32,6 +32,18 @@
#include "../atom/sst-atom-controls.h" #include "../atom/sst-atom-controls.h"
#include "../common/sst-acpi.h" #include "../common/sst-acpi.h"
enum {
BYT_RT5640_DMIC1_MAP,
BYT_RT5640_DMIC2_MAP,
BYT_RT5640_IN1_MAP,
};
#define BYT_RT5640_MAP(quirk) ((quirk) & 0xff)
#define BYT_RT5640_DMIC_EN BIT(16)
static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
BYT_RT5640_DMIC_EN;
static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = { static const struct snd_soc_dapm_widget byt_rt5640_widgets[] = {
SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_HP("Headphone", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL),
...@@ -70,18 +82,6 @@ static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = { ...@@ -70,18 +82,6 @@ static const struct snd_soc_dapm_route byt_rt5640_intmic_in1_map[] = {
{"IN1P", NULL, "Internal Mic"}, {"IN1P", NULL, "Internal Mic"},
}; };
enum {
BYT_RT5640_DMIC1_MAP,
BYT_RT5640_DMIC2_MAP,
BYT_RT5640_IN1_MAP,
};
#define BYT_RT5640_MAP(quirk) ((quirk) & 0xff)
#define BYT_RT5640_DMIC_EN BIT(16)
static unsigned long byt_rt5640_quirk = BYT_RT5640_DMIC1_MAP |
BYT_RT5640_DMIC_EN;
static const struct snd_kcontrol_new byt_rt5640_controls[] = { static const struct snd_kcontrol_new byt_rt5640_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headphone"),
SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Headset Mic"),
...@@ -174,7 +174,6 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) ...@@ -174,7 +174,6 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime)
return ret; return ret;
} }
dmi_check_system(byt_rt5640_quirk_table);
switch (BYT_RT5640_MAP(byt_rt5640_quirk)) { switch (BYT_RT5640_MAP(byt_rt5640_quirk)) {
case BYT_RT5640_IN1_MAP: case BYT_RT5640_IN1_MAP:
custom_map = byt_rt5640_intmic_in1_map; custom_map = byt_rt5640_intmic_in1_map;
...@@ -341,15 +340,34 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) ...@@ -341,15 +340,34 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
{ {
int ret_val = 0; int ret_val = 0;
struct sst_acpi_mach *mach; struct sst_acpi_mach *mach;
const char *i2c_name = NULL;
int i;
int dai_index;
/* register the soc card */ /* register the soc card */
byt_rt5640_card.dev = &pdev->dev; byt_rt5640_card.dev = &pdev->dev;
mach = byt_rt5640_card.dev->platform_data; mach = byt_rt5640_card.dev->platform_data;
/* fix index of codec dai */
dai_index = MERR_DPCM_COMPR + 1;
for (i = 0; i < ARRAY_SIZE(byt_rt5640_dais); i++) {
if (!strcmp(byt_rt5640_dais[i].codec_name, "i2c-10EC5640:00")) {
dai_index = i;
break;
}
}
/* fixup codec name based on HID */ /* fixup codec name based on HID */
snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name), i2c_name = sst_acpi_find_name_from_hid(mach->id);
"%s%s%s", "i2c-", mach->id, ":00"); if (i2c_name != NULL) {
byt_rt5640_dais[MERR_DPCM_COMPR+1].codec_name = byt_rt5640_codec_name; snprintf(byt_rt5640_codec_name, sizeof(byt_rt5640_codec_name),
"%s%s", "i2c-", i2c_name);
byt_rt5640_dais[dai_index].codec_name = byt_rt5640_codec_name;
}
/* check quirks before creating card */
dmi_check_system(byt_rt5640_quirk_table);
ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card); ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5640_card);
......
...@@ -287,33 +287,20 @@ static struct snd_soc_card snd_soc_card_cht = { ...@@ -287,33 +287,20 @@ static struct snd_soc_card snd_soc_card_cht = {
.num_controls = ARRAY_SIZE(cht_mc_controls), .num_controls = ARRAY_SIZE(cht_mc_controls),
}; };
static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level,
void *context, void **ret)
{
*(bool *)context = true;
return AE_OK;
}
static int snd_cht_mc_probe(struct platform_device *pdev) static int snd_cht_mc_probe(struct platform_device *pdev)
{ {
int ret_val = 0; int ret_val = 0;
bool found = false;
struct cht_mc_private *drv; struct cht_mc_private *drv;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
if (!drv) if (!drv)
return -ENOMEM; return -ENOMEM;
if (ACPI_SUCCESS(acpi_get_devices( drv->ts3a227e_present = acpi_dev_present("104C227E");
"104C227E", if (!drv->ts3a227e_present) {
snd_acpi_codec_match,
&found, NULL)) && found) {
drv->ts3a227e_present = true;
} else {
/* no need probe TI jack detection chip */ /* no need probe TI jack detection chip */
snd_soc_card_cht.aux_dev = NULL; snd_soc_card_cht.aux_dev = NULL;
snd_soc_card_cht.num_aux_devs = 0; snd_soc_card_cht.num_aux_devs = 0;
drv->ts3a227e_present = false;
} }
/* register the soc card */ /* register the soc card */
......
...@@ -147,6 +147,17 @@ static const struct snd_kcontrol_new cht_mc_controls[] = { ...@@ -147,6 +147,17 @@ static const struct snd_kcontrol_new cht_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Ext Spk"), SOC_DAPM_PIN_SWITCH("Ext Spk"),
}; };
static struct snd_soc_jack_pin cht_bsw_jack_pins[] = {
{
.pin = "Headphone",
.mask = SND_JACK_HEADPHONE,
},
{
.pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE,
},
};
static int cht_aif1_hw_params(struct snd_pcm_substream *substream, static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
...@@ -202,9 +213,9 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) ...@@ -202,9 +213,9 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
else else
jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE; jack_type = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE;
ret = snd_soc_card_jack_new(runtime->card, "Headset Jack", ret = snd_soc_card_jack_new(runtime->card, "Headset",
jack_type, &ctx->jack, jack_type, &ctx->jack,
NULL, 0); cht_bsw_jack_pins, ARRAY_SIZE(cht_bsw_jack_pins));
if (ret) { if (ret) {
dev_err(runtime->dev, "Headset jack creation failed %d\n", ret); dev_err(runtime->dev, "Headset jack creation failed %d\n", ret);
return ret; return ret;
...@@ -333,20 +344,12 @@ static struct cht_acpi_card snd_soc_cards[] = { ...@@ -333,20 +344,12 @@ static struct cht_acpi_card snd_soc_cards[] = {
{"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650}, {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650},
}; };
static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level,
void *context, void **ret)
{
*(bool *)context = true;
return AE_OK;
}
static int snd_cht_mc_probe(struct platform_device *pdev) static int snd_cht_mc_probe(struct platform_device *pdev)
{ {
int ret_val = 0; int ret_val = 0;
int i; int i;
struct cht_mc_private *drv; struct cht_mc_private *drv;
struct snd_soc_card *card = snd_soc_cards[0].soc_card; struct snd_soc_card *card = snd_soc_cards[0].soc_card;
bool found = false;
char codec_name[16]; char codec_name[16];
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC);
...@@ -354,10 +357,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) ...@@ -354,10 +357,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) { for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) {
if (ACPI_SUCCESS(acpi_get_devices( if (acpi_dev_present(snd_soc_cards[i].codec_id)) {
snd_soc_cards[i].codec_id,
snd_acpi_codec_match,
&found, NULL)) && found) {
dev_dbg(&pdev->dev, dev_dbg(&pdev->dev,
"found codec %s\n", snd_soc_cards[i].codec_id); "found codec %s\n", snd_soc_cards[i].codec_id);
card = snd_soc_cards[i].soc_card; card = snd_soc_cards[i].soc_card;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "../../codecs/nau8825.h" #include "../../codecs/nau8825.h"
#include "../../codecs/hdac_hdmi.h"
#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" #define SKL_NUVOTON_CODEC_DAI "nau8825-hifi"
#define SKL_MAXIM_CODEC_DAI "HiFi" #define SKL_MAXIM_CODEC_DAI "HiFi"
...@@ -29,6 +30,16 @@ ...@@ -29,6 +30,16 @@
static struct snd_soc_jack skylake_headset; static struct snd_soc_jack skylake_headset;
static struct snd_soc_card skylake_audio_card; static struct snd_soc_card skylake_audio_card;
enum {
SKL_DPCM_AUDIO_PB = 0,
SKL_DPCM_AUDIO_CP,
SKL_DPCM_AUDIO_REF_CP,
SKL_DPCM_AUDIO_DMIC_CP,
SKL_DPCM_AUDIO_HDMI1_PB,
SKL_DPCM_AUDIO_HDMI2_PB,
SKL_DPCM_AUDIO_HDMI3_PB,
};
static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card) static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card)
{ {
struct snd_soc_pcm_runtime *rtd; struct snd_soc_pcm_runtime *rtd;
...@@ -87,7 +98,6 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = { ...@@ -87,7 +98,6 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_SPK("Spk", NULL), SND_SOC_DAPM_SPK("Spk", NULL),
SND_SOC_DAPM_MIC("SoC DMIC", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL),
SND_SOC_DAPM_SINK("WoV Sink"),
SND_SOC_DAPM_SPK("DP", NULL), SND_SOC_DAPM_SPK("DP", NULL),
SND_SOC_DAPM_SPK("HDMI", NULL), SND_SOC_DAPM_SPK("HDMI", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
...@@ -107,7 +117,6 @@ static const struct snd_soc_dapm_route skylake_map[] = { ...@@ -107,7 +117,6 @@ static const struct snd_soc_dapm_route skylake_map[] = {
{ "MIC", NULL, "Headset Mic" }, { "MIC", NULL, "Headset Mic" },
{ "DMic", NULL, "SoC DMIC" }, { "DMic", NULL, "SoC DMIC" },
{"WoV Sink", NULL, "hwd_in sink"},
{"HDMI", NULL, "hif5 Output"}, {"HDMI", NULL, "hif5 Output"},
{"DP", NULL, "hif6 Output"}, {"DP", NULL, "hif6 Output"},
...@@ -124,8 +133,14 @@ static const struct snd_soc_dapm_route skylake_map[] = { ...@@ -124,8 +133,14 @@ static const struct snd_soc_dapm_route skylake_map[] = {
/* DMIC */ /* DMIC */
{ "dmic01_hifi", NULL, "DMIC01 Rx" }, { "dmic01_hifi", NULL, "DMIC01 Rx" },
{ "DMIC01 Rx", NULL, "DMIC AIF" }, { "DMIC01 Rx", NULL, "DMIC AIF" },
{ "hifi1", NULL, "iDisp Tx"},
{ "iDisp Tx", NULL, "iDisp_out"}, { "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"},
{ "Headphone Jack", NULL, "Platform Clock" }, { "Headphone Jack", NULL, "Platform Clock" },
{ "Headset Mic", NULL, "Platform Clock" }, { "Headset Mic", NULL, "Platform Clock" },
}; };
...@@ -171,11 +186,31 @@ static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -171,11 +186,31 @@ static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
nau8825_enable_jack_detect(codec, &skylake_headset); nau8825_enable_jack_detect(codec, &skylake_headset);
snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
return ret; return ret;
} }
static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->codec_dai;
return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI1_PB);
}
static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->codec_dai;
return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI2_PB);
}
static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->codec_dai;
return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI3_PB);
}
static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_dapm_context *dapm; struct snd_soc_dapm_context *dapm;
...@@ -318,7 +353,7 @@ static struct snd_soc_ops skylaye_refcap_ops = { ...@@ -318,7 +353,7 @@ static struct snd_soc_ops skylaye_refcap_ops = {
/* skylake digital audio interface glue - connects codec <--> CPU */ /* skylake digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link skylake_dais[] = { static struct snd_soc_dai_link skylake_dais[] = {
/* Front End DAI links */ /* Front End DAI links */
{ [SKL_DPCM_AUDIO_PB] = {
.name = "Skl Audio Port", .name = "Skl Audio Port",
.stream_name = "Audio", .stream_name = "Audio",
.cpu_dai_name = "System Pin", .cpu_dai_name = "System Pin",
...@@ -333,7 +368,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -333,7 +368,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
.dpcm_playback = 1, .dpcm_playback = 1,
.ops = &skylake_nau8825_fe_ops, .ops = &skylake_nau8825_fe_ops,
}, },
{ [SKL_DPCM_AUDIO_CP] = {
.name = "Skl Audio Capture Port", .name = "Skl Audio Capture Port",
.stream_name = "Audio Record", .stream_name = "Audio Record",
.cpu_dai_name = "System Pin", .cpu_dai_name = "System Pin",
...@@ -347,7 +382,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -347,7 +382,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
.dpcm_capture = 1, .dpcm_capture = 1,
.ops = &skylake_nau8825_fe_ops, .ops = &skylake_nau8825_fe_ops,
}, },
{ [SKL_DPCM_AUDIO_REF_CP] = {
.name = "Skl Audio Reference cap", .name = "Skl Audio Reference cap",
.stream_name = "Wake on Voice", .stream_name = "Wake on Voice",
.cpu_dai_name = "Reference Pin", .cpu_dai_name = "Reference Pin",
...@@ -361,7 +396,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -361,7 +396,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
.dynamic = 1, .dynamic = 1,
.ops = &skylaye_refcap_ops, .ops = &skylaye_refcap_ops,
}, },
{ [SKL_DPCM_AUDIO_DMIC_CP] = {
.name = "Skl Audio DMIC cap", .name = "Skl Audio DMIC cap",
.stream_name = "dmiccap", .stream_name = "dmiccap",
.cpu_dai_name = "DMIC Pin", .cpu_dai_name = "DMIC Pin",
...@@ -374,15 +409,45 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -374,15 +409,45 @@ static struct snd_soc_dai_link skylake_dais[] = {
.dynamic = 1, .dynamic = 1,
.ops = &skylake_dmic_ops, .ops = &skylake_dmic_ops,
}, },
{ [SKL_DPCM_AUDIO_HDMI1_PB] = {
.name = "Skl HDMI Port", .name = "Skl HDMI Port1",
.stream_name = "Hdmi", .stream_name = "Hdmi1",
.cpu_dai_name = "HDMI Pin", .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,
},
[SKL_DPCM_AUDIO_HDMI2_PB] = {
.name = "Skl HDMI Port2",
.stream_name = "Hdmi2",
.cpu_dai_name = "HDMI2 Pin",
.codec_name = "snd-soc-dummy", .codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai", .codec_dai_name = "snd-soc-dummy-dai",
.platform_name = "0000:00:1f.3", .platform_name = "0000:00:1f.3",
.dpcm_playback = 1, .dpcm_playback = 1,
.init = NULL, .init = NULL,
.trigger = {
SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.nonatomic = 1,
.dynamic = 1,
},
[SKL_DPCM_AUDIO_HDMI3_PB] = {
.name = "Skl 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, .nonatomic = 1,
.dynamic = 1, .dynamic = 1,
}, },
...@@ -407,7 +472,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -407,7 +472,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
{ {
/* SSP1 - Codec */ /* SSP1 - Codec */
.name = "SSP1-Codec", .name = "SSP1-Codec",
.be_id = 0, .be_id = 1,
.cpu_dai_name = "SSP1 Pin", .cpu_dai_name = "SSP1 Pin",
.platform_name = "0000:00:1f.3", .platform_name = "0000:00:1f.3",
.no_pcm = 1, .no_pcm = 1,
...@@ -424,7 +489,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -424,7 +489,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
}, },
{ {
.name = "dmic01", .name = "dmic01",
.be_id = 1, .be_id = 2,
.cpu_dai_name = "DMIC01 Pin", .cpu_dai_name = "DMIC01 Pin",
.codec_name = "dmic-codec", .codec_name = "dmic-codec",
.codec_dai_name = "dmic-hifi", .codec_dai_name = "dmic-hifi",
...@@ -435,13 +500,36 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -435,13 +500,36 @@ static struct snd_soc_dai_link skylake_dais[] = {
.no_pcm = 1, .no_pcm = 1,
}, },
{ {
.name = "iDisp", .name = "iDisp1",
.be_id = 3, .be_id = 3,
.cpu_dai_name = "iDisp Pin", .cpu_dai_name = "iDisp1 Pin",
.codec_name = "ehdaudio0D2", .codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi1", .codec_dai_name = "intel-hdmi-hifi1",
.platform_name = "0000:00:1f.3", .platform_name = "0000:00:1f.3",
.dpcm_playback = 1, .dpcm_playback = 1,
.init = skylake_hdmi1_init,
.no_pcm = 1,
},
{
.name = "iDisp2",
.be_id = 4,
.cpu_dai_name = "iDisp2 Pin",
.codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi2",
.platform_name = "0000:00:1f.3",
.init = skylake_hdmi2_init,
.dpcm_playback = 1,
.no_pcm = 1,
},
{
.name = "iDisp3",
.be_id = 5,
.cpu_dai_name = "iDisp3 Pin",
.codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi3",
.platform_name = "0000:00:1f.3",
.init = skylake_hdmi3_init,
.dpcm_playback = 1,
.no_pcm = 1, .no_pcm = 1,
}, },
}; };
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <sound/jack.h> #include <sound/jack.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include "../../codecs/nau8825.h" #include "../../codecs/nau8825.h"
#include "../../codecs/hdac_hdmi.h"
#define SKL_NUVOTON_CODEC_DAI "nau8825-hifi" #define SKL_NUVOTON_CODEC_DAI "nau8825-hifi"
#define SKL_SSM_CODEC_DAI "ssm4567-hifi" #define SKL_SSM_CODEC_DAI "ssm4567-hifi"
...@@ -33,6 +34,16 @@ ...@@ -33,6 +34,16 @@
static struct snd_soc_jack skylake_headset; static struct snd_soc_jack skylake_headset;
static struct snd_soc_card skylake_audio_card; static struct snd_soc_card skylake_audio_card;
enum {
SKL_DPCM_AUDIO_PB = 0,
SKL_DPCM_AUDIO_CP,
SKL_DPCM_AUDIO_REF_CP,
SKL_DPCM_AUDIO_DMIC_CP,
SKL_DPCM_AUDIO_HDMI1_PB,
SKL_DPCM_AUDIO_HDMI2_PB,
SKL_DPCM_AUDIO_HDMI3_PB,
};
static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card) static inline struct snd_soc_dai *skl_get_codec_dai(struct snd_soc_card *card)
{ {
struct snd_soc_pcm_runtime *rtd; struct snd_soc_pcm_runtime *rtd;
...@@ -92,7 +103,6 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = { ...@@ -92,7 +103,6 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
SND_SOC_DAPM_SPK("Left Speaker", NULL), SND_SOC_DAPM_SPK("Left Speaker", NULL),
SND_SOC_DAPM_SPK("Right Speaker", NULL), SND_SOC_DAPM_SPK("Right Speaker", NULL),
SND_SOC_DAPM_MIC("SoC DMIC", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL),
SND_SOC_DAPM_SINK("WoV Sink"),
SND_SOC_DAPM_SPK("DP", NULL), SND_SOC_DAPM_SPK("DP", NULL),
SND_SOC_DAPM_SPK("HDMI", NULL), SND_SOC_DAPM_SPK("HDMI", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
...@@ -113,8 +123,6 @@ static const struct snd_soc_dapm_route skylake_map[] = { ...@@ -113,8 +123,6 @@ static const struct snd_soc_dapm_route skylake_map[] = {
{"MIC", NULL, "Headset Mic"}, {"MIC", NULL, "Headset Mic"},
{"DMic", NULL, "SoC DMIC"}, {"DMic", NULL, "SoC DMIC"},
{"WoV Sink", NULL, "hwd_in sink"},
{"HDMI", NULL, "hif5 Output"}, {"HDMI", NULL, "hif5 Output"},
{"DP", NULL, "hif6 Output"}, {"DP", NULL, "hif6 Output"},
/* CODEC BE connections */ /* CODEC BE connections */
...@@ -122,6 +130,11 @@ static const struct snd_soc_dapm_route skylake_map[] = { ...@@ -122,6 +130,11 @@ static const struct snd_soc_dapm_route skylake_map[] = {
{ "Right Playback", NULL, "ssp0 Tx"}, { "Right Playback", NULL, "ssp0 Tx"},
{ "ssp0 Tx", NULL, "codec0_out"}, { "ssp0 Tx", NULL, "codec0_out"},
/* IV feedback path */
{ "codec0_lp_in", NULL, "ssp0 Rx"},
{ "ssp0 Rx", NULL, "Left Capture Sense" },
{ "ssp0 Rx", NULL, "Right Capture Sense" },
{ "Playback", NULL, "ssp1 Tx"}, { "Playback", NULL, "ssp1 Tx"},
{ "ssp1 Tx", NULL, "codec1_out"}, { "ssp1 Tx", NULL, "codec1_out"},
...@@ -131,8 +144,14 @@ static const struct snd_soc_dapm_route skylake_map[] = { ...@@ -131,8 +144,14 @@ static const struct snd_soc_dapm_route skylake_map[] = {
/* DMIC */ /* DMIC */
{ "dmic01_hifi", NULL, "DMIC01 Rx" }, { "dmic01_hifi", NULL, "DMIC01 Rx" },
{ "DMIC01 Rx", NULL, "DMIC AIF" }, { "DMIC01 Rx", NULL, "DMIC AIF" },
{ "hifi1", NULL, "iDisp Tx"},
{ "iDisp Tx", NULL, "iDisp_out"}, { "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"},
{ "Headphone Jack", NULL, "Platform Clock" }, { "Headphone Jack", NULL, "Platform Clock" },
{ "Headset Mic", NULL, "Platform Clock" }, { "Headset Mic", NULL, "Platform Clock" },
}; };
...@@ -197,11 +216,32 @@ static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -197,11 +216,32 @@ static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
nau8825_enable_jack_detect(codec, &skylake_headset); nau8825_enable_jack_detect(codec, &skylake_headset);
snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
return ret; return ret;
} }
static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->codec_dai;
return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI1_PB);
}
static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->codec_dai;
return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI2_PB);
}
static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->codec_dai;
return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI3_PB);
}
static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_dapm_context *dapm; struct snd_soc_dapm_context *dapm;
...@@ -362,7 +402,7 @@ static struct snd_soc_ops skylaye_refcap_ops = { ...@@ -362,7 +402,7 @@ static struct snd_soc_ops skylaye_refcap_ops = {
/* skylake digital audio interface glue - connects codec <--> CPU */ /* skylake digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link skylake_dais[] = { static struct snd_soc_dai_link skylake_dais[] = {
/* Front End DAI links */ /* Front End DAI links */
{ [SKL_DPCM_AUDIO_PB] = {
.name = "Skl Audio Port", .name = "Skl Audio Port",
.stream_name = "Audio", .stream_name = "Audio",
.cpu_dai_name = "System Pin", .cpu_dai_name = "System Pin",
...@@ -377,7 +417,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -377,7 +417,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
.dpcm_playback = 1, .dpcm_playback = 1,
.ops = &skylake_nau8825_fe_ops, .ops = &skylake_nau8825_fe_ops,
}, },
{ [SKL_DPCM_AUDIO_CP] = {
.name = "Skl Audio Capture Port", .name = "Skl Audio Capture Port",
.stream_name = "Audio Record", .stream_name = "Audio Record",
.cpu_dai_name = "System Pin", .cpu_dai_name = "System Pin",
...@@ -391,7 +431,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -391,7 +431,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
.dpcm_capture = 1, .dpcm_capture = 1,
.ops = &skylake_nau8825_fe_ops, .ops = &skylake_nau8825_fe_ops,
}, },
{ [SKL_DPCM_AUDIO_REF_CP] = {
.name = "Skl Audio Reference cap", .name = "Skl Audio Reference cap",
.stream_name = "Wake on Voice", .stream_name = "Wake on Voice",
.cpu_dai_name = "Reference Pin", .cpu_dai_name = "Reference Pin",
...@@ -405,7 +445,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -405,7 +445,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
.dynamic = 1, .dynamic = 1,
.ops = &skylaye_refcap_ops, .ops = &skylaye_refcap_ops,
}, },
{ [SKL_DPCM_AUDIO_DMIC_CP] = {
.name = "Skl Audio DMIC cap", .name = "Skl Audio DMIC cap",
.stream_name = "dmiccap", .stream_name = "dmiccap",
.cpu_dai_name = "DMIC Pin", .cpu_dai_name = "DMIC Pin",
...@@ -418,13 +458,43 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -418,13 +458,43 @@ static struct snd_soc_dai_link skylake_dais[] = {
.dynamic = 1, .dynamic = 1,
.ops = &skylake_dmic_ops, .ops = &skylake_dmic_ops,
}, },
{ [SKL_DPCM_AUDIO_HDMI1_PB] = {
.name = "Skl HDMI Port", .name = "Skl HDMI Port1",
.stream_name = "Hdmi", .stream_name = "Hdmi1",
.cpu_dai_name = "HDMI Pin", .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,
},
[SKL_DPCM_AUDIO_HDMI2_PB] = {
.name = "Skl 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,
},
[SKL_DPCM_AUDIO_HDMI3_PB] = {
.name = "Skl HDMI Port3",
.stream_name = "Hdmi3",
.cpu_dai_name = "HDMI3 Pin",
.codec_name = "snd-soc-dummy", .codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai", .codec_dai_name = "snd-soc-dummy-dai",
.platform_name = "0000:00:1f.3", .platform_name = "0000:00:1f.3",
.trigger = {
SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
.dpcm_playback = 1, .dpcm_playback = 1,
.init = NULL, .init = NULL,
.nonatomic = 1, .nonatomic = 1,
...@@ -448,11 +518,12 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -448,11 +518,12 @@ static struct snd_soc_dai_link skylake_dais[] = {
.ignore_pmdown_time = 1, .ignore_pmdown_time = 1,
.be_hw_params_fixup = skylake_ssp_fixup, .be_hw_params_fixup = skylake_ssp_fixup,
.dpcm_playback = 1, .dpcm_playback = 1,
.dpcm_capture = 1,
}, },
{ {
/* SSP1 - Codec */ /* SSP1 - Codec */
.name = "SSP1-Codec", .name = "SSP1-Codec",
.be_id = 0, .be_id = 1,
.cpu_dai_name = "SSP1 Pin", .cpu_dai_name = "SSP1 Pin",
.platform_name = "0000:00:1f.3", .platform_name = "0000:00:1f.3",
.no_pcm = 1, .no_pcm = 1,
...@@ -469,7 +540,7 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -469,7 +540,7 @@ static struct snd_soc_dai_link skylake_dais[] = {
}, },
{ {
.name = "dmic01", .name = "dmic01",
.be_id = 1, .be_id = 2,
.cpu_dai_name = "DMIC01 Pin", .cpu_dai_name = "DMIC01 Pin",
.codec_name = "dmic-codec", .codec_name = "dmic-codec",
.codec_dai_name = "dmic-hifi", .codec_dai_name = "dmic-hifi",
...@@ -480,13 +551,36 @@ static struct snd_soc_dai_link skylake_dais[] = { ...@@ -480,13 +551,36 @@ static struct snd_soc_dai_link skylake_dais[] = {
.no_pcm = 1, .no_pcm = 1,
}, },
{ {
.name = "iDisp", .name = "iDisp1",
.be_id = 3, .be_id = 3,
.cpu_dai_name = "iDisp Pin", .cpu_dai_name = "iDisp1 Pin",
.codec_name = "ehdaudio0D2", .codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi1", .codec_dai_name = "intel-hdmi-hifi1",
.platform_name = "0000:00:1f.3", .platform_name = "0000:00:1f.3",
.dpcm_playback = 1, .dpcm_playback = 1,
.init = skylake_hdmi1_init,
.no_pcm = 1,
},
{
.name = "iDisp2",
.be_id = 4,
.cpu_dai_name = "iDisp2 Pin",
.codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi2",
.platform_name = "0000:00:1f.3",
.init = skylake_hdmi2_init,
.dpcm_playback = 1,
.no_pcm = 1,
},
{
.name = "iDisp3",
.be_id = 5,
.cpu_dai_name = "iDisp3 Pin",
.codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi3",
.platform_name = "0000:00:1f.3",
.init = skylake_hdmi3_init,
.dpcm_playback = 1,
.no_pcm = 1, .no_pcm = 1,
}, },
}; };
......
...@@ -26,8 +26,20 @@ ...@@ -26,8 +26,20 @@
#include <sound/jack.h> #include <sound/jack.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
#include "../../codecs/rt286.h" #include "../../codecs/rt286.h"
#include "../../codecs/hdac_hdmi.h"
static struct snd_soc_jack skylake_headset; static struct snd_soc_jack skylake_headset;
enum {
SKL_DPCM_AUDIO_PB = 0,
SKL_DPCM_AUDIO_CP,
SKL_DPCM_AUDIO_REF_CP,
SKL_DPCM_AUDIO_DMIC_CP,
SKL_DPCM_AUDIO_HDMI1_PB,
SKL_DPCM_AUDIO_HDMI2_PB,
SKL_DPCM_AUDIO_HDMI3_PB,
};
/* Headset jack detection DAPM pins */ /* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin skylake_headset_pins[] = { static struct snd_soc_jack_pin skylake_headset_pins[] = {
{ {
...@@ -52,7 +64,9 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = { ...@@ -52,7 +64,9 @@ static const struct snd_soc_dapm_widget skylake_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL), SND_SOC_DAPM_MIC("Mic Jack", NULL),
SND_SOC_DAPM_MIC("DMIC2", NULL), SND_SOC_DAPM_MIC("DMIC2", NULL),
SND_SOC_DAPM_MIC("SoC DMIC", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL),
SND_SOC_DAPM_SINK("WoV Sink"), SND_SOC_DAPM_SPK("HDMI1", NULL),
SND_SOC_DAPM_SPK("HDMI2", NULL),
SND_SOC_DAPM_SPK("HDMI3", NULL),
}; };
static const struct snd_soc_dapm_route skylake_rt286_map[] = { static const struct snd_soc_dapm_route skylake_rt286_map[] = {
...@@ -70,7 +84,9 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = { ...@@ -70,7 +84,9 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
{"DMIC1 Pin", NULL, "DMIC2"}, {"DMIC1 Pin", NULL, "DMIC2"},
{"DMic", NULL, "SoC DMIC"}, {"DMic", NULL, "SoC DMIC"},
{"WoV Sink", NULL, "hwd_in sink"}, {"HDMI1", NULL, "hif5 Output"},
{"HDMI2", NULL, "hif6 Output"},
{"HDMI3", NULL, "hif7 Output"},
/* CODEC BE connections */ /* CODEC BE connections */
{ "AIF1 Playback", NULL, "ssp0 Tx"}, { "AIF1 Playback", NULL, "ssp0 Tx"},
...@@ -84,8 +100,12 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = { ...@@ -84,8 +100,12 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = {
{ "dmic01_hifi", NULL, "DMIC01 Rx" }, { "dmic01_hifi", NULL, "DMIC01 Rx" },
{ "DMIC01 Rx", NULL, "DMIC AIF" }, { "DMIC01 Rx", NULL, "DMIC AIF" },
{ "hif1", NULL, "iDisp Tx"}, { "hifi3", NULL, "iDisp3 Tx"},
{ "iDisp Tx", NULL, "iDisp_out"}, { "iDisp3 Tx", NULL, "iDisp3_out"},
{ "hifi2", NULL, "iDisp2 Tx"},
{ "iDisp2 Tx", NULL, "iDisp2_out"},
{ "hifi1", NULL, "iDisp1 Tx"},
{ "iDisp1 Tx", NULL, "iDisp1_out"},
}; };
...@@ -116,11 +136,17 @@ static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) ...@@ -116,11 +136,17 @@ static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd)
rt286_mic_detect(codec, &skylake_headset); rt286_mic_detect(codec, &skylake_headset);
snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC"); snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "SoC DMIC");
snd_soc_dapm_ignore_suspend(&rtd->card->dapm, "WoV Sink");
return 0; return 0;
} }
static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->codec_dai;
return hdac_hdmi_jack_init(dai, SKL_DPCM_AUDIO_HDMI1_PB + dai->id);
}
static unsigned int rates[] = { static unsigned int rates[] = {
48000, 48000,
}; };
...@@ -249,7 +275,7 @@ static struct snd_soc_ops skylake_dmic_ops = { ...@@ -249,7 +275,7 @@ static struct snd_soc_ops skylake_dmic_ops = {
/* skylake digital audio interface glue - connects codec <--> CPU */ /* skylake digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link skylake_rt286_dais[] = { static struct snd_soc_dai_link skylake_rt286_dais[] = {
/* Front End DAI links */ /* Front End DAI links */
{ [SKL_DPCM_AUDIO_PB] = {
.name = "Skl Audio Port", .name = "Skl Audio Port",
.stream_name = "Audio", .stream_name = "Audio",
.cpu_dai_name = "System Pin", .cpu_dai_name = "System Pin",
...@@ -266,7 +292,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { ...@@ -266,7 +292,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.dpcm_playback = 1, .dpcm_playback = 1,
.ops = &skylake_rt286_fe_ops, .ops = &skylake_rt286_fe_ops,
}, },
{ [SKL_DPCM_AUDIO_CP] = {
.name = "Skl Audio Capture Port", .name = "Skl Audio Capture Port",
.stream_name = "Audio Record", .stream_name = "Audio Record",
.cpu_dai_name = "System Pin", .cpu_dai_name = "System Pin",
...@@ -282,7 +308,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { ...@@ -282,7 +308,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.dpcm_capture = 1, .dpcm_capture = 1,
.ops = &skylake_rt286_fe_ops, .ops = &skylake_rt286_fe_ops,
}, },
{ [SKL_DPCM_AUDIO_REF_CP] = {
.name = "Skl Audio Reference cap", .name = "Skl Audio Reference cap",
.stream_name = "refcap", .stream_name = "refcap",
.cpu_dai_name = "Reference Pin", .cpu_dai_name = "Reference Pin",
...@@ -295,7 +321,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { ...@@ -295,7 +321,7 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.nonatomic = 1, .nonatomic = 1,
.dynamic = 1, .dynamic = 1,
}, },
{ [SKL_DPCM_AUDIO_DMIC_CP] = {
.name = "Skl Audio DMIC cap", .name = "Skl Audio DMIC cap",
.stream_name = "dmiccap", .stream_name = "dmiccap",
.cpu_dai_name = "DMIC Pin", .cpu_dai_name = "DMIC Pin",
...@@ -308,6 +334,42 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { ...@@ -308,6 +334,42 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.dynamic = 1, .dynamic = 1,
.ops = &skylake_dmic_ops, .ops = &skylake_dmic_ops,
}, },
[SKL_DPCM_AUDIO_HDMI1_PB] = {
.name = "Skl 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,
.nonatomic = 1,
.dynamic = 1,
},
[SKL_DPCM_AUDIO_HDMI2_PB] = {
.name = "Skl 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,
.nonatomic = 1,
.dynamic = 1,
},
[SKL_DPCM_AUDIO_HDMI3_PB] = {
.name = "Skl 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",
.dpcm_playback = 1,
.init = NULL,
.nonatomic = 1,
.dynamic = 1,
},
/* Back End DAI links */ /* Back End DAI links */
{ {
...@@ -341,6 +403,39 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = { ...@@ -341,6 +403,39 @@ static struct snd_soc_dai_link skylake_rt286_dais[] = {
.dpcm_capture = 1, .dpcm_capture = 1,
.no_pcm = 1, .no_pcm = 1,
}, },
{
.name = "iDisp1",
.be_id = 2,
.cpu_dai_name = "iDisp1 Pin",
.codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi1",
.platform_name = "0000:00:1f.3",
.init = skylake_hdmi_init,
.dpcm_playback = 1,
.no_pcm = 1,
},
{
.name = "iDisp2",
.be_id = 3,
.cpu_dai_name = "iDisp2 Pin",
.codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi2",
.platform_name = "0000:00:1f.3",
.init = skylake_hdmi_init,
.dpcm_playback = 1,
.no_pcm = 1,
},
{
.name = "iDisp3",
.be_id = 4,
.cpu_dai_name = "iDisp3 Pin",
.codec_name = "ehdaudio0D2",
.codec_dai_name = "intel-hdmi-hifi3",
.platform_name = "0000:00:1f.3",
.init = skylake_hdmi_init,
.dpcm_playback = 1,
.no_pcm = 1,
},
}; };
/* skylake audio machine driver for SPT + RT286S */ /* skylake audio machine driver for SPT + RT286S */
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
#include <linux/acpi.h> #include <linux/acpi.h>
/* translation fron HID to I2C name, needed for DAI codec_name */
const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN]);
/* acpi match */ /* acpi match */
struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines); struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines);
......
...@@ -317,6 +317,7 @@ struct sst_dsp { ...@@ -317,6 +317,7 @@ struct sst_dsp {
struct skl_cl_dev cl_dev; struct skl_cl_dev cl_dev;
u32 intr_status; u32 intr_status;
const struct firmware *fw; const struct firmware *fw;
struct snd_dma_buffer dmab;
}; };
/* Size optimised DRAM/IRAM memcpy */ /* Size optimised DRAM/IRAM memcpy */
......
...@@ -13,17 +13,53 @@ ...@@ -13,17 +13,53 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
*/ */
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "sst-acpi.h" #include "sst-acpi.h"
static acpi_status sst_acpi_find_name(acpi_handle handle, u32 level,
void *context, void **ret)
{
struct acpi_device *adev;
const char *name = NULL;
if (acpi_bus_get_device(handle, &adev))
return AE_OK;
if (adev->status.present && adev->status.functional) {
name = acpi_dev_name(adev);
*(const char **)ret = name;
return AE_CTRL_TERMINATE;
}
return AE_OK;
}
const char *sst_acpi_find_name_from_hid(const u8 hid[ACPI_ID_LEN])
{
const char *name = NULL;
acpi_status status;
status = acpi_get_devices(hid, sst_acpi_find_name, NULL,
(void **)&name);
if (ACPI_FAILURE(status) || name[0] == '\0')
return NULL;
return name;
}
EXPORT_SYMBOL_GPL(sst_acpi_find_name_from_hid);
static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level,
void *context, void **ret) void *context, void **ret)
{ {
unsigned long long sta;
acpi_status status;
*(bool *)context = true; *(bool *)context = true;
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
*(bool *)context = false;
return AE_OK; return AE_OK;
} }
...@@ -37,7 +73,6 @@ struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) ...@@ -37,7 +73,6 @@ struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines)
sst_acpi_mach_match, sst_acpi_mach_match,
&found, NULL)) && found) &found, NULL)) && found)
return mach; return mach;
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(sst_acpi_find_machine); EXPORT_SYMBOL_GPL(sst_acpi_find_machine);
......
...@@ -72,17 +72,47 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable) ...@@ -72,17 +72,47 @@ static void skl_dsp_enable_notification(struct skl_sst *ctx, bool enable)
skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask); skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)&mask);
} }
static struct skl_dsp_loader_ops skl_get_loader_ops(void)
{
struct skl_dsp_loader_ops loader_ops;
memset(&loader_ops, 0, sizeof(struct skl_dsp_loader_ops));
loader_ops.alloc_dma_buf = skl_alloc_dma_buf;
loader_ops.free_dma_buf = skl_free_dma_buf;
return loader_ops;
};
static const struct skl_dsp_ops dsp_ops[] = {
{
.id = 0x9d70,
.loader_ops = skl_get_loader_ops,
.init = skl_sst_dsp_init,
.cleanup = skl_sst_dsp_cleanup
},
};
static int skl_get_dsp_ops(int pci_id)
{
int i;
for (i = 0; i < ARRAY_SIZE(dsp_ops); i++) {
if (dsp_ops[i].id == pci_id)
return i;
}
return -EINVAL;
}
int skl_init_dsp(struct skl *skl) int skl_init_dsp(struct skl *skl)
{ {
void __iomem *mmio_base; void __iomem *mmio_base;
struct hdac_ext_bus *ebus = &skl->ebus; struct hdac_ext_bus *ebus = &skl->ebus;
struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus);
int irq = bus->irq;
struct skl_dsp_loader_ops loader_ops; struct skl_dsp_loader_ops loader_ops;
int ret; int irq = bus->irq;
int ret, index;
loader_ops.alloc_dma_buf = skl_alloc_dma_buf;
loader_ops.free_dma_buf = skl_free_dma_buf;
/* enable ppcap interrupt */ /* enable ppcap interrupt */
snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true); snd_hdac_ext_bus_ppcap_enable(&skl->ebus, true);
...@@ -95,8 +125,14 @@ int skl_init_dsp(struct skl *skl) ...@@ -95,8 +125,14 @@ int skl_init_dsp(struct skl *skl)
return -ENXIO; return -ENXIO;
} }
ret = skl_sst_dsp_init(bus->dev, mmio_base, irq, index = skl_get_dsp_ops(skl->pci->device);
if (index < 0)
return -EINVAL;
loader_ops = dsp_ops[index].loader_ops();
ret = dsp_ops[index].init(bus->dev, mmio_base, irq,
skl->fw_name, loader_ops, &skl->skl_sst); skl->fw_name, loader_ops, &skl->skl_sst);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -106,18 +142,26 @@ int skl_init_dsp(struct skl *skl) ...@@ -106,18 +142,26 @@ int skl_init_dsp(struct skl *skl)
return ret; return ret;
} }
void skl_free_dsp(struct skl *skl) int skl_free_dsp(struct skl *skl)
{ {
struct hdac_ext_bus *ebus = &skl->ebus; struct hdac_ext_bus *ebus = &skl->ebus;
struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus);
struct skl_sst *ctx = skl->skl_sst; struct skl_sst *ctx = skl->skl_sst;
int index;
/* disable ppcap interrupt */ /* disable ppcap interrupt */
snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false); snd_hdac_ext_bus_ppcap_int_enable(&skl->ebus, false);
skl_sst_dsp_cleanup(bus->dev, ctx); index = skl_get_dsp_ops(skl->pci->device);
if (index < 0)
return -EIO;
dsp_ops[index].cleanup(bus->dev, ctx);
if (ctx->dsp->addr.lpe) if (ctx->dsp->addr.lpe)
iounmap(ctx->dsp->addr.lpe); iounmap(ctx->dsp->addr.lpe);
return 0;
} }
int skl_suspend_dsp(struct skl *skl) int skl_suspend_dsp(struct skl *skl)
...@@ -238,9 +282,8 @@ static void skl_copy_copier_caps(struct skl_module_cfg *mconfig, ...@@ -238,9 +282,8 @@ static void skl_copy_copier_caps(struct skl_module_cfg *mconfig,
* Calculate the gatewat settings required for copier module, type of * Calculate the gatewat settings required for copier module, type of
* gateway and index of gateway to use * gateway and index of gateway to use
*/ */
static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, static u32 skl_get_node_id(struct skl_sst *ctx,
struct skl_module_cfg *mconfig, struct skl_module_cfg *mconfig)
struct skl_cpr_cfg *cpr_mconfig)
{ {
union skl_connector_node_id node_id = {0}; union skl_connector_node_id node_id = {0};
union skl_ssp_dma_node ssp_node = {0}; union skl_ssp_dma_node ssp_node = {0};
...@@ -289,13 +332,24 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, ...@@ -289,13 +332,24 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
break; break;
default: default:
cpr_mconfig->gtw_cfg.node_id = SKL_NON_GATEWAY_CPR_NODE_ID; node_id.val = 0xFFFFFFFF;
break;
}
return node_id.val;
}
static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
struct skl_module_cfg *mconfig,
struct skl_cpr_cfg *cpr_mconfig)
{
cpr_mconfig->gtw_cfg.node_id = skl_get_node_id(ctx, mconfig);
if (cpr_mconfig->gtw_cfg.node_id == SKL_NON_GATEWAY_CPR_NODE_ID) {
cpr_mconfig->cpr_feature_mask = 0; cpr_mconfig->cpr_feature_mask = 0;
return; return;
} }
cpr_mconfig->gtw_cfg.node_id = node_id.val;
if (SKL_CONN_SOURCE == mconfig->hw_conn_type) if (SKL_CONN_SOURCE == mconfig->hw_conn_type)
cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs;
else else
...@@ -307,6 +361,46 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, ...@@ -307,6 +361,46 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx,
skl_copy_copier_caps(mconfig, cpr_mconfig); skl_copy_copier_caps(mconfig, cpr_mconfig);
} }
#define DMA_CONTROL_ID 5
int skl_dsp_set_dma_control(struct skl_sst *ctx, struct skl_module_cfg *mconfig)
{
struct skl_dma_control *dma_ctrl;
struct skl_i2s_config_blob config_blob;
struct skl_ipc_large_config_msg msg = {0};
int err = 0;
/*
* if blob size is same as capablity size, then no dma control
* present so return
*/
if (mconfig->formats_config.caps_size == sizeof(config_blob))
return 0;
msg.large_param_id = DMA_CONTROL_ID;
msg.param_data_size = sizeof(struct skl_dma_control) +
mconfig->formats_config.caps_size;
dma_ctrl = kzalloc(msg.param_data_size, GFP_KERNEL);
if (dma_ctrl == NULL)
return -ENOMEM;
dma_ctrl->node_id = skl_get_node_id(ctx, mconfig);
/* size in dwords */
dma_ctrl->config_length = sizeof(config_blob) / 4;
memcpy(dma_ctrl->config_data, mconfig->formats_config.caps,
mconfig->formats_config.caps_size);
err = skl_ipc_set_large_config(&ctx->ipc, &msg, (u32 *)dma_ctrl);
kfree(dma_ctrl);
return err;
}
static void skl_setup_out_format(struct skl_sst *ctx, static void skl_setup_out_format(struct skl_sst *ctx,
struct skl_module_cfg *mconfig, struct skl_module_cfg *mconfig,
struct skl_audio_data_format *out_fmt) struct skl_audio_data_format *out_fmt)
......
...@@ -145,3 +145,37 @@ struct nhlt_specific_cfg ...@@ -145,3 +145,37 @@ struct nhlt_specific_cfg
return NULL; return NULL;
} }
static void skl_nhlt_trim_space(struct skl *skl)
{
char *s = skl->tplg_name;
int cnt;
int i;
cnt = 0;
for (i = 0; s[i]; i++) {
if (!isspace(s[i]))
s[cnt++] = s[i];
}
s[cnt] = '\0';
}
int skl_nhlt_update_topology_bin(struct skl *skl)
{
struct nhlt_acpi_table *nhlt = (struct nhlt_acpi_table *)skl->nhlt;
struct hdac_bus *bus = ebus_to_hbus(&skl->ebus);
struct device *dev = bus->dev;
dev_dbg(dev, "oem_id %.6s, oem_table_id %8s oem_revision %d\n",
nhlt->header.oem_id, nhlt->header.oem_table_id,
nhlt->header.oem_revision);
snprintf(skl->tplg_name, sizeof(skl->tplg_name), "%x-%.6s-%.8s-%d%s",
skl->pci_id, nhlt->header.oem_id, nhlt->header.oem_table_id,
nhlt->header.oem_revision, "-tplg.bin");
skl_nhlt_trim_space(skl);
return 0;
}
...@@ -206,6 +206,23 @@ static int skl_get_format(struct snd_pcm_substream *substream, ...@@ -206,6 +206,23 @@ static int skl_get_format(struct snd_pcm_substream *substream,
return format_val; return format_val;
} }
static int skl_be_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct skl *skl = get_skl_ctx(dai->dev);
struct skl_sst *ctx = skl->skl_sst;
struct skl_module_cfg *mconfig;
if ((dai->playback_active > 1) || (dai->capture_active > 1))
return 0;
mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
if (mconfig == NULL)
return -EINVAL;
return skl_dsp_set_dma_control(ctx, mconfig);
}
static int skl_pcm_prepare(struct snd_pcm_substream *substream, static int skl_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
...@@ -458,7 +475,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, ...@@ -458,7 +475,7 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev); struct hdac_ext_bus *ebus = dev_get_drvdata(dai->dev);
struct hdac_ext_stream *link_dev; struct hdac_ext_stream *link_dev;
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
struct skl_dma_params *dma_params; struct hdac_ext_dma_params *dma_params;
struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct skl_pipe_params p_params = {0}; struct skl_pipe_params p_params = {0};
...@@ -470,11 +487,9 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream, ...@@ -470,11 +487,9 @@ static int skl_link_hw_params(struct snd_pcm_substream *substream,
snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev); snd_soc_dai_set_dma_data(dai, substream, (void *)link_dev);
/* set the stream tag in the codec dai dma params */ /* set the stream tag in the codec dai dma params */
dma_params = (struct skl_dma_params *) dma_params = snd_soc_dai_get_dma_data(codec_dai, substream);
snd_soc_dai_get_dma_data(codec_dai, substream);
if (dma_params) if (dma_params)
dma_params->stream_tag = hdac_stream(link_dev)->stream_tag; dma_params->stream_tag = hdac_stream(link_dev)->stream_tag;
snd_soc_dai_set_dma_data(codec_dai, substream, (void *)dma_params);
p_params.s_fmt = snd_pcm_format_width(params_format(params)); p_params.s_fmt = snd_pcm_format_width(params_format(params));
p_params.ch = params_channels(params); p_params.ch = params_channels(params);
...@@ -588,6 +603,7 @@ static struct snd_soc_dai_ops skl_dmic_dai_ops = { ...@@ -588,6 +603,7 @@ static struct snd_soc_dai_ops skl_dmic_dai_ops = {
static struct snd_soc_dai_ops skl_be_ssp_dai_ops = { static struct snd_soc_dai_ops skl_be_ssp_dai_ops = {
.hw_params = skl_be_hw_params, .hw_params = skl_be_hw_params,
.prepare = skl_be_prepare,
}; };
static struct snd_soc_dai_ops skl_link_dai_ops = { static struct snd_soc_dai_ops skl_link_dai_ops = {
...@@ -660,6 +676,51 @@ static struct snd_soc_dai_driver skl_platform_dai[] = { ...@@ -660,6 +676,51 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
}, },
}, },
{
.name = "HDMI1 Pin",
.ops = &skl_pcm_dai_ops,
.playback = {
.stream_name = "HDMI1 Playback",
.channels_min = HDA_STEREO,
.channels_max = HDA_STEREO,
.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
{
.name = "HDMI2 Pin",
.ops = &skl_pcm_dai_ops,
.playback = {
.stream_name = "HDMI2 Playback",
.channels_min = HDA_STEREO,
.channels_max = HDA_STEREO,
.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
{
.name = "HDMI3 Pin",
.ops = &skl_pcm_dai_ops,
.playback = {
.stream_name = "HDMI3 Playback",
.channels_min = HDA_STEREO,
.channels_max = HDA_STEREO,
.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
/* BE CPU Dais */ /* BE CPU Dais */
{ {
...@@ -699,14 +760,41 @@ static struct snd_soc_dai_driver skl_platform_dai[] = { ...@@ -699,14 +760,41 @@ static struct snd_soc_dai_driver skl_platform_dai[] = {
}, },
}, },
{ {
.name = "iDisp Pin", .name = "iDisp1 Pin",
.ops = &skl_link_dai_ops, .ops = &skl_link_dai_ops,
.playback = { .playback = {
.stream_name = "iDisp Tx", .stream_name = "iDisp1 Tx",
.channels_min = HDA_STEREO, .channels_min = HDA_STEREO,
.channels_max = HDA_STEREO, .channels_max = HDA_STEREO,
.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000, .rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
SNDRV_PCM_FMTBIT_S24_LE,
},
},
{
.name = "iDisp2 Pin",
.ops = &skl_link_dai_ops,
.playback = {
.stream_name = "iDisp2 Tx",
.channels_min = HDA_STEREO,
.channels_max = HDA_STEREO,
.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
SNDRV_PCM_FMTBIT_S24_LE,
},
},
{
.name = "iDisp3 Pin",
.ops = &skl_link_dai_ops,
.playback = {
.stream_name = "iDisp3 Tx",
.channels_min = HDA_STEREO,
.channels_max = HDA_STEREO,
.rates = SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|
SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
SNDRV_PCM_FMTBIT_S24_LE,
}, },
}, },
{ {
...@@ -863,7 +951,9 @@ static int skl_get_delay_from_lpib(struct hdac_ext_bus *ebus, ...@@ -863,7 +951,9 @@ static int skl_get_delay_from_lpib(struct hdac_ext_bus *ebus,
else else
delay += hstream->bufsize; delay += hstream->bufsize;
} }
delay = (hstream->bufsize == delay) ? 0 : delay;
if (hstream->bufsize == delay)
delay = 0;
if (delay >= hstream->period_bytes) { if (delay >= hstream->period_bytes) {
dev_info(bus->dev, dev_info(bus->dev,
......
...@@ -34,7 +34,7 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state) ...@@ -34,7 +34,7 @@ void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state)
mutex_unlock(&ctx->mutex); mutex_unlock(&ctx->mutex);
} }
static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx)
{ {
int ret; int ret;
...@@ -60,7 +60,7 @@ static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx) ...@@ -60,7 +60,7 @@ static int skl_dsp_core_set_reset_state(struct sst_dsp *ctx)
return ret; return ret;
} }
static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
{ {
int ret; int ret;
...@@ -87,7 +87,7 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx) ...@@ -87,7 +87,7 @@ static int skl_dsp_core_unset_reset_state(struct sst_dsp *ctx)
return ret; return ret;
} }
static bool is_skl_dsp_core_enable(struct sst_dsp *ctx) static bool is_skl_dsp_core_enable(struct sst_dsp *ctx)
{ {
int val; int val;
bool is_enable; bool is_enable;
...@@ -140,7 +140,7 @@ static int skl_dsp_start_core(struct sst_dsp *ctx) ...@@ -140,7 +140,7 @@ static int skl_dsp_start_core(struct sst_dsp *ctx)
return ret; return ret;
} }
static int skl_dsp_core_power_up(struct sst_dsp *ctx) static int skl_dsp_core_power_up(struct sst_dsp *ctx)
{ {
int ret; int ret;
...@@ -166,7 +166,7 @@ static int skl_dsp_core_power_up(struct sst_dsp *ctx) ...@@ -166,7 +166,7 @@ static int skl_dsp_core_power_up(struct sst_dsp *ctx)
return ret; return ret;
} }
static int skl_dsp_core_power_down(struct sst_dsp *ctx) static int skl_dsp_core_power_down(struct sst_dsp *ctx)
{ {
/* update bits */ /* update bits */
sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS, sst_dsp_shim_update_bits_unlocked(ctx, SKL_ADSP_REG_ADSPCS,
...@@ -181,7 +181,7 @@ static int skl_dsp_core_power_down(struct sst_dsp *ctx) ...@@ -181,7 +181,7 @@ static int skl_dsp_core_power_down(struct sst_dsp *ctx)
"Power down"); "Power down");
} }
static int skl_dsp_enable_core(struct sst_dsp *ctx) int skl_dsp_enable_core(struct sst_dsp *ctx)
{ {
int ret; int ret;
...@@ -195,7 +195,7 @@ static int skl_dsp_enable_core(struct sst_dsp *ctx) ...@@ -195,7 +195,7 @@ static int skl_dsp_enable_core(struct sst_dsp *ctx)
return skl_dsp_start_core(ctx); return skl_dsp_start_core(ctx);
} }
int skl_dsp_disable_core(struct sst_dsp *ctx) int skl_dsp_disable_core(struct sst_dsp *ctx)
{ {
int ret; int ret;
......
...@@ -53,6 +53,10 @@ struct sst_dsp_device; ...@@ -53,6 +53,10 @@ struct sst_dsp_device;
/* HIPCT */ /* HIPCT */
#define SKL_ADSP_REG_HIPCT_BUSY BIT(31) #define SKL_ADSP_REG_HIPCT_BUSY BIT(31)
/* FW base IDs */
#define SKL_INSTANCE_ID 0
#define SKL_BASE_FW_MODULE_ID 0
/* Intel HD Audio SRAM Window 1 */ /* Intel HD Audio SRAM Window 1 */
#define SKL_ADSP_SRAM1_BASE 0xA000 #define SKL_ADSP_SRAM1_BASE 0xA000
...@@ -144,7 +148,8 @@ int skl_cldma_prepare(struct sst_dsp *ctx); ...@@ -144,7 +148,8 @@ int skl_cldma_prepare(struct sst_dsp *ctx);
void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state); void skl_dsp_set_state_locked(struct sst_dsp *ctx, int state);
struct sst_dsp *skl_dsp_ctx_init(struct device *dev, struct sst_dsp *skl_dsp_ctx_init(struct device *dev,
struct sst_dsp_device *sst_dev, int irq); struct sst_dsp_device *sst_dev, int irq);
int skl_dsp_disable_core(struct sst_dsp *ctx); int skl_dsp_enable_core(struct sst_dsp *ctx);
int skl_dsp_disable_core(struct sst_dsp *ctx);
bool is_skl_dsp_running(struct sst_dsp *ctx); bool is_skl_dsp_running(struct sst_dsp *ctx);
irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id); irqreturn_t skl_dsp_sst_interrupt(int irq, void *dev_id);
int skl_dsp_wake(struct sst_dsp *ctx); int skl_dsp_wake(struct sst_dsp *ctx);
......
...@@ -35,9 +35,6 @@ ...@@ -35,9 +35,6 @@
#define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE #define SKL_ADSP_FW_STATUS SKL_ADSP_SRAM0_BASE
#define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4) #define SKL_ADSP_ERROR_CODE (SKL_ADSP_FW_STATUS + 0x4)
#define SKL_INSTANCE_ID 0
#define SKL_BASE_FW_MODULE_ID 0
#define SKL_NUM_MODULES 1 #define SKL_NUM_MODULES 1
static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status) static bool skl_check_fw_status(struct sst_dsp *ctx, u32 status)
......
...@@ -260,6 +260,65 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx, ...@@ -260,6 +260,65 @@ static void skl_tplg_update_buffer_size(struct skl_sst *ctx,
multiplier; multiplier;
} }
static int skl_tplg_update_be_blob(struct snd_soc_dapm_widget *w,
struct skl_sst *ctx)
{
struct skl_module_cfg *m_cfg = w->priv;
int link_type, dir;
u32 ch, s_freq, s_fmt;
struct nhlt_specific_cfg *cfg;
struct skl *skl = get_skl_ctx(ctx->dev);
/* check if we already have blob */
if (m_cfg->formats_config.caps_size > 0)
return 0;
dev_dbg(ctx->dev, "Applying default cfg blob\n");
switch (m_cfg->dev_type) {
case SKL_DEVICE_DMIC:
link_type = NHLT_LINK_DMIC;
dir = SNDRV_PCM_STREAM_CAPTURE;
s_freq = m_cfg->in_fmt[0].s_freq;
s_fmt = m_cfg->in_fmt[0].bit_depth;
ch = m_cfg->in_fmt[0].channels;
break;
case SKL_DEVICE_I2S:
link_type = NHLT_LINK_SSP;
if (m_cfg->hw_conn_type == SKL_CONN_SOURCE) {
dir = SNDRV_PCM_STREAM_PLAYBACK;
s_freq = m_cfg->out_fmt[0].s_freq;
s_fmt = m_cfg->out_fmt[0].bit_depth;
ch = m_cfg->out_fmt[0].channels;
} else {
dir = SNDRV_PCM_STREAM_CAPTURE;
s_freq = m_cfg->in_fmt[0].s_freq;
s_fmt = m_cfg->in_fmt[0].bit_depth;
ch = m_cfg->in_fmt[0].channels;
}
break;
default:
return -EINVAL;
}
/* update the blob based on virtual bus_id and default params */
cfg = skl_get_ep_blob(skl, m_cfg->vbus_id, link_type,
s_fmt, ch, s_freq, dir);
if (cfg) {
m_cfg->formats_config.caps_size = cfg->size;
m_cfg->formats_config.caps = (u32 *) &cfg->caps;
} else {
dev_err(ctx->dev, "Blob NULL for id %x type %d dirn %d\n",
m_cfg->vbus_id, link_type, dir);
dev_err(ctx->dev, "PCM: ch %d, freq %d, fmt %d\n",
ch, s_freq, s_fmt);
return -EIO;
}
return 0;
}
static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w, static void skl_tplg_update_module_params(struct snd_soc_dapm_widget *w,
struct skl_sst *ctx) struct skl_sst *ctx)
{ {
...@@ -433,6 +492,9 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe) ...@@ -433,6 +492,9 @@ skl_tplg_init_pipe_modules(struct skl *skl, struct skl_pipe *pipe)
return ret; return ret;
} }
/* update blob if blob is null for be with default value */
skl_tplg_update_be_blob(w, ctx);
/* /*
* apply fix/conversion to module params based on * apply fix/conversion to module params based on
* FE/BE params * FE/BE params
...@@ -545,6 +607,66 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, ...@@ -545,6 +607,66 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
/*
* Some modules require params to be set after the module is bound to
* all pins connected.
*
* The module provider initializes set_param flag for such modules and we
* send params after binding
*/
static int skl_tplg_set_module_bind_params(struct snd_soc_dapm_widget *w,
struct skl_module_cfg *mcfg, struct skl_sst *ctx)
{
int i, ret;
struct skl_module_cfg *mconfig = w->priv;
const struct snd_kcontrol_new *k;
struct soc_bytes_ext *sb;
struct skl_algo_data *bc;
struct skl_specific_cfg *sp_cfg;
/*
* check all out/in pins are in bind state.
* if so set the module param
*/
for (i = 0; i < mcfg->max_out_queue; i++) {
if (mcfg->m_out_pin[i].pin_state != SKL_PIN_BIND_DONE)
return 0;
}
for (i = 0; i < mcfg->max_in_queue; i++) {
if (mcfg->m_in_pin[i].pin_state != SKL_PIN_BIND_DONE)
return 0;
}
if (mconfig->formats_config.caps_size > 0 &&
mconfig->formats_config.set_params == SKL_PARAM_BIND) {
sp_cfg = &mconfig->formats_config;
ret = skl_set_module_params(ctx, sp_cfg->caps,
sp_cfg->caps_size,
sp_cfg->param_id, mconfig);
if (ret < 0)
return ret;
}
for (i = 0; i < w->num_kcontrols; i++) {
k = &w->kcontrol_news[i];
if (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
sb = (void *) k->private_value;
bc = (struct skl_algo_data *)sb->dobj.private;
if (bc->set_params == SKL_PARAM_BIND) {
ret = skl_set_module_params(ctx,
(u32 *)bc->params, bc->max,
bc->param_id, mconfig);
if (ret < 0)
return ret;
}
}
}
return 0;
}
static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
struct skl *skl, struct skl *skl,
struct snd_soc_dapm_widget *src_w, struct snd_soc_dapm_widget *src_w,
...@@ -579,11 +701,19 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w, ...@@ -579,11 +701,19 @@ static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
sink = p->sink; sink = p->sink;
sink_mconfig = sink->priv; sink_mconfig = sink->priv;
if (src_mconfig->m_state == SKL_MODULE_UNINIT ||
sink_mconfig->m_state == SKL_MODULE_UNINIT)
continue;
/* Bind source to sink, mixin is always source */ /* Bind source to sink, mixin is always source */
ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig); ret = skl_bind_modules(ctx, src_mconfig, sink_mconfig);
if (ret) if (ret)
return ret; return ret;
/* set module params after bind */
skl_tplg_set_module_bind_params(src_w, src_mconfig, ctx);
skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx);
/* Start sinks pipe first */ /* Start sinks pipe first */
if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) { if (sink_mconfig->pipe->state != SKL_PIPE_STARTED) {
if (sink_mconfig->pipe->conn_type != if (sink_mconfig->pipe->conn_type !=
...@@ -714,6 +844,10 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w, ...@@ -714,6 +844,10 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
if (ret) if (ret)
return ret; return ret;
/* set module params after bind */
skl_tplg_set_module_bind_params(source, src_mconfig, ctx);
skl_tplg_set_module_bind_params(sink, sink_mconfig, ctx);
if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE) if (sink_mconfig->pipe->conn_type != SKL_PIPE_CONN_TYPE_FE)
ret = skl_run_pipe(ctx, sink_mconfig->pipe); ret = skl_run_pipe(ctx, sink_mconfig->pipe);
} }
...@@ -1091,6 +1225,66 @@ skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream) ...@@ -1091,6 +1225,66 @@ skl_tplg_fe_get_cpr_module(struct snd_soc_dai *dai, int stream)
return NULL; return NULL;
} }
static struct skl_module_cfg *skl_get_mconfig_pb_cpr(
struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w)
{
struct snd_soc_dapm_path *p;
struct skl_module_cfg *mconfig = NULL;
snd_soc_dapm_widget_for_each_source_path(w, p) {
if (w->endpoints[SND_SOC_DAPM_DIR_OUT] > 0) {
if (p->connect &&
(p->sink->id == snd_soc_dapm_aif_out) &&
p->source->priv) {
mconfig = p->source->priv;
return mconfig;
}
mconfig = skl_get_mconfig_pb_cpr(dai, p->source);
if (mconfig)
return mconfig;
}
}
return mconfig;
}
static struct skl_module_cfg *skl_get_mconfig_cap_cpr(
struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w)
{
struct snd_soc_dapm_path *p;
struct skl_module_cfg *mconfig = NULL;
snd_soc_dapm_widget_for_each_sink_path(w, p) {
if (w->endpoints[SND_SOC_DAPM_DIR_IN] > 0) {
if (p->connect &&
(p->source->id == snd_soc_dapm_aif_in) &&
p->sink->priv) {
mconfig = p->sink->priv;
return mconfig;
}
mconfig = skl_get_mconfig_cap_cpr(dai, p->sink);
if (mconfig)
return mconfig;
}
}
return mconfig;
}
struct skl_module_cfg *
skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai, int stream)
{
struct snd_soc_dapm_widget *w;
struct skl_module_cfg *mconfig;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
w = dai->playback_widget;
mconfig = skl_get_mconfig_pb_cpr(dai, w);
} else {
w = dai->capture_widget;
mconfig = skl_get_mconfig_cap_cpr(dai, w);
}
return mconfig;
}
static u8 skl_tplg_be_link_type(int dev_type) static u8 skl_tplg_be_link_type(int dev_type)
{ {
int ret; int ret;
...@@ -1464,8 +1658,7 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be, ...@@ -1464,8 +1658,7 @@ static int skl_init_algo_data(struct device *dev, struct soc_bytes_ext *be,
if (!ac->params) if (!ac->params)
return -ENOMEM; return -ENOMEM;
if (dfw_ac->params) memcpy(ac->params, dfw_ac->params, ac->max);
memcpy(ac->params, dfw_ac->params, ac->max);
} }
be->dobj.private = ac; be->dobj.private = ac;
...@@ -1523,11 +1716,16 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus) ...@@ -1523,11 +1716,16 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus);
struct skl *skl = ebus_to_skl(ebus); struct skl *skl = ebus_to_skl(ebus);
ret = request_firmware(&fw, "dfw_sst.bin", bus->dev); ret = request_firmware(&fw, skl->tplg_name, bus->dev);
if (ret < 0) { if (ret < 0) {
dev_err(bus->dev, "tplg fw %s load failed with %d\n", dev_err(bus->dev, "tplg fw %s load failed with %d\n",
"dfw_sst.bin", ret); skl->tplg_name, ret);
return ret; ret = request_firmware(&fw, "dfw_sst.bin", bus->dev);
if (ret < 0) {
dev_err(bus->dev, "Fallback tplg fw %s load failed with %d\n",
"dfw_sst.bin", ret);
return ret;
}
} }
/* /*
......
...@@ -113,6 +113,29 @@ struct skl_cpr_gtw_cfg { ...@@ -113,6 +113,29 @@ struct skl_cpr_gtw_cfg {
u32 config_data[1]; u32 config_data[1];
} __packed; } __packed;
struct skl_i2s_config_blob {
u32 gateway_attrib;
u32 tdm_ts_group[8];
u32 ssc0;
u32 ssc1;
u32 sscto;
u32 sspsp;
u32 sstsa;
u32 ssrsa;
u32 ssc2;
u32 sspsp2;
u32 ssc3;
u32 ssioc;
u32 mdivc;
u32 mdivr;
} __packed;
struct skl_dma_control {
u32 node_id;
u32 config_length;
u32 config_data[1];
} __packed;
struct skl_cpr_cfg { struct skl_cpr_cfg {
struct skl_base_cfg base_cfg; struct skl_base_cfg base_cfg;
struct skl_audio_data_format out_fmt; struct skl_audio_data_format out_fmt;
...@@ -313,6 +336,8 @@ static inline struct skl *get_skl_ctx(struct device *dev) ...@@ -313,6 +336,8 @@ static inline struct skl *get_skl_ctx(struct device *dev)
int skl_tplg_be_update_params(struct snd_soc_dai *dai, int skl_tplg_be_update_params(struct snd_soc_dai *dai,
struct skl_pipe_params *params); struct skl_pipe_params *params);
int skl_dsp_set_dma_control(struct skl_sst *ctx,
struct skl_module_cfg *mconfig);
void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai, void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai,
struct skl_pipe_params *params, int stream); struct skl_pipe_params *params, int stream);
int skl_tplg_init(struct snd_soc_platform *platform, int skl_tplg_init(struct snd_soc_platform *platform,
...@@ -345,5 +370,7 @@ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size, ...@@ -345,5 +370,7 @@ int skl_set_module_params(struct skl_sst *ctx, u32 *params, int size,
int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size, int skl_get_module_params(struct skl_sst *ctx, u32 *params, int size,
u32 param_id, struct skl_module_cfg *mcfg); u32 param_id, struct skl_module_cfg *mcfg);
struct skl_module_cfg *skl_tplg_be_get_cpr_module(struct snd_soc_dai *dai,
int stream);
enum skl_bitdepth skl_get_bit_depth(int params); enum skl_bitdepth skl_get_bit_depth(int params);
#endif #endif
...@@ -144,7 +144,8 @@ enum module_pin_type { ...@@ -144,7 +144,8 @@ enum module_pin_type {
enum skl_module_param_type { enum skl_module_param_type {
SKL_PARAM_DEFAULT = 0, SKL_PARAM_DEFAULT = 0,
SKL_PARAM_INIT, SKL_PARAM_INIT,
SKL_PARAM_SET SKL_PARAM_SET,
SKL_PARAM_BIND
}; };
struct skl_dfw_module_pin { struct skl_dfw_module_pin {
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include "../common/sst-acpi.h" #include "../common/sst-acpi.h"
#include <sound/hda_register.h>
#include <sound/hdaudio.h>
#include <sound/hda_i915.h>
#include "skl.h" #include "skl.h"
#include "skl-sst-dsp.h" #include "skl-sst-dsp.h"
#include "skl-sst-ipc.h" #include "skl-sst-ipc.h"
...@@ -243,6 +246,16 @@ static int skl_resume(struct device *dev) ...@@ -243,6 +246,16 @@ static int skl_resume(struct device *dev)
struct hdac_bus *bus = ebus_to_hbus(ebus); struct hdac_bus *bus = ebus_to_hbus(ebus);
int ret; int ret;
/* Turned OFF in HDMI codec driver after codec reconfiguration */
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
ret = snd_hdac_display_power(bus, true);
if (ret < 0) {
dev_err(bus->dev,
"Cannot turn on display power on i915\n");
return ret;
}
}
/* /*
* resume only when we are not in suspend active, otherwise need to * resume only when we are not in suspend active, otherwise need to
* restore the device * restore the device
...@@ -481,6 +494,27 @@ static int skl_create(struct pci_dev *pci, ...@@ -481,6 +494,27 @@ static int skl_create(struct pci_dev *pci,
return 0; 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) static int skl_first_init(struct hdac_ext_bus *ebus)
{ {
struct skl *skl = ebus_to_skl(ebus); struct skl *skl = ebus_to_skl(ebus);
...@@ -543,6 +577,12 @@ static int skl_first_init(struct hdac_ext_bus *ebus) ...@@ -543,6 +577,12 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
/* initialize chip */ /* initialize chip */
skl_init_pci(skl); 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); skl_init_chip(bus, true);
/* codec detection */ /* codec detection */
...@@ -573,11 +613,15 @@ static int skl_probe(struct pci_dev *pci, ...@@ -573,11 +613,15 @@ static int skl_probe(struct pci_dev *pci,
if (err < 0) if (err < 0)
goto out_free; goto out_free;
skl->pci_id = pci->device;
skl->nhlt = skl_nhlt_init(bus->dev); skl->nhlt = skl_nhlt_init(bus->dev);
if (skl->nhlt == NULL) if (skl->nhlt == NULL)
goto out_free; goto out_free;
skl_nhlt_update_topology_bin(skl);
pci_set_drvdata(skl->pci, ebus); pci_set_drvdata(skl->pci, ebus);
/* check if dsp is there */ /* check if dsp is there */
...@@ -613,6 +657,14 @@ static int skl_probe(struct pci_dev *pci, ...@@ -613,6 +657,14 @@ static int skl_probe(struct pci_dev *pci,
if (err < 0) if (err < 0)
goto out_unregister; 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;
}
}
/*configure PM */ /*configure PM */
pm_runtime_put_noidle(bus->dev); pm_runtime_put_noidle(bus->dev);
pm_runtime_allow(bus->dev); pm_runtime_allow(bus->dev);
...@@ -634,6 +686,31 @@ static int skl_probe(struct pci_dev *pci, ...@@ -634,6 +686,31 @@ static int skl_probe(struct pci_dev *pci,
return err; return err;
} }
static void skl_shutdown(struct pci_dev *pci)
{
struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
struct hdac_bus *bus = ebus_to_hbus(ebus);
struct hdac_stream *s;
struct hdac_ext_stream *stream;
struct skl *skl;
if (ebus == NULL)
return;
skl = ebus_to_skl(ebus);
if (skl->init_failed)
return;
snd_hdac_ext_stop_streams(ebus);
list_for_each_entry(s, &bus->stream_list, list) {
stream = stream_to_hdac_ext_stream(s);
snd_hdac_ext_stream_decouple(ebus, stream, false);
}
snd_hdac_bus_stop_chip(bus);
}
static void skl_remove(struct pci_dev *pci) static void skl_remove(struct pci_dev *pci)
{ {
struct hdac_ext_bus *ebus = pci_get_drvdata(pci); struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
...@@ -642,6 +719,9 @@ static void skl_remove(struct pci_dev *pci) ...@@ -642,6 +719,9 @@ static void skl_remove(struct pci_dev *pci)
if (skl->tplg) if (skl->tplg)
release_firmware(skl->tplg); release_firmware(skl->tplg);
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
snd_hdac_i915_exit(&ebus->bus);
if (pci_dev_run_wake(pci)) if (pci_dev_run_wake(pci))
pm_runtime_get_noresume(&pci->dev); pm_runtime_get_noresume(&pci->dev);
pci_dev_put(pci); pci_dev_put(pci);
...@@ -662,11 +742,18 @@ static struct sst_acpi_mach sst_skl_devdata[] = { ...@@ -662,11 +742,18 @@ static struct sst_acpi_mach sst_skl_devdata[] = {
{} {}
}; };
static struct sst_acpi_mach sst_bxtp_devdata[] = {
{ "INT343A", "bxt_alc298s_i2s", "intel/dsp_fw_bxtn.bin", NULL, NULL, NULL },
};
/* PCI IDs */ /* PCI IDs */
static const struct pci_device_id skl_ids[] = { static const struct pci_device_id skl_ids[] = {
/* Sunrise Point-LP */ /* Sunrise Point-LP */
{ PCI_DEVICE(0x8086, 0x9d70), { PCI_DEVICE(0x8086, 0x9d70),
.driver_data = (unsigned long)&sst_skl_devdata}, .driver_data = (unsigned long)&sst_skl_devdata},
/* BXT-P */
{ PCI_DEVICE(0x8086, 0x5a98),
.driver_data = (unsigned long)&sst_bxtp_devdata},
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, skl_ids); MODULE_DEVICE_TABLE(pci, skl_ids);
...@@ -677,6 +764,7 @@ static struct pci_driver skl_driver = { ...@@ -677,6 +764,7 @@ static struct pci_driver skl_driver = {
.id_table = skl_ids, .id_table = skl_ids,
.probe = skl_probe, .probe = skl_probe,
.remove = skl_remove, .remove = skl_remove,
.shutdown = skl_shutdown,
.driver = { .driver = {
.pm = &skl_pm, .pm = &skl_pm,
}, },
......
...@@ -73,6 +73,8 @@ struct skl { ...@@ -73,6 +73,8 @@ struct skl {
struct list_head ppl_list; struct list_head ppl_list;
const char *fw_name; const char *fw_name;
char tplg_name[64];
unsigned short pci_id;
const struct firmware *tplg; const struct firmware *tplg;
int supend_active; int supend_active;
...@@ -88,6 +90,16 @@ struct skl_dma_params { ...@@ -88,6 +90,16 @@ struct skl_dma_params {
u8 stream_tag; u8 stream_tag;
}; };
struct skl_dsp_ops {
int id;
struct skl_dsp_loader_ops (*loader_ops)(void);
int (*init)(struct device *dev, void __iomem *mmio_base,
int irq, const char *fw_name,
struct skl_dsp_loader_ops loader_ops,
struct skl_sst **skl_sst);
void (*cleanup)(struct device *dev, struct skl_sst *ctx);
};
int skl_platform_unregister(struct device *dev); int skl_platform_unregister(struct device *dev);
int skl_platform_register(struct device *dev); int skl_platform_register(struct device *dev);
...@@ -96,8 +108,9 @@ void skl_nhlt_free(void *addr); ...@@ -96,8 +108,9 @@ void skl_nhlt_free(void *addr);
struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance, struct nhlt_specific_cfg *skl_get_ep_blob(struct skl *skl, u32 instance,
u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn); u8 link_type, u8 s_fmt, u8 no_ch, u32 s_rate, u8 dirn);
int skl_nhlt_update_topology_bin(struct skl *skl);
int skl_init_dsp(struct skl *skl); int skl_init_dsp(struct skl *skl);
void skl_free_dsp(struct skl *skl); int skl_free_dsp(struct skl *skl);
int skl_suspend_dsp(struct skl *skl); int skl_suspend_dsp(struct skl *skl);
int skl_resume_dsp(struct skl *skl); int skl_resume_dsp(struct skl *skl);
#endif /* __SOUND_SOC_SKL_H */ #endif /* __SOUND_SOC_SKL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment