mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 14:20:55 +07:00
Merge branch 'asoc-5.4' into asoc-5.5
This commit is contained in:
commit
25317997cb
@ -901,16 +901,20 @@ static void max98373_slot_config(struct i2c_client *i2c,
|
||||
max98373->i_slot = value & 0xF;
|
||||
else
|
||||
max98373->i_slot = 1;
|
||||
|
||||
max98373->reset_gpio = of_get_named_gpio(dev->of_node,
|
||||
if (dev->of_node) {
|
||||
max98373->reset_gpio = of_get_named_gpio(dev->of_node,
|
||||
"maxim,reset-gpio", 0);
|
||||
if (!gpio_is_valid(max98373->reset_gpio)) {
|
||||
dev_err(dev, "Looking up %s property in node %s failed %d\n",
|
||||
"maxim,reset-gpio", dev->of_node->full_name,
|
||||
max98373->reset_gpio);
|
||||
if (!gpio_is_valid(max98373->reset_gpio)) {
|
||||
dev_err(dev, "Looking up %s property in node %s failed %d\n",
|
||||
"maxim,reset-gpio", dev->of_node->full_name,
|
||||
max98373->reset_gpio);
|
||||
} else {
|
||||
dev_dbg(dev, "maxim,reset-gpio=%d",
|
||||
max98373->reset_gpio);
|
||||
}
|
||||
} else {
|
||||
dev_dbg(dev, "maxim,reset-gpio=%d",
|
||||
max98373->reset_gpio);
|
||||
/* this makes reset_gpio as invalid */
|
||||
max98373->reset_gpio = -1;
|
||||
}
|
||||
|
||||
if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value))
|
||||
|
@ -1770,6 +1770,9 @@ static int rt5651_detect_headset(struct snd_soc_component *component)
|
||||
|
||||
static bool rt5651_support_button_press(struct rt5651_priv *rt5651)
|
||||
{
|
||||
if (!rt5651->hp_jack)
|
||||
return false;
|
||||
|
||||
/* Button press support only works with internal jack-detection */
|
||||
return (rt5651->hp_jack->status & SND_JACK_MICROPHONE) &&
|
||||
rt5651->gpiod_hp_det == NULL;
|
||||
|
@ -995,6 +995,16 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
|
||||
{
|
||||
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
rt5682->hs_jack = hs_jack;
|
||||
|
||||
if (!hs_jack) {
|
||||
regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2,
|
||||
RT5682_JD1_EN_MASK, RT5682_JD1_DIS);
|
||||
regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL,
|
||||
RT5682_POW_JDH | RT5682_POW_JDL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (rt5682->pdata.jd_src) {
|
||||
case RT5682_JD1:
|
||||
snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_2,
|
||||
@ -1032,8 +1042,6 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component,
|
||||
break;
|
||||
}
|
||||
|
||||
rt5682->hs_jack = hs_jack;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -533,13 +533,10 @@ static SOC_ENUM_SINGLE_DECL(dac_osr,
|
||||
static SOC_ENUM_SINGLE_DECL(adc_osr,
|
||||
WM8994_OVERSAMPLING, 1, osr_text);
|
||||
|
||||
static const struct snd_kcontrol_new wm8994_snd_controls[] = {
|
||||
static const struct snd_kcontrol_new wm8994_common_snd_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
|
||||
WM8994_AIF1_ADC1_RIGHT_VOLUME,
|
||||
1, 119, 0, digital_tlv),
|
||||
SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME,
|
||||
WM8994_AIF1_ADC2_RIGHT_VOLUME,
|
||||
1, 119, 0, digital_tlv),
|
||||
SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME,
|
||||
WM8994_AIF2_ADC_RIGHT_VOLUME,
|
||||
1, 119, 0, digital_tlv),
|
||||
@ -556,8 +553,6 @@ SOC_ENUM("AIF2DACR Source", aif2dacr_src),
|
||||
|
||||
SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME,
|
||||
WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
|
||||
SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
|
||||
WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
|
||||
SOC_DOUBLE_R_TLV("AIF2DAC Volume", WM8994_AIF2_DAC_LEFT_VOLUME,
|
||||
WM8994_AIF2_DAC_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
|
||||
|
||||
@ -565,17 +560,12 @@ SOC_SINGLE_TLV("AIF1 Boost Volume", WM8994_AIF1_CONTROL_2, 10, 3, 0, aif_tlv),
|
||||
SOC_SINGLE_TLV("AIF2 Boost Volume", WM8994_AIF2_CONTROL_2, 10, 3, 0, aif_tlv),
|
||||
|
||||
SOC_SINGLE("AIF1DAC1 EQ Switch", WM8994_AIF1_DAC1_EQ_GAINS_1, 0, 1, 0),
|
||||
SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0),
|
||||
SOC_SINGLE("AIF2 EQ Switch", WM8994_AIF2_EQ_GAINS_1, 0, 1, 0),
|
||||
|
||||
WM8994_DRC_SWITCH("AIF1DAC1 DRC Switch", WM8994_AIF1_DRC1_1, 2),
|
||||
WM8994_DRC_SWITCH("AIF1ADC1L DRC Switch", WM8994_AIF1_DRC1_1, 1),
|
||||
WM8994_DRC_SWITCH("AIF1ADC1R DRC Switch", WM8994_AIF1_DRC1_1, 0),
|
||||
|
||||
WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2),
|
||||
WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1),
|
||||
WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0),
|
||||
|
||||
WM8994_DRC_SWITCH("AIF2DAC DRC Switch", WM8994_AIF2_DRC_1, 2),
|
||||
WM8994_DRC_SWITCH("AIF2ADCL DRC Switch", WM8994_AIF2_DRC_1, 1),
|
||||
WM8994_DRC_SWITCH("AIF2ADCR DRC Switch", WM8994_AIF2_DRC_1, 0),
|
||||
@ -594,9 +584,6 @@ SOC_SINGLE("Sidetone HPF Switch", WM8994_SIDETONE, 6, 1, 0),
|
||||
SOC_ENUM("AIF1ADC1 HPF Mode", aif1adc1_hpf),
|
||||
SOC_DOUBLE("AIF1ADC1 HPF Switch", WM8994_AIF1_ADC1_FILTERS, 12, 11, 1, 0),
|
||||
|
||||
SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf),
|
||||
SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0),
|
||||
|
||||
SOC_ENUM("AIF2ADC HPF Mode", aif2adc_hpf),
|
||||
SOC_DOUBLE("AIF2ADC HPF Switch", WM8994_AIF2_ADC_FILTERS, 12, 11, 1, 0),
|
||||
|
||||
@ -637,6 +624,24 @@ SOC_SINGLE("AIF2DAC 3D Stereo Switch", WM8994_AIF2_DAC_FILTERS_2,
|
||||
8, 1, 0),
|
||||
};
|
||||
|
||||
/* Controls not available on WM1811 */
|
||||
static const struct snd_kcontrol_new wm8994_snd_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("AIF1ADC2 Volume", WM8994_AIF1_ADC2_LEFT_VOLUME,
|
||||
WM8994_AIF1_ADC2_RIGHT_VOLUME,
|
||||
1, 119, 0, digital_tlv),
|
||||
SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
|
||||
WM8994_AIF1_DAC2_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
|
||||
|
||||
SOC_SINGLE("AIF1DAC2 EQ Switch", WM8994_AIF1_DAC2_EQ_GAINS_1, 0, 1, 0),
|
||||
|
||||
WM8994_DRC_SWITCH("AIF1DAC2 DRC Switch", WM8994_AIF1_DRC2_1, 2),
|
||||
WM8994_DRC_SWITCH("AIF1ADC2L DRC Switch", WM8994_AIF1_DRC2_1, 1),
|
||||
WM8994_DRC_SWITCH("AIF1ADC2R DRC Switch", WM8994_AIF1_DRC2_1, 0),
|
||||
|
||||
SOC_ENUM("AIF1ADC2 HPF Mode", aif1adc2_hpf),
|
||||
SOC_DOUBLE("AIF1ADC2 HPF Switch", WM8994_AIF1_ADC2_FILTERS, 12, 11, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new wm8994_eq_controls[] = {
|
||||
SOC_SINGLE_TLV("AIF1DAC1 EQ1 Volume", WM8994_AIF1_DAC1_EQ_GAINS_1, 11, 31, 0,
|
||||
eq_tlv),
|
||||
@ -4385,13 +4390,15 @@ static int wm8994_component_probe(struct snd_soc_component *component)
|
||||
wm8994_handle_pdata(wm8994);
|
||||
|
||||
wm_hubs_add_analogue_controls(component);
|
||||
snd_soc_add_component_controls(component, wm8994_snd_controls,
|
||||
ARRAY_SIZE(wm8994_snd_controls));
|
||||
snd_soc_add_component_controls(component, wm8994_common_snd_controls,
|
||||
ARRAY_SIZE(wm8994_common_snd_controls));
|
||||
snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
|
||||
ARRAY_SIZE(wm8994_dapm_widgets));
|
||||
|
||||
switch (control->type) {
|
||||
case WM8994:
|
||||
snd_soc_add_component_controls(component, wm8994_snd_controls,
|
||||
ARRAY_SIZE(wm8994_snd_controls));
|
||||
snd_soc_dapm_new_controls(dapm, wm8994_specific_dapm_widgets,
|
||||
ARRAY_SIZE(wm8994_specific_dapm_widgets));
|
||||
if (control->revision < 4) {
|
||||
@ -4411,8 +4418,10 @@ static int wm8994_component_probe(struct snd_soc_component *component)
|
||||
}
|
||||
break;
|
||||
case WM8958:
|
||||
snd_soc_add_component_controls(component, wm8994_snd_controls,
|
||||
ARRAY_SIZE(wm8994_snd_controls));
|
||||
snd_soc_add_component_controls(component, wm8958_snd_controls,
|
||||
ARRAY_SIZE(wm8958_snd_controls));
|
||||
ARRAY_SIZE(wm8958_snd_controls));
|
||||
snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
|
||||
ARRAY_SIZE(wm8958_dapm_widgets));
|
||||
if (control->revision < 1) {
|
||||
|
@ -3697,11 +3697,16 @@ static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp)
|
||||
u32 xmalg, addr, magic;
|
||||
int i, ret;
|
||||
|
||||
alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
|
||||
if (!alg_region) {
|
||||
adsp_err(dsp, "No algorithm region found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = wm_adsp_buffer_alloc(dsp);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
|
||||
xmalg = dsp->ops->sys_config_size / sizeof(__be32);
|
||||
|
||||
addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
|
||||
|
@ -308,6 +308,9 @@ static const struct snd_soc_dapm_widget sof_widgets[] = {
|
||||
SND_SOC_DAPM_HP("Headphone Jack", NULL),
|
||||
SND_SOC_DAPM_MIC("Headset Mic", NULL),
|
||||
SND_SOC_DAPM_SPK("Spk", NULL),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget dmic_widgets[] = {
|
||||
SND_SOC_DAPM_MIC("SoC DMIC", NULL),
|
||||
};
|
||||
|
||||
@ -318,10 +321,6 @@ static const struct snd_soc_dapm_route sof_map[] = {
|
||||
|
||||
/* other jacks */
|
||||
{ "IN1P", NULL, "Headset Mic" },
|
||||
|
||||
/* digital mics */
|
||||
{"DMic", NULL, "SoC DMIC"},
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route speaker_map[] = {
|
||||
@ -329,6 +328,11 @@ static const struct snd_soc_dapm_route speaker_map[] = {
|
||||
{ "Spk", NULL, "Speaker" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route dmic_map[] = {
|
||||
/* digital mics */
|
||||
{"DMic", NULL, "SoC DMIC"},
|
||||
};
|
||||
|
||||
static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
@ -342,6 +346,28 @@ static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dmic_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
int ret;
|
||||
|
||||
ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
|
||||
ARRAY_SIZE(dmic_widgets));
|
||||
if (ret) {
|
||||
dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
|
||||
/* Don't need to add routes if widget addition failed */
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
|
||||
ARRAY_SIZE(dmic_map));
|
||||
|
||||
if (ret)
|
||||
dev_err(card->dev, "DMic map addition failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* sof audio machine driver for rt5682 codec */
|
||||
static struct snd_soc_card sof_audio_card_rt5682 = {
|
||||
.name = "sof_rt5682",
|
||||
@ -445,6 +471,7 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
|
||||
links[id].name = "dmic01";
|
||||
links[id].cpus = &cpus[id];
|
||||
links[id].cpus->dai_name = "DMIC01 Pin";
|
||||
links[id].init = dmic_init;
|
||||
if (dmic_be_num > 1) {
|
||||
/* set up 2 BE links at most */
|
||||
links[id + 1].name = "dmic16k";
|
||||
@ -621,8 +648,24 @@ static int sof_audio_probe(struct platform_device *pdev)
|
||||
&sof_audio_card_rt5682);
|
||||
}
|
||||
|
||||
static int sof_rt5682_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
struct snd_soc_component *component = NULL;
|
||||
|
||||
for_each_card_components(card, component) {
|
||||
if (!strcmp(component->name, rt5682_component[0].name)) {
|
||||
snd_soc_component_set_jack(component, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sof_audio = {
|
||||
.probe = sof_audio_probe,
|
||||
.remove = sof_rt5682_remove,
|
||||
.driver = {
|
||||
.name = "sof_rt5682",
|
||||
.pm = &snd_soc_pm_ops,
|
||||
|
@ -5,6 +5,7 @@
|
||||
// Author: Claude <claude@insginal.co.kr>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
@ -74,6 +75,17 @@ static struct snd_soc_card arndale_rt5631 = {
|
||||
.num_links = ARRAY_SIZE(arndale_rt5631_dai),
|
||||
};
|
||||
|
||||
static void arndale_put_of_nodes(struct snd_soc_card *card)
|
||||
{
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
int i;
|
||||
|
||||
for_each_card_prelinks(card, i, dai_link) {
|
||||
of_node_put(dai_link->cpus->of_node);
|
||||
of_node_put(dai_link->codecs->of_node);
|
||||
}
|
||||
}
|
||||
|
||||
static int arndale_audio_probe(struct platform_device *pdev)
|
||||
{
|
||||
int n, ret;
|
||||
@ -103,18 +115,31 @@ static int arndale_audio_probe(struct platform_device *pdev)
|
||||
if (!arndale_rt5631_dai[0].codecs->of_node) {
|
||||
dev_err(&pdev->dev,
|
||||
"Property 'samsung,audio-codec' missing or invalid\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err_put_of_nodes;
|
||||
}
|
||||
}
|
||||
|
||||
ret = devm_snd_soc_register_card(card->dev, card);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);
|
||||
goto err_put_of_nodes;
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
|
||||
|
||||
err_put_of_nodes:
|
||||
arndale_put_of_nodes(card);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int arndale_audio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||
|
||||
arndale_put_of_nodes(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id samsung_arndale_rt5631_of_match[] __maybe_unused = {
|
||||
{ .compatible = "samsung,arndale-rt5631", },
|
||||
{ .compatible = "samsung,arndale-alc5631", },
|
||||
@ -129,6 +154,7 @@ static struct platform_driver arndale_audio_driver = {
|
||||
.of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match),
|
||||
},
|
||||
.probe = arndale_audio_probe,
|
||||
.remove = arndale_audio_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(arndale_audio_driver);
|
||||
|
@ -1070,7 +1070,7 @@ static int soc_pcm_trigger_start(struct snd_pcm_substream *substream, int cmd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_soc_dai_trigger(cpu_dai, substream, cmd);
|
||||
ret = snd_soc_dai_trigger(cpu_dai, substream, cmd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -1155,7 +1155,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
|
||||
return ret;
|
||||
}
|
||||
|
||||
snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd);
|
||||
ret = snd_soc_dai_bespoke_trigger(cpu_dai, substream, cmd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1582,7 +1582,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg,
|
||||
|
||||
/* map user to kernel widget ID */
|
||||
template.id = get_widget_id(le32_to_cpu(w->id));
|
||||
if (template.id < 0)
|
||||
if ((int)template.id < 0)
|
||||
return template.id;
|
||||
|
||||
/* strings are allocated here, but used and freed by the widget */
|
||||
|
@ -273,6 +273,16 @@ config SND_SOC_SOF_HDA_AUDIO_CODEC
|
||||
Say Y if you want to enable HDAudio codecs with SOF.
|
||||
If unsure select "N".
|
||||
|
||||
config SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1
|
||||
bool "SOF enable DMI Link L1"
|
||||
help
|
||||
This option enables DMI L1 for both playback and capture
|
||||
and disables known workarounds for specific HDaudio platforms.
|
||||
Only use to look into power optimizations on platforms not
|
||||
affected by DMI L1 issues. This option is not recommended.
|
||||
Say Y if you want to enable DMI Link L1
|
||||
If unsure, select "N".
|
||||
|
||||
endif ## SND_SOC_SOF_HDA_COMMON
|
||||
|
||||
config SND_SOC_SOF_HDA_LINK_BASELINE
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define MBOX_SIZE 0x1000
|
||||
#define MBOX_DUMP_SIZE 0x30
|
||||
#define EXCEPT_OFFSET 0x800
|
||||
#define EXCEPT_MAX_HDR_SIZE 0x400
|
||||
|
||||
/* DSP peripherals */
|
||||
#define DMAC0_OFFSET 0xFE000
|
||||
@ -228,6 +229,11 @@ static void bdw_get_registers(struct snd_sof_dev *sdev,
|
||||
/* note: variable AR register array is not read */
|
||||
|
||||
/* then get panic info */
|
||||
if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
|
||||
dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
|
||||
xoops->arch_hdr.totalsize);
|
||||
return;
|
||||
}
|
||||
offset += xoops->arch_hdr.totalsize;
|
||||
sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
|
||||
|
||||
@ -471,6 +477,7 @@ static int bdw_probe(struct snd_sof_dev *sdev)
|
||||
/* TODO: add offsets */
|
||||
sdev->mmio_bar = BDW_DSP_BAR;
|
||||
sdev->mailbox_bar = BDW_DSP_BAR;
|
||||
sdev->dsp_oops_offset = MBOX_OFFSET;
|
||||
|
||||
/* PCI base */
|
||||
mmio = platform_get_resource(pdev, IORESOURCE_MEM,
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define MBOX_OFFSET 0x144000
|
||||
#define MBOX_SIZE 0x1000
|
||||
#define EXCEPT_OFFSET 0x800
|
||||
#define EXCEPT_MAX_HDR_SIZE 0x400
|
||||
|
||||
/* DSP peripherals */
|
||||
#define DMAC0_OFFSET 0x098000
|
||||
@ -126,6 +127,11 @@ static void byt_get_registers(struct snd_sof_dev *sdev,
|
||||
/* note: variable AR register array is not read */
|
||||
|
||||
/* then get panic info */
|
||||
if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
|
||||
dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
|
||||
xoops->arch_hdr.totalsize);
|
||||
return;
|
||||
}
|
||||
offset += xoops->arch_hdr.totalsize;
|
||||
sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
|
||||
|
||||
|
@ -139,20 +139,16 @@ void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable)
|
||||
*/
|
||||
int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
#endif
|
||||
u32 val;
|
||||
|
||||
/* enable/disable audio dsp clock gating */
|
||||
val = enable ? PCI_CGCTL_ADSPDCGE : 0;
|
||||
snd_sof_pci_update_bits(sdev, PCI_CGCTL, PCI_CGCTL_ADSPDCGE, val);
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
|
||||
/* enable/disable L1 support */
|
||||
val = enable ? SOF_HDA_VS_EM2_L1SEN : 0;
|
||||
snd_hdac_chip_updatel(bus, VS_EM2, SOF_HDA_VS_EM2_L1SEN, val);
|
||||
#endif
|
||||
/* enable/disable DMI Link L1 support */
|
||||
val = enable ? HDA_VS_INTEL_EM2_L1SEN : 0;
|
||||
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
|
||||
HDA_VS_INTEL_EM2_L1SEN, val);
|
||||
|
||||
/* enable/disable audio dsp power gating */
|
||||
val = enable ? 0 : PCI_PGCTL_ADSPPGD;
|
||||
|
@ -44,6 +44,7 @@ static int cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
|
||||
return -ENODEV;
|
||||
}
|
||||
hstream = &dsp_stream->hstream;
|
||||
hstream->substream = NULL;
|
||||
|
||||
/* allocate DMA buffer */
|
||||
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab);
|
||||
|
@ -185,6 +185,17 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
|
||||
direction == SNDRV_PCM_STREAM_PLAYBACK ?
|
||||
"playback" : "capture");
|
||||
|
||||
/*
|
||||
* Disable DMI Link L1 entry when capture stream is opened.
|
||||
* Workaround to address a known issue with host DMA that results
|
||||
* in xruns during pause/release in capture scenarios.
|
||||
*/
|
||||
if (!IS_ENABLED(SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
|
||||
if (stream && direction == SNDRV_PCM_STREAM_CAPTURE)
|
||||
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
|
||||
HDA_VS_INTEL_EM2,
|
||||
HDA_VS_INTEL_EM2_L1SEN, 0);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -193,23 +204,43 @@ int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
|
||||
{
|
||||
struct hdac_bus *bus = sof_to_bus(sdev);
|
||||
struct hdac_stream *s;
|
||||
bool active_capture_stream = false;
|
||||
bool found = false;
|
||||
|
||||
spin_lock_irq(&bus->reg_lock);
|
||||
|
||||
/* find used stream */
|
||||
/*
|
||||
* close stream matching the stream tag
|
||||
* and check if there are any open capture streams.
|
||||
*/
|
||||
list_for_each_entry(s, &bus->stream_list, list) {
|
||||
if (s->direction == direction &&
|
||||
s->opened && s->stream_tag == stream_tag) {
|
||||
if (!s->opened)
|
||||
continue;
|
||||
|
||||
if (s->direction == direction && s->stream_tag == stream_tag) {
|
||||
s->opened = false;
|
||||
spin_unlock_irq(&bus->reg_lock);
|
||||
return 0;
|
||||
found = true;
|
||||
} else if (s->direction == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
active_capture_stream = true;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(&bus->reg_lock);
|
||||
|
||||
dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
|
||||
return -ENODEV;
|
||||
/* Enable DMI L1 entry if there are no capture streams open */
|
||||
if (!IS_ENABLED(SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
|
||||
if (!active_capture_stream)
|
||||
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
|
||||
HDA_VS_INTEL_EM2,
|
||||
HDA_VS_INTEL_EM2_L1SEN,
|
||||
HDA_VS_INTEL_EM2_L1SEN);
|
||||
|
||||
if (!found) {
|
||||
dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
|
||||
|
@ -35,6 +35,8 @@
|
||||
#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
|
||||
#define IS_CNL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9dc8)
|
||||
|
||||
#define EXCEPT_MAX_HDR_SIZE 0x400
|
||||
|
||||
/*
|
||||
* Debug
|
||||
*/
|
||||
@ -131,6 +133,11 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev,
|
||||
/* note: variable AR register array is not read */
|
||||
|
||||
/* then get panic info */
|
||||
if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
|
||||
dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
|
||||
xoops->arch_hdr.totalsize);
|
||||
return;
|
||||
}
|
||||
offset += xoops->arch_hdr.totalsize;
|
||||
sof_block_read(sdev, sdev->mmio_bar, offset,
|
||||
panic_info, sizeof(*panic_info));
|
||||
|
@ -39,7 +39,6 @@
|
||||
#define SOF_HDA_WAKESTS 0x0E
|
||||
#define SOF_HDA_WAKESTS_INT_MASK ((1 << 8) - 1)
|
||||
#define SOF_HDA_RIRBSTS 0x5d
|
||||
#define SOF_HDA_VS_EM2_L1SEN BIT(13)
|
||||
|
||||
/* SOF_HDA_GCTL register bist */
|
||||
#define SOF_HDA_GCTL_RESET BIT(0)
|
||||
@ -228,6 +227,10 @@
|
||||
#define HDA_DSP_REG_HIPCIE (HDA_DSP_IPC_BASE + 0x0C)
|
||||
#define HDA_DSP_REG_HIPCCTL (HDA_DSP_IPC_BASE + 0x10)
|
||||
|
||||
/* Intel Vendor Specific Registers */
|
||||
#define HDA_VS_INTEL_EM2 0x1030
|
||||
#define HDA_VS_INTEL_EM2_L1SEN BIT(13)
|
||||
|
||||
/* HIPCI */
|
||||
#define HDA_DSP_REG_HIPCI_BUSY BIT(31)
|
||||
#define HDA_DSP_REG_HIPCI_MSG_MASK 0x7FFFFFFF
|
||||
|
@ -546,10 +546,10 @@ int snd_sof_run_firmware(struct snd_sof_dev *sdev)
|
||||
msecs_to_jiffies(sdev->boot_timeout));
|
||||
if (ret == 0) {
|
||||
dev_err(sdev->dev, "error: firmware boot failure\n");
|
||||
/* after this point FW_READY msg should be ignored */
|
||||
sdev->boot_complete = true;
|
||||
snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX |
|
||||
SOF_DBG_TEXT | SOF_DBG_PCI);
|
||||
/* after this point FW_READY msg should be ignored */
|
||||
sdev->boot_complete = true;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
snd_soc_rtdcom_lookup(rtd, DRV_NAME);
|
||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
|
||||
struct snd_sof_pcm *spcm;
|
||||
int ret;
|
||||
int ret, err = 0;
|
||||
|
||||
/* nothing to do for BE */
|
||||
if (rtd->dai_link->no_pcm)
|
||||
@ -254,26 +254,26 @@ static int sof_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
if (!spcm)
|
||||
return -EINVAL;
|
||||
|
||||
if (!spcm->prepared[substream->stream])
|
||||
return 0;
|
||||
|
||||
dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id,
|
||||
substream->stream);
|
||||
|
||||
ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
|
||||
if (spcm->prepared[substream->stream]) {
|
||||
ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
|
||||
if (ret < 0)
|
||||
err = ret;
|
||||
}
|
||||
|
||||
snd_pcm_lib_free_pages(substream);
|
||||
|
||||
cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = snd_sof_pcm_platform_hw_free(sdev, substream);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(sdev->dev, "error: platform hw free failed\n");
|
||||
err = ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sof_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
@ -323,6 +323,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
struct sof_ipc_stream stream;
|
||||
struct sof_ipc_reply reply;
|
||||
bool reset_hw_params = false;
|
||||
bool ipc_first = false;
|
||||
int ret;
|
||||
|
||||
/* nothing to do for BE */
|
||||
@ -343,6 +344,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE;
|
||||
ipc_first = true;
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE;
|
||||
@ -363,6 +365,7 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
|
||||
ipc_first = true;
|
||||
reset_hw_params = true;
|
||||
break;
|
||||
default:
|
||||
@ -370,12 +373,22 @@ static int sof_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
|
||||
/*
|
||||
* DMA and IPC sequence is different for start and stop. Need to send
|
||||
* STOP IPC before stop DMA
|
||||
*/
|
||||
if (!ipc_first)
|
||||
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
|
||||
|
||||
/* send IPC to the DSP */
|
||||
ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream,
|
||||
sizeof(stream), &reply, sizeof(reply));
|
||||
|
||||
/* need to STOP DMA even if STOP IPC failed */
|
||||
if (ipc_first)
|
||||
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
|
||||
|
||||
/* free PCM if reset_hw_params is set and the STOP IPC is successful */
|
||||
if (!ret && reset_hw_params)
|
||||
ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
|
||||
|
||||
|
@ -920,7 +920,9 @@ static void sof_parse_word_tokens(struct snd_soc_component *scomp,
|
||||
for (j = 0; j < count; j++) {
|
||||
/* match token type */
|
||||
if (!(tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_WORD ||
|
||||
tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT))
|
||||
tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_SHORT ||
|
||||
tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BYTE ||
|
||||
tokens[j].type == SND_SOC_TPLG_TUPLE_TYPE_BOOL))
|
||||
continue;
|
||||
|
||||
/* match token id */
|
||||
|
Loading…
Reference in New Issue
Block a user