Commit 2acf6ce2 authored by Mark Brown's avatar Mark Brown

Merge branch 'for-5.5' of...

Merge branch 'for-5.5' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-5.6
parents 2aae447a 4e64ba3f
...@@ -1141,6 +1141,7 @@ struct snd_soc_pcm_runtime { ...@@ -1141,6 +1141,7 @@ struct snd_soc_pcm_runtime {
unsigned int num_codecs; unsigned int num_codecs;
struct delayed_work delayed_work; struct delayed_work delayed_work;
void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_dpcm_root; struct dentry *debugfs_dpcm_root;
#endif #endif
......
...@@ -96,14 +96,19 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) ...@@ -96,14 +96,19 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
return 0; return 0;
} }
static int da7219_clk_enable(struct snd_pcm_substream *substream, static int da7219_clk_enable(struct snd_pcm_substream *substream)
int wclk_rate, int bclk_rate)
{ {
int ret = 0; int ret = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
clk_set_rate(da7219_dai_wclk, wclk_rate); /*
clk_set_rate(da7219_dai_bclk, bclk_rate); * Set wclk to 48000 because the rate constraint of this driver is
* 48000. ADAU7002 spec: "The ADAU7002 requires a BCLK rate that is
* minimum of 64x the LRCLK sample rate." DA7219 is the only clk
* source so for all codecs we have to limit bclk to 64X lrclk.
*/
clk_set_rate(da7219_dai_wclk, 48000);
clk_set_rate(da7219_dai_bclk, 48000 * 64);
ret = clk_prepare_enable(da7219_dai_bclk); ret = clk_prepare_enable(da7219_dai_bclk);
if (ret < 0) { if (ret < 0) {
dev_err(rtd->dev, "can't enable master clock %d\n", ret); dev_err(rtd->dev, "can't enable master clock %d\n", ret);
...@@ -156,7 +161,7 @@ static int cz_da7219_play_startup(struct snd_pcm_substream *substream) ...@@ -156,7 +161,7 @@ static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
&constraints_rates); &constraints_rates);
machine->play_i2s_instance = I2S_SP_INSTANCE; machine->play_i2s_instance = I2S_SP_INSTANCE;
return 0; return da7219_clk_enable(substream);
} }
static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
...@@ -178,7 +183,7 @@ static int cz_da7219_cap_startup(struct snd_pcm_substream *substream) ...@@ -178,7 +183,7 @@ static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
machine->cap_i2s_instance = I2S_SP_INSTANCE; machine->cap_i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL1; machine->capture_channel = CAP_CHANNEL1;
return 0; return da7219_clk_enable(substream);
} }
static int cz_max_startup(struct snd_pcm_substream *substream) static int cz_max_startup(struct snd_pcm_substream *substream)
...@@ -199,7 +204,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream) ...@@ -199,7 +204,7 @@ static int cz_max_startup(struct snd_pcm_substream *substream)
&constraints_rates); &constraints_rates);
machine->play_i2s_instance = I2S_BT_INSTANCE; machine->play_i2s_instance = I2S_BT_INSTANCE;
return 0; return da7219_clk_enable(substream);
} }
static int cz_dmic0_startup(struct snd_pcm_substream *substream) static int cz_dmic0_startup(struct snd_pcm_substream *substream)
...@@ -220,7 +225,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream) ...@@ -220,7 +225,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream *substream)
&constraints_rates); &constraints_rates);
machine->cap_i2s_instance = I2S_BT_INSTANCE; machine->cap_i2s_instance = I2S_BT_INSTANCE;
return 0; return da7219_clk_enable(substream);
} }
static int cz_dmic1_startup(struct snd_pcm_substream *substream) static int cz_dmic1_startup(struct snd_pcm_substream *substream)
...@@ -242,25 +247,7 @@ static int cz_dmic1_startup(struct snd_pcm_substream *substream) ...@@ -242,25 +247,7 @@ static int cz_dmic1_startup(struct snd_pcm_substream *substream)
machine->cap_i2s_instance = I2S_SP_INSTANCE; machine->cap_i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0; machine->capture_channel = CAP_CHANNEL0;
return 0; return da7219_clk_enable(substream);
}
static int cz_da7219_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
int wclk, bclk;
wclk = params_rate(params);
bclk = wclk * params_channels(params) *
snd_pcm_format_width(params_format(params));
/* ADAU7002 spec: "The ADAU7002 requires a BCLK rate
* that is minimum of 64x the LRCLK sample rate."
* DA7219 is the only clk source so for all codecs
* we have to limit bclk to 64X lrclk.
*/
if (bclk < (wclk * 64))
bclk = wclk * 64;
return da7219_clk_enable(substream, wclk, bclk);
} }
static void cz_da7219_shutdown(struct snd_pcm_substream *substream) static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
...@@ -271,31 +258,26 @@ static void cz_da7219_shutdown(struct snd_pcm_substream *substream) ...@@ -271,31 +258,26 @@ static void cz_da7219_shutdown(struct snd_pcm_substream *substream)
static const struct snd_soc_ops cz_da7219_play_ops = { static const struct snd_soc_ops cz_da7219_play_ops = {
.startup = cz_da7219_play_startup, .startup = cz_da7219_play_startup,
.shutdown = cz_da7219_shutdown, .shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
}; };
static const struct snd_soc_ops cz_da7219_cap_ops = { static const struct snd_soc_ops cz_da7219_cap_ops = {
.startup = cz_da7219_cap_startup, .startup = cz_da7219_cap_startup,
.shutdown = cz_da7219_shutdown, .shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
}; };
static const struct snd_soc_ops cz_max_play_ops = { static const struct snd_soc_ops cz_max_play_ops = {
.startup = cz_max_startup, .startup = cz_max_startup,
.shutdown = cz_da7219_shutdown, .shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
}; };
static const struct snd_soc_ops cz_dmic0_cap_ops = { static const struct snd_soc_ops cz_dmic0_cap_ops = {
.startup = cz_dmic0_startup, .startup = cz_dmic0_startup,
.shutdown = cz_da7219_shutdown, .shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
}; };
static const struct snd_soc_ops cz_dmic1_cap_ops = { static const struct snd_soc_ops cz_dmic1_cap_ops = {
.startup = cz_dmic1_startup, .startup = cz_dmic1_startup,
.shutdown = cz_da7219_shutdown, .shutdown = cz_da7219_shutdown,
.hw_params = cz_da7219_params,
}; };
SND_SOC_DAILINK_DEF(designware1, SND_SOC_DAILINK_DEF(designware1,
......
...@@ -2294,28 +2294,42 @@ static void max98090_pll_det_disable_work(struct work_struct *work) ...@@ -2294,28 +2294,42 @@ static void max98090_pll_det_disable_work(struct work_struct *work)
M98090_IULK_MASK, 0); M98090_IULK_MASK, 0);
} }
static void max98090_pll_work(struct work_struct *work) static void max98090_pll_work(struct max98090_priv *max98090)
{ {
struct max98090_priv *max98090 =
container_of(work, struct max98090_priv, pll_work);
struct snd_soc_component *component = max98090->component; struct snd_soc_component *component = max98090->component;
unsigned int pll;
int i;
if (!snd_soc_component_is_active(component)) if (!snd_soc_component_is_active(component))
return; return;
dev_info_ratelimited(component->dev, "PLL unlocked\n"); dev_info_ratelimited(component->dev, "PLL unlocked\n");
/*
* As the datasheet suggested, the maximum PLL lock time should be
* 7 msec. The workaround resets the codec softly by toggling SHDN
* off and on if PLL failed to lock for 10 msec. Notably, there is
* no suggested hold time for SHDN off.
*/
/* Toggle shutdown OFF then ON */ /* Toggle shutdown OFF then ON */
mutex_lock(&component->card->dapm_mutex); mutex_lock(&component->card->dapm_mutex);
snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN, snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK, 0); M98090_SHDNN_MASK, 0);
msleep(10);
snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN, snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
M98090_SHDNN_MASK, M98090_SHDNN_MASK); M98090_SHDNN_MASK, M98090_SHDNN_MASK);
mutex_unlock(&component->card->dapm_mutex); mutex_unlock(&component->card->dapm_mutex);
for (i = 0; i < 10; ++i) {
/* Give PLL time to lock */ /* Give PLL time to lock */
msleep(10); usleep_range(1000, 1200);
/* Check lock status */
pll = snd_soc_component_read32(
component, M98090_REG_DEVICE_STATUS);
if (!(pll & M98090_ULK_MASK))
break;
}
} }
static void max98090_jack_work(struct work_struct *work) static void max98090_jack_work(struct work_struct *work)
...@@ -2452,7 +2466,7 @@ static irqreturn_t max98090_interrupt(int irq, void *data) ...@@ -2452,7 +2466,7 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
if (active & M98090_ULK_MASK) { if (active & M98090_ULK_MASK) {
dev_dbg(component->dev, "M98090_ULK_MASK\n"); dev_dbg(component->dev, "M98090_ULK_MASK\n");
schedule_work(&max98090->pll_work); max98090_pll_work(max98090);
} }
if (active & M98090_JDET_MASK) { if (active & M98090_JDET_MASK) {
...@@ -2615,7 +2629,6 @@ static int max98090_probe(struct snd_soc_component *component) ...@@ -2615,7 +2629,6 @@ static int max98090_probe(struct snd_soc_component *component)
max98090_pll_det_enable_work); max98090_pll_det_enable_work);
INIT_WORK(&max98090->pll_det_disable_work, INIT_WORK(&max98090->pll_det_disable_work,
max98090_pll_det_disable_work); max98090_pll_det_disable_work);
INIT_WORK(&max98090->pll_work, max98090_pll_work);
/* Enable jack detection */ /* Enable jack detection */
snd_soc_component_write(component, M98090_REG_JACK_DETECT, snd_soc_component_write(component, M98090_REG_JACK_DETECT,
...@@ -2678,7 +2691,6 @@ static void max98090_remove(struct snd_soc_component *component) ...@@ -2678,7 +2691,6 @@ static void max98090_remove(struct snd_soc_component *component)
cancel_delayed_work_sync(&max98090->jack_work); cancel_delayed_work_sync(&max98090->jack_work);
cancel_delayed_work_sync(&max98090->pll_det_enable_work); cancel_delayed_work_sync(&max98090->pll_det_enable_work);
cancel_work_sync(&max98090->pll_det_disable_work); cancel_work_sync(&max98090->pll_det_disable_work);
cancel_work_sync(&max98090->pll_work);
max98090->component = NULL; max98090->component = NULL;
} }
......
...@@ -1530,7 +1530,6 @@ struct max98090_priv { ...@@ -1530,7 +1530,6 @@ struct max98090_priv {
struct delayed_work jack_work; struct delayed_work jack_work;
struct delayed_work pll_det_enable_work; struct delayed_work pll_det_enable_work;
struct work_struct pll_det_disable_work; struct work_struct pll_det_disable_work;
struct work_struct pll_work;
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
unsigned int dai_fmt; unsigned int dai_fmt;
int tdm_slots; int tdm_slots;
......
...@@ -9,9 +9,25 @@ ...@@ -9,9 +9,25 @@
#ifndef __RT5677_SPI_H__ #ifndef __RT5677_SPI_H__
#define __RT5677_SPI_H__ #define __RT5677_SPI_H__
#if IS_ENABLED(CONFIG_SND_SOC_RT5677_SPI)
int rt5677_spi_read(u32 addr, void *rxbuf, size_t len); int rt5677_spi_read(u32 addr, void *rxbuf, size_t len);
int rt5677_spi_write(u32 addr, const void *txbuf, size_t len); int rt5677_spi_write(u32 addr, const void *txbuf, size_t len);
int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw); int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw);
void rt5677_spi_hotword_detected(void); void rt5677_spi_hotword_detected(void);
#else
static inline int rt5677_spi_read(u32 addr, void *rxbuf, size_t len)
{
return -EINVAL;
}
static inline int rt5677_spi_write(u32 addr, const void *txbuf, size_t len)
{
return -EINVAL;
}
static inline int rt5677_spi_write_firmware(u32 addr, const struct firmware *fw)
{
return -EINVAL;
}
static inline void rt5677_spi_hotword_detected(void){}
#endif
#endif /* __RT5677_SPI_H__ */ #endif /* __RT5677_SPI_H__ */
...@@ -73,6 +73,7 @@ struct rt5682_priv { ...@@ -73,6 +73,7 @@ struct rt5682_priv {
static const struct reg_sequence patch_list[] = { static const struct reg_sequence patch_list[] = {
{RT5682_HP_IMP_SENS_CTRL_19, 0x1000}, {RT5682_HP_IMP_SENS_CTRL_19, 0x1000},
{RT5682_DAC_ADC_DIG_VOL1, 0xa020}, {RT5682_DAC_ADC_DIG_VOL1, 0xa020},
{RT5682_I2C_CTRL, 0x000f},
}; };
static const struct reg_default rt5682_reg[] = { static const struct reg_default rt5682_reg[] = {
...@@ -2474,6 +2475,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682) ...@@ -2474,6 +2475,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
mutex_lock(&rt5682->calibrate_mutex); mutex_lock(&rt5682->calibrate_mutex);
rt5682_reset(rt5682->regmap); rt5682_reset(rt5682->regmap);
regmap_write(rt5682->regmap, RT5682_I2C_CTRL, 0x000f);
regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xa2af); regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xa2af);
usleep_range(15000, 20000); usleep_range(15000, 20000);
regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xf2af); regmap_write(rt5682->regmap, RT5682_PWR_ANLG_1, 0xf2af);
......
...@@ -1806,6 +1806,12 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id, ...@@ -1806,6 +1806,12 @@ static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id,
switch (clk_id) { switch (clk_id) {
case WM8904_CLK_AUTO: case WM8904_CLK_AUTO:
/* We don't have any rate constraints, so just ignore the
* request to disable constraining.
*/
if (!freq)
return 0;
mclk_freq = clk_get_rate(priv->mclk); mclk_freq = clk_get_rate(priv->mclk);
/* enable FLL if a different sysclk is desired */ /* enable FLL if a different sysclk is desired */
if (mclk_freq != freq) { if (mclk_freq != freq) {
......
...@@ -371,6 +371,7 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, ...@@ -371,6 +371,7 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
do { do {
struct asoc_simple_data adata; struct asoc_simple_data adata;
struct device_node *codec; struct device_node *codec;
struct device_node *plat;
struct device_node *np; struct device_node *np;
int num = of_get_child_count(node); int num = of_get_child_count(node);
...@@ -381,6 +382,9 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, ...@@ -381,6 +382,9 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
ret = -ENODEV; ret = -ENODEV;
goto error; goto error;
} }
/* get platform */
plat = of_get_child_by_name(node, is_top ?
PREFIX "plat" : "plat");
/* get convert-xxx property */ /* get convert-xxx property */
memset(&adata, 0, sizeof(adata)); memset(&adata, 0, sizeof(adata));
...@@ -389,6 +393,8 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, ...@@ -389,6 +393,8 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
/* loop for all CPU/Codec node */ /* loop for all CPU/Codec node */
for_each_child_of_node(node, np) { for_each_child_of_node(node, np) {
if (plat == np)
continue;
/* /*
* It is DPCM * It is DPCM
* if it has many CPUs, * if it has many CPUs,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
......
...@@ -707,13 +707,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { ...@@ -707,13 +707,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{ {
/* Teclast X89 */
.matches = { .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
DMI_MATCH(DMI_BOARD_NAME, "tPAD"), DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
}, },
.driver_data = (void *)(BYT_RT5640_IN3_MAP | .driver_data = (void *)(BYT_RT5640_IN3_MAP |
BYT_RT5640_MCLK_EN | BYT_RT5640_JD_SRC_JD1_IN4P |
BYT_RT5640_SSP0_AIF1), BYT_RT5640_OVCD_TH_2000UA |
BYT_RT5640_OVCD_SF_1P0 |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
}, },
{ /* Toshiba Satellite Click Mini L9W-B */ { /* Toshiba Satellite Click Mini L9W-B */
.matches = { .matches = {
......
...@@ -9,45 +9,52 @@ ...@@ -9,45 +9,52 @@
#include <sound/soc-acpi.h> #include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h> #include <sound/soc-acpi-intel-match.h>
static struct snd_soc_acpi_codecs cml_codecs = { static struct snd_soc_acpi_codecs rt1011_spk_codecs = {
.num_codecs = 1, .num_codecs = 1,
.codecs = {"10EC5682"} .codecs = {"10EC1011"}
}; };
static struct snd_soc_acpi_codecs cml_spk_codecs = { static struct snd_soc_acpi_codecs max98357a_spk_codecs = {
.num_codecs = 1, .num_codecs = 1,
.codecs = {"MX98357A"} .codecs = {"MX98357A"}
}; };
/*
* The order of the three entries with .id = "10EC5682" matters
* here, because DSDT tables expose an ACPI HID for the MAX98357A
* speaker amplifier which is not populated on the board.
*/
struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
{ {
.id = "DLGS7219", .id = "10EC5682",
.drv_name = "cml_da7219_max98357a", .drv_name = "cml_rt1011_rt5682",
.quirk_data = &cml_spk_codecs, .machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &rt1011_spk_codecs,
.sof_fw_filename = "sof-cml.ri", .sof_fw_filename = "sof-cml.ri",
.sof_tplg_filename = "sof-cml-da7219-max98357a.tplg", .sof_tplg_filename = "sof-cml-rt1011-rt5682.tplg",
}, },
{ {
.id = "MX98357A", .id = "10EC5682",
.drv_name = "sof_rt5682", .drv_name = "sof_rt5682",
.quirk_data = &cml_codecs, .machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &max98357a_spk_codecs,
.sof_fw_filename = "sof-cml.ri", .sof_fw_filename = "sof-cml.ri",
.sof_tplg_filename = "sof-cml-rt5682-max98357a.tplg", .sof_tplg_filename = "sof-cml-rt5682-max98357a.tplg",
}, },
{
.id = "10EC1011",
.drv_name = "cml_rt1011_rt5682",
.quirk_data = &cml_codecs,
.sof_fw_filename = "sof-cml.ri",
.sof_tplg_filename = "sof-cml-rt1011-rt5682.tplg",
},
{ {
.id = "10EC5682", .id = "10EC5682",
.drv_name = "sof_rt5682", .drv_name = "sof_rt5682",
.sof_fw_filename = "sof-cml.ri", .sof_fw_filename = "sof-cml.ri",
.sof_tplg_filename = "sof-cml-rt5682.tplg", .sof_tplg_filename = "sof-cml-rt5682.tplg",
}, },
{
.id = "DLGS7219",
.drv_name = "cml_da7219_max98357a",
.machine_quirk = snd_soc_acpi_codec_list,
.quirk_data = &max98357a_spk_codecs,
.sof_fw_filename = "sof-cml.ri",
.sof_tplg_filename = "sof-cml-da7219-max98357a.tplg",
},
{}, {},
}; };
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines); EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines);
......
...@@ -214,10 +214,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) ...@@ -214,10 +214,8 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
* This is to ensure there are no pops or clicks in between any music tracks * This is to ensure there are no pops or clicks in between any music tracks
* due to DAPM power cycling. * due to DAPM power cycling.
*/ */
static void close_delayed_work(struct work_struct *work) static void close_delayed_work(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_pcm_runtime *rtd =
container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *codec_dai = rtd->codec_dai;
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
...@@ -929,7 +927,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) ...@@ -929,7 +927,7 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
} }
/* DAPM dai link stream work */ /* DAPM dai link stream work */
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); rtd->close_delayed_work_func = close_delayed_work;
rtd->compr = compr; rtd->compr = compr;
compr->private_data = rtd; compr->private_data = rtd;
......
...@@ -419,6 +419,7 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd) ...@@ -419,6 +419,7 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd)
list_del(&rtd->list); list_del(&rtd->list);
if (delayed_work_pending(&rtd->delayed_work))
flush_delayed_work(&rtd->delayed_work); flush_delayed_work(&rtd->delayed_work);
snd_soc_pcm_component_free(rtd); snd_soc_pcm_component_free(rtd);
...@@ -435,6 +436,15 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd) ...@@ -435,6 +436,15 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd)
device_unregister(rtd->dev); device_unregister(rtd->dev);
} }
static void close_delayed_work(struct work_struct *work) {
struct snd_soc_pcm_runtime *rtd =
container_of(work, struct snd_soc_pcm_runtime,
delayed_work.work);
if (rtd->close_delayed_work_func)
rtd->close_delayed_work_func(rtd);
}
static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{ {
...@@ -470,6 +480,7 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( ...@@ -470,6 +480,7 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
rtd->dev = dev; rtd->dev = dev;
dev_set_drvdata(dev, rtd); dev_set_drvdata(dev, rtd);
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
/* /*
* for rtd->codec_dais * for rtd->codec_dais
......
...@@ -637,10 +637,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) ...@@ -637,10 +637,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
* This is to ensure there are no pops or clicks in between any music tracks * This is to ensure there are no pops or clicks in between any music tracks
* due to DAPM power cycling. * due to DAPM power cycling.
*/ */
static void close_delayed_work(struct work_struct *work) static void close_delayed_work(struct snd_soc_pcm_runtime *rtd)
{ {
struct snd_soc_pcm_runtime *rtd =
container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
struct snd_soc_dai *codec_dai = rtd->codec_dais[0]; struct snd_soc_dai *codec_dai = rtd->codec_dais[0];
mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
...@@ -660,7 +658,7 @@ static void close_delayed_work(struct work_struct *work) ...@@ -660,7 +658,7 @@ static void close_delayed_work(struct work_struct *work)
mutex_unlock(&rtd->card->pcm_mutex); mutex_unlock(&rtd->card->pcm_mutex);
} }
static void codec2codec_close_delayed_work(struct work_struct *work) static void codec2codec_close_delayed_work(struct snd_soc_pcm_runtime *rtd)
{ {
/* /*
* Currently nothing to do for c2c links * Currently nothing to do for c2c links
...@@ -2974,10 +2972,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) ...@@ -2974,10 +2972,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
/* DAPM dai link stream work */ /* DAPM dai link stream work */
if (rtd->dai_link->params) if (rtd->dai_link->params)
INIT_DELAYED_WORK(&rtd->delayed_work, rtd->close_delayed_work_func = codec2codec_close_delayed_work;
codec2codec_close_delayed_work);
else else
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); rtd->close_delayed_work_func = close_delayed_work;
pcm->nonatomic = rtd->dai_link->nonatomic; pcm->nonatomic = rtd->dai_link->nonatomic;
rtd->pcm = pcm; rtd->pcm = pcm;
......
...@@ -1935,11 +1935,13 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, ...@@ -1935,11 +1935,13 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
ret = soc_tplg_dai_link_load(tplg, link, NULL); ret = soc_tplg_dai_link_load(tplg, link, NULL);
if (ret < 0) { if (ret < 0) {
dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n"); dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n");
kfree(link->name); goto err;
kfree(link->stream_name); }
kfree(link->cpus->dai_name);
kfree(link); ret = snd_soc_add_pcm_runtime(tplg->comp->card, link);
return ret; if (ret < 0) {
dev_err(tplg->comp->dev, "ASoC: adding FE link failed\n");
goto err;
} }
link->dobj.index = tplg->index; link->dobj.index = tplg->index;
...@@ -1947,8 +1949,13 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, ...@@ -1947,8 +1949,13 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
link->dobj.type = SND_SOC_DOBJ_DAI_LINK; link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
list_add(&link->dobj.list, &tplg->comp->dobj_list); list_add(&link->dobj.list, &tplg->comp->dobj_list);
snd_soc_add_pcm_runtime(tplg->comp->card, link);
return 0; return 0;
err:
kfree(link->name);
kfree(link->stream_name);
kfree(link->cpus->dai_name);
kfree(link);
return ret;
} }
/* create a FE DAI and DAI link from the PCM object */ /* create a FE DAI and DAI link from the PCM object */
...@@ -2041,6 +2048,7 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, ...@@ -2041,6 +2048,7 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
int size; int size;
int i; int i;
bool abi_match; bool abi_match;
int ret;
count = le32_to_cpu(hdr->count); count = le32_to_cpu(hdr->count);
...@@ -2082,7 +2090,12 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, ...@@ -2082,7 +2090,12 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
} }
/* create the FE DAIs and DAI links */ /* create the FE DAIs and DAI links */
soc_tplg_pcm_create(tplg, _pcm); ret = soc_tplg_pcm_create(tplg, _pcm);
if (ret < 0) {
if (!abi_match)
kfree(_pcm);
return ret;
}
/* offset by version-specific struct size and /* offset by version-specific struct size and
* real priv data size * real priv data size
......
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
#define DRAM_OFFSET 0x100000 #define DRAM_OFFSET 0x100000
#define DRAM_SIZE (160 * 1024) #define DRAM_SIZE (160 * 1024)
#define SHIM_OFFSET 0x140000 #define SHIM_OFFSET 0x140000
#define SHIM_SIZE 0x100 #define SHIM_SIZE_BYT 0x100
#define SHIM_SIZE_CHT 0x118
#define MBOX_OFFSET 0x144000 #define MBOX_OFFSET 0x144000
#define MBOX_SIZE 0x1000 #define MBOX_SIZE 0x1000
#define EXCEPT_OFFSET 0x800 #define EXCEPT_OFFSET 0x800
...@@ -77,7 +78,7 @@ static const struct snd_sof_debugfs_map byt_debugfs[] = { ...@@ -77,7 +78,7 @@ static const struct snd_sof_debugfs_map byt_debugfs[] = {
SOF_DEBUGFS_ACCESS_D0_ONLY}, SOF_DEBUGFS_ACCESS_D0_ONLY},
{"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE, {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
SOF_DEBUGFS_ACCESS_D0_ONLY}, SOF_DEBUGFS_ACCESS_D0_ONLY},
{"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE, {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_BYT,
SOF_DEBUGFS_ACCESS_ALWAYS}, SOF_DEBUGFS_ACCESS_ALWAYS},
}; };
...@@ -104,7 +105,7 @@ static const struct snd_sof_debugfs_map cht_debugfs[] = { ...@@ -104,7 +105,7 @@ static const struct snd_sof_debugfs_map cht_debugfs[] = {
SOF_DEBUGFS_ACCESS_D0_ONLY}, SOF_DEBUGFS_ACCESS_D0_ONLY},
{"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE, {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
SOF_DEBUGFS_ACCESS_D0_ONLY}, SOF_DEBUGFS_ACCESS_D0_ONLY},
{"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE, {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE_CHT,
SOF_DEBUGFS_ACCESS_ALWAYS}, SOF_DEBUGFS_ACCESS_ALWAYS},
}; };
...@@ -147,33 +148,33 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags) ...@@ -147,33 +148,33 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags)
struct sof_ipc_dsp_oops_xtensa xoops; struct sof_ipc_dsp_oops_xtensa xoops;
struct sof_ipc_panic_info panic_info; struct sof_ipc_panic_info panic_info;
u32 stack[BYT_STACK_DUMP_SIZE]; u32 stack[BYT_STACK_DUMP_SIZE];
u32 status, panic, imrd, imrx; u64 status, panic, imrd, imrx;
/* now try generic SOF status messages */ /* now try generic SOF status messages */
status = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCD); status = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
panic = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCX); panic = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
byt_get_registers(sdev, &xoops, &panic_info, stack, byt_get_registers(sdev, &xoops, &panic_info, stack,
BYT_STACK_DUMP_SIZE); BYT_STACK_DUMP_SIZE);
snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack, snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
BYT_STACK_DUMP_SIZE); BYT_STACK_DUMP_SIZE);
/* provide some context for firmware debug */ /* provide some context for firmware debug */
imrx = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRX); imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX);
imrd = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRD); imrd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRD);
dev_err(sdev->dev, dev_err(sdev->dev,
"error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n", "error: ipc host -> DSP: pending %s complete %s raw 0x%llx\n",
(panic & SHIM_IPCX_BUSY) ? "yes" : "no", (panic & SHIM_IPCX_BUSY) ? "yes" : "no",
(panic & SHIM_IPCX_DONE) ? "yes" : "no", panic); (panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
dev_err(sdev->dev, dev_err(sdev->dev,
"error: mask host: pending %s complete %s raw 0x%8.8x\n", "error: mask host: pending %s complete %s raw 0x%llx\n",
(imrx & SHIM_IMRX_BUSY) ? "yes" : "no", (imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
(imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx); (imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
dev_err(sdev->dev, dev_err(sdev->dev,
"error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n", "error: ipc DSP -> host: pending %s complete %s raw 0x%llx\n",
(status & SHIM_IPCD_BUSY) ? "yes" : "no", (status & SHIM_IPCD_BUSY) ? "yes" : "no",
(status & SHIM_IPCD_DONE) ? "yes" : "no", status); (status & SHIM_IPCD_DONE) ? "yes" : "no", status);
dev_err(sdev->dev, dev_err(sdev->dev,
"error: mask DSP: pending %s complete %s raw 0x%8.8x\n", "error: mask DSP: pending %s complete %s raw 0x%llx\n",
(imrd & SHIM_IMRD_BUSY) ? "yes" : "no", (imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
(imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd); (imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
......
...@@ -50,8 +50,7 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) ...@@ -50,8 +50,7 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset)
while (ext_hdr->hdr.cmd == SOF_IPC_FW_READY) { while (ext_hdr->hdr.cmd == SOF_IPC_FW_READY) {
/* read in ext structure */ /* read in ext structure */
offset += sizeof(*ext_hdr); snd_sof_dsp_block_read(sdev, bar, offset + sizeof(*ext_hdr),
snd_sof_dsp_block_read(sdev, bar, offset,
(void *)((u8 *)ext_data + sizeof(*ext_hdr)), (void *)((u8 *)ext_data + sizeof(*ext_hdr)),
ext_hdr->hdr.size - sizeof(*ext_hdr)); ext_hdr->hdr.size - sizeof(*ext_hdr));
...@@ -61,11 +60,15 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset) ...@@ -61,11 +60,15 @@ int snd_sof_fw_parse_ext_data(struct snd_sof_dev *sdev, u32 bar, u32 offset)
/* process structure data */ /* process structure data */
switch (ext_hdr->type) { switch (ext_hdr->type) {
case SOF_IPC_EXT_DMA_BUFFER: case SOF_IPC_EXT_DMA_BUFFER:
ret = 0;
break; break;
case SOF_IPC_EXT_WINDOW: case SOF_IPC_EXT_WINDOW:
ret = get_ext_windows(sdev, ext_hdr); ret = get_ext_windows(sdev, ext_hdr);
break; break;
default: default:
dev_warn(sdev->dev, "warning: unknown ext header type %d size 0x%x\n",
ext_hdr->type, ext_hdr->hdr.size);
ret = 0;
break; break;
} }
......
...@@ -3208,7 +3208,9 @@ static int sof_link_unload(struct snd_soc_component *scomp, ...@@ -3208,7 +3208,9 @@ static int sof_link_unload(struct snd_soc_component *scomp,
case SOF_DAI_INTEL_SSP: case SOF_DAI_INTEL_SSP:
case SOF_DAI_INTEL_DMIC: case SOF_DAI_INTEL_DMIC:
case SOF_DAI_INTEL_ALH: case SOF_DAI_INTEL_ALH:
/* no resource needs to be released for SSP, DMIC and ALH */ case SOF_DAI_IMX_SAI:
case SOF_DAI_IMX_ESAI:
/* no resource needs to be released for all cases above */
break; break;
case SOF_DAI_INTEL_HDA: case SOF_DAI_INTEL_HDA:
ret = sof_link_hda_unload(sdev, link); ret = sof_link_hda_unload(sdev, link);
......
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