summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/amd/acp/acp-sof-mach.c14
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c14
-rw-r--r--sound/soc/codecs/rt5645.c10
-rw-r--r--sound/soc/codecs/rt5682-sdw.c4
-rw-r--r--sound/soc/codecs/rt711-sdca-sdw.c4
-rw-r--r--sound/soc/codecs/rt711-sdw.c4
-rw-r--r--sound/soc/codecs/wm8962.c29
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c12
-rw-r--r--sound/soc/meson/aiu.c19
-rw-r--r--sound/soc/meson/aiu.h1
-rw-r--r--sound/soc/meson/axg-tdm-interface.c29
-rw-r--r--sound/soc/meson/t9015.c20
-rw-r--r--sound/soc/rockchip/rockchip_i2s_tdm.c352
-rw-r--r--sound/soc/soc-ops.c2
-rw-r--r--sound/soc/sof/ipc3-loader.c28
-rw-r--r--sound/soc/sof/ipc4-loader.c6
-rw-r--r--sound/soc/sof/loader.c18
-rw-r--r--sound/soc/sof/sof-priv.h14
18 files changed, 145 insertions, 435 deletions
diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
index f19f064a7..972600d27 100644
--- a/sound/soc/amd/acp/acp-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sof-mach.c
@@ -114,16 +114,14 @@ static int acp_sof_probe(struct platform_device *pdev)
card->num_controls = ARRAY_SIZE(acp_controls);
card->drvdata = (struct acp_card_drvdata *)pdev->id_entry->driver_data;
- acp_sofdsp_dai_links_create(card);
+ ret = acp_sofdsp_dai_links_create(card);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Failed to create DAI links\n");
ret = devm_snd_soc_register_card(&pdev->dev, card);
- if (ret) {
- dev_err(&pdev->dev,
- "devm_snd_soc_register_card(%s) failed: %d\n",
- card->name, ret);
- return ret;
- }
-
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to register card(%s)\n", card->name);
return 0;
}
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 28da4e185..0568e64d1 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -203,6 +203,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21J0"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21J5"),
}
},
@@ -231,6 +238,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "82UU"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82V2"),
}
},
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 844d14d4c..aac914074 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -3802,6 +3802,16 @@ static const struct dmi_system_id dmi_platform_data[] = {
DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
DMI_EXACT_MATCH(DMI_BOARD_VERSION, "Default string"),
+ /*
+ * Above strings are too generic, LattePanda BIOS versions for
+ * all 4 hw revisions are:
+ * DF-BI-7-S70CR100-*
+ * DF-BI-7-S70CR110-*
+ * DF-BI-7-S70CR200-*
+ * LP-BS-7-S70CR700-*
+ * Do a partial match for S70CR to avoid false positive matches.
+ */
+ DMI_MATCH(DMI_BIOS_VERSION, "S70CR"),
},
.driver_data = (void *)&lattepanda_board_platform_data,
},
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
index 868a61c8b..7685011a0 100644
--- a/sound/soc/codecs/rt5682-sdw.c
+++ b/sound/soc/codecs/rt5682-sdw.c
@@ -787,12 +787,12 @@ static int __maybe_unused rt5682_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
+ mutex_lock(&rt5682->disable_irq_lock);
if (rt5682->disable_irq == true) {
- mutex_lock(&rt5682->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
rt5682->disable_irq = false;
- mutex_unlock(&rt5682->disable_irq_lock);
}
+ mutex_unlock(&rt5682->disable_irq_lock);
goto regmap_sync;
}
diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c
index 487d3010d..931dbc685 100644
--- a/sound/soc/codecs/rt711-sdca-sdw.c
+++ b/sound/soc/codecs/rt711-sdca-sdw.c
@@ -443,13 +443,13 @@ static int __maybe_unused rt711_sdca_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
+ mutex_lock(&rt711->disable_irq_lock);
if (rt711->disable_irq == true) {
- mutex_lock(&rt711->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
rt711->disable_irq = false;
- mutex_unlock(&rt711->disable_irq_lock);
}
+ mutex_unlock(&rt711->disable_irq_lock);
goto regmap_sync;
}
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
index 9545b8a7e..af7a0ab56 100644
--- a/sound/soc/codecs/rt711-sdw.c
+++ b/sound/soc/codecs/rt711-sdw.c
@@ -542,12 +542,12 @@ static int __maybe_unused rt711_dev_resume(struct device *dev)
return 0;
if (!slave->unattach_request) {
+ mutex_lock(&rt711->disable_irq_lock);
if (rt711->disable_irq == true) {
- mutex_lock(&rt711->disable_irq_lock);
sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
rt711->disable_irq = false;
- mutex_unlock(&rt711->disable_irq_lock);
}
+ mutex_unlock(&rt711->disable_irq_lock);
goto regmap_sync;
}
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index b901e4c65..d215e58c4 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2229,6 +2229,9 @@ SND_SOC_DAPM_PGA_E("HPOUT", SND_SOC_NOPM, 0, 0, NULL, 0, hp_event,
SND_SOC_DAPM_OUTPUT("HPOUTL"),
SND_SOC_DAPM_OUTPUT("HPOUTR"),
+
+SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
};
static const struct snd_soc_dapm_widget wm8962_dapm_spk_mono_widgets[] = {
@@ -2236,7 +2239,6 @@ SND_SOC_DAPM_MIXER("Speaker Mixer", WM8962_MIXER_ENABLES, 1, 0,
spkmixl, ARRAY_SIZE(spkmixl)),
SND_SOC_DAPM_MUX_E("Speaker PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
out_pga_event, SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA("Speaker Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("SPKOUT"),
};
@@ -2251,9 +2253,6 @@ SND_SOC_DAPM_MUX_E("SPKOUTL PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
SND_SOC_DAPM_MUX_E("SPKOUTR PGA", WM8962_PWR_MGMT_2, 3, 0, &spkoutr_mux,
out_pga_event, SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
-SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0),
-
SND_SOC_DAPM_OUTPUT("SPKOUTL"),
SND_SOC_DAPM_OUTPUT("SPKOUTR"),
};
@@ -2366,12 +2365,18 @@ static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
{ "Speaker PGA", "Mixer", "Speaker Mixer" },
{ "Speaker PGA", "DAC", "DACL" },
- { "Speaker Output", NULL, "Speaker PGA" },
- { "Speaker Output", NULL, "SYSCLK" },
- { "Speaker Output", NULL, "TOCLK" },
- { "Speaker Output", NULL, "TEMP_SPK" },
+ { "SPKOUTL Output", NULL, "Speaker PGA" },
+ { "SPKOUTL Output", NULL, "SYSCLK" },
+ { "SPKOUTL Output", NULL, "TOCLK" },
+ { "SPKOUTL Output", NULL, "TEMP_SPK" },
- { "SPKOUT", NULL, "Speaker Output" },
+ { "SPKOUTR Output", NULL, "Speaker PGA" },
+ { "SPKOUTR Output", NULL, "SYSCLK" },
+ { "SPKOUTR Output", NULL, "TOCLK" },
+ { "SPKOUTR Output", NULL, "TEMP_SPK" },
+
+ { "SPKOUT", NULL, "SPKOUTL Output" },
+ { "SPKOUT", NULL, "SPKOUTR Output" },
};
static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = {
@@ -2914,8 +2919,12 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s
switch (fll_id) {
case WM8962_FLL_MCLK:
case WM8962_FLL_BCLK:
+ fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT;
+ break;
case WM8962_FLL_OSC:
fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT;
+ snd_soc_component_update_bits(component, WM8962_PLL2,
+ WM8962_OSC_ENA, WM8962_OSC_ENA);
break;
case WM8962_FLL_INT:
snd_soc_component_update_bits(component, WM8962_FLL_CONTROL_1,
@@ -2924,7 +2933,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s
WM8962_FLL_FRC_NCO, WM8962_FLL_FRC_NCO);
break;
default:
- dev_err(component->dev, "Unknown FLL source %d\n", ret);
+ dev_err(component->dev, "Unknown FLL source %d\n", source);
return -EINVAL;
}
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 797d0a48d..094445036 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -685,6 +685,18 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
+ { /* Chuwi Vi8 dual-boot (CWI506) */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "i86"),
+ /* The above are too generic, also match BIOS info */
+ DMI_MATCH(DMI_BIOS_VERSION, "CHUWI2.D86JHBNR02"),
+ },
+ .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+ BYT_RT5640_MONO_SPEAKER |
+ BYT_RT5640_SSP0_AIF1 |
+ BYT_RT5640_MCLK_EN),
+ },
{
/* Chuwi Vi10 (CWI505) */
.matches = {
diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c
index 88e611e64..077b9c0b6 100644
--- a/sound/soc/meson/aiu.c
+++ b/sound/soc/meson/aiu.c
@@ -218,11 +218,12 @@ static const char * const aiu_spdif_ids[] = {
static int aiu_clk_get(struct device *dev)
{
struct aiu *aiu = dev_get_drvdata(dev);
+ struct clk *pclk;
int ret;
- aiu->pclk = devm_clk_get(dev, "pclk");
- if (IS_ERR(aiu->pclk))
- return dev_err_probe(dev, PTR_ERR(aiu->pclk), "Can't get the aiu pclk\n");
+ pclk = devm_clk_get_enabled(dev, "pclk");
+ if (IS_ERR(pclk))
+ return dev_err_probe(dev, PTR_ERR(pclk), "Can't get the aiu pclk\n");
aiu->spdif_mclk = devm_clk_get(dev, "spdif_mclk");
if (IS_ERR(aiu->spdif_mclk))
@@ -239,18 +240,6 @@ static int aiu_clk_get(struct device *dev)
if (ret)
return dev_err_probe(dev, ret, "Can't get the spdif clocks\n");
- ret = clk_prepare_enable(aiu->pclk);
- if (ret) {
- dev_err(dev, "peripheral clock enable failed\n");
- return ret;
- }
-
- ret = devm_add_action_or_reset(dev,
- (void(*)(void *))clk_disable_unprepare,
- aiu->pclk);
- if (ret)
- dev_err(dev, "failed to add reset action on pclk");
-
return ret;
}
diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h
index 393b6c230..0f94c8bf6 100644
--- a/sound/soc/meson/aiu.h
+++ b/sound/soc/meson/aiu.h
@@ -33,7 +33,6 @@ struct aiu_platform_data {
};
struct aiu {
- struct clk *pclk;
struct clk *spdif_mclk;
struct aiu_interface i2s;
struct aiu_interface spdif;
diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c
index c040c8363..028383f94 100644
--- a/sound/soc/meson/axg-tdm-interface.c
+++ b/sound/soc/meson/axg-tdm-interface.c
@@ -12,6 +12,9 @@
#include "axg-tdm.h"
+/* Maximum bit clock frequency according the datasheets */
+#define MAX_SCLK 100000000 /* Hz */
+
enum {
TDM_IFACE_PAD,
TDM_IFACE_LOOPBACK,
@@ -155,19 +158,27 @@ static int axg_tdm_iface_startup(struct snd_pcm_substream *substream,
return -EINVAL;
}
- /* Apply component wide rate symmetry */
if (snd_soc_component_active(dai->component)) {
+ /* Apply component wide rate symmetry */
ret = snd_pcm_hw_constraint_single(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
iface->rate);
- if (ret < 0) {
- dev_err(dai->dev,
- "can't set iface rate constraint\n");
- return ret;
- }
+
+ } else {
+ /* Limit rate according to the slot number and width */
+ unsigned int max_rate =
+ MAX_SCLK / (iface->slots * iface->slot_width);
+ ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ 0, max_rate);
}
- return 0;
+ if (ret < 0)
+ dev_err(dai->dev, "can't set iface rate constraint\n");
+ else
+ ret = 0;
+
+ return ret;
}
static int axg_tdm_iface_set_stream(struct snd_pcm_substream *substream,
@@ -266,8 +277,8 @@ static int axg_tdm_iface_set_sclk(struct snd_soc_dai *dai,
srate = iface->slots * iface->slot_width * params_rate(params);
if (!iface->mclk_rate) {
- /* If no specific mclk is requested, default to bit clock * 4 */
- clk_set_rate(iface->mclk, 4 * srate);
+ /* If no specific mclk is requested, default to bit clock * 2 */
+ clk_set_rate(iface->mclk, 2 * srate);
} else {
/* Check if we can actually get the bit clock from mclk */
if (iface->mclk_rate % srate) {
diff --git a/sound/soc/meson/t9015.c b/sound/soc/meson/t9015.c
index 9c6b4dac6..571f65788 100644
--- a/sound/soc/meson/t9015.c
+++ b/sound/soc/meson/t9015.c
@@ -48,7 +48,6 @@
#define POWER_CFG 0x10
struct t9015 {
- struct clk *pclk;
struct regulator *avdd;
};
@@ -249,6 +248,7 @@ static int t9015_probe(struct platform_device *pdev)
struct t9015 *priv;
void __iomem *regs;
struct regmap *regmap;
+ struct clk *pclk;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -256,26 +256,14 @@ static int t9015_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, priv);
- priv->pclk = devm_clk_get(dev, "pclk");
- if (IS_ERR(priv->pclk))
- return dev_err_probe(dev, PTR_ERR(priv->pclk), "failed to get core clock\n");
+ pclk = devm_clk_get_enabled(dev, "pclk");
+ if (IS_ERR(pclk))
+ return dev_err_probe(dev, PTR_ERR(pclk), "failed to get core clock\n");
priv->avdd = devm_regulator_get(dev, "AVDD");
if (IS_ERR(priv->avdd))
return dev_err_probe(dev, PTR_ERR(priv->avdd), "failed to AVDD\n");
- ret = clk_prepare_enable(priv->pclk);
- if (ret) {
- dev_err(dev, "core clock enable failed\n");
- return ret;
- }
-
- ret = devm_add_action_or_reset(dev,
- (void(*)(void *))clk_disable_unprepare,
- priv->pclk);
- if (ret)
- return ret;
-
ret = device_reset(dev);
if (ret) {
dev_err(dev, "reset failed\n");
diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c
index 2550bd2a5..2e36a9707 100644
--- a/sound/soc/rockchip/rockchip_i2s_tdm.c
+++ b/sound/soc/rockchip/rockchip_i2s_tdm.c
@@ -27,8 +27,6 @@
#define DEFAULT_MCLK_FS 256
#define CH_GRP_MAX 4 /* The max channel 8 / 2 */
#define MULTIPLEX_CH_MAX 10
-#define CLK_PPM_MIN -1000
-#define CLK_PPM_MAX 1000
#define TRCM_TXRX 0
#define TRCM_TX 1
@@ -55,20 +53,6 @@ struct rk_i2s_tdm_dev {
struct clk *hclk;
struct clk *mclk_tx;
struct clk *mclk_rx;
- /* The mclk_tx_src is parent of mclk_tx */
- struct clk *mclk_tx_src;
- /* The mclk_rx_src is parent of mclk_rx */
- struct clk *mclk_rx_src;
- /*
- * The mclk_root0 and mclk_root1 are root parent and supplies for
- * the different FS.
- *
- * e.g:
- * mclk_root0 is VPLL0, used for FS=48000Hz
- * mclk_root1 is VPLL1, used for FS=44100Hz
- */
- struct clk *mclk_root0;
- struct clk *mclk_root1;
struct regmap *regmap;
struct regmap *grf;
struct snd_dmaengine_dai_dma_data capture_dma_data;
@@ -78,19 +62,11 @@ struct rk_i2s_tdm_dev {
struct rk_i2s_soc_data *soc_data;
bool is_master_mode;
bool io_multiplex;
- bool mclk_calibrate;
bool tdm_mode;
- unsigned int mclk_rx_freq;
- unsigned int mclk_tx_freq;
- unsigned int mclk_root0_freq;
- unsigned int mclk_root1_freq;
- unsigned int mclk_root0_initial_freq;
- unsigned int mclk_root1_initial_freq;
unsigned int frame_width;
unsigned int clk_trcm;
unsigned int i2s_sdis[CH_GRP_MAX];
unsigned int i2s_sdos[CH_GRP_MAX];
- int clk_ppm;
int refcount;
spinlock_t lock; /* xfer lock */
bool has_playback;
@@ -116,12 +92,6 @@ static void i2s_tdm_disable_unprepare_mclk(struct rk_i2s_tdm_dev *i2s_tdm)
{
clk_disable_unprepare(i2s_tdm->mclk_tx);
clk_disable_unprepare(i2s_tdm->mclk_rx);
- if (i2s_tdm->mclk_calibrate) {
- clk_disable_unprepare(i2s_tdm->mclk_tx_src);
- clk_disable_unprepare(i2s_tdm->mclk_rx_src);
- clk_disable_unprepare(i2s_tdm->mclk_root0);
- clk_disable_unprepare(i2s_tdm->mclk_root1);
- }
}
/**
@@ -144,29 +114,9 @@ static int i2s_tdm_prepare_enable_mclk(struct rk_i2s_tdm_dev *i2s_tdm)
ret = clk_prepare_enable(i2s_tdm->mclk_rx);
if (ret)
goto err_mclk_rx;
- if (i2s_tdm->mclk_calibrate) {
- ret = clk_prepare_enable(i2s_tdm->mclk_tx_src);
- if (ret)
- goto err_mclk_rx;
- ret = clk_prepare_enable(i2s_tdm->mclk_rx_src);
- if (ret)
- goto err_mclk_rx_src;
- ret = clk_prepare_enable(i2s_tdm->mclk_root0);
- if (ret)
- goto err_mclk_root0;
- ret = clk_prepare_enable(i2s_tdm->mclk_root1);
- if (ret)
- goto err_mclk_root1;
- }
return 0;
-err_mclk_root1:
- clk_disable_unprepare(i2s_tdm->mclk_root0);
-err_mclk_root0:
- clk_disable_unprepare(i2s_tdm->mclk_rx_src);
-err_mclk_rx_src:
- clk_disable_unprepare(i2s_tdm->mclk_tx_src);
err_mclk_rx:
clk_disable_unprepare(i2s_tdm->mclk_tx);
err_mclk_tx:
@@ -566,159 +516,6 @@ static void rockchip_i2s_tdm_xfer_resume(struct snd_pcm_substream *substream,
I2S_XFER_RXS_START);
}
-static int rockchip_i2s_tdm_clk_set_rate(struct rk_i2s_tdm_dev *i2s_tdm,
- struct clk *clk, unsigned long rate,
- int ppm)
-{
- unsigned long rate_target;
- int delta, ret;
-
- if (ppm == i2s_tdm->clk_ppm)
- return 0;
-
- if (ppm < 0)
- delta = -1;
- else
- delta = 1;
-
- delta *= (int)div64_u64((u64)rate * (u64)abs(ppm) + 500000,
- 1000000);
-
- rate_target = rate + delta;
-
- if (!rate_target)
- return -EINVAL;
-
- ret = clk_set_rate(clk, rate_target);
- if (ret)
- return ret;
-
- i2s_tdm->clk_ppm = ppm;
-
- return 0;
-}
-
-static int rockchip_i2s_tdm_calibrate_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
- struct snd_pcm_substream *substream,
- unsigned int lrck_freq)
-{
- struct clk *mclk_root;
- struct clk *mclk_parent;
- unsigned int mclk_root_freq;
- unsigned int mclk_root_initial_freq;
- unsigned int mclk_parent_freq;
- unsigned int div, delta;
- u64 ppm;
- int ret;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- mclk_parent = i2s_tdm->mclk_tx_src;
- else
- mclk_parent = i2s_tdm->mclk_rx_src;
-
- switch (lrck_freq) {
- case 8000:
- case 16000:
- case 24000:
- case 32000:
- case 48000:
- case 64000:
- case 96000:
- case 192000:
- mclk_root = i2s_tdm->mclk_root0;
- mclk_root_freq = i2s_tdm->mclk_root0_freq;
- mclk_root_initial_freq = i2s_tdm->mclk_root0_initial_freq;
- mclk_parent_freq = DEFAULT_MCLK_FS * 192000;
- break;
- case 11025:
- case 22050:
- case 44100:
- case 88200:
- case 176400:
- mclk_root = i2s_tdm->mclk_root1;
- mclk_root_freq = i2s_tdm->mclk_root1_freq;
- mclk_root_initial_freq = i2s_tdm->mclk_root1_initial_freq;
- mclk_parent_freq = DEFAULT_MCLK_FS * 176400;
- break;
- default:
- dev_err(i2s_tdm->dev, "Invalid LRCK frequency: %u Hz\n",
- lrck_freq);
- return -EINVAL;
- }
-
- ret = clk_set_parent(mclk_parent, mclk_root);
- if (ret)
- return ret;
-
- ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, mclk_root,
- mclk_root_freq, 0);
- if (ret)
- return ret;
-
- delta = abs(mclk_root_freq % mclk_parent_freq - mclk_parent_freq);
- ppm = div64_u64((uint64_t)delta * 1000000, (uint64_t)mclk_root_freq);
-
- if (ppm) {
- div = DIV_ROUND_CLOSEST(mclk_root_initial_freq, mclk_parent_freq);
- if (!div)
- return -EINVAL;
-
- mclk_root_freq = mclk_parent_freq * round_up(div, 2);
-
- ret = clk_set_rate(mclk_root, mclk_root_freq);
- if (ret)
- return ret;
-
- i2s_tdm->mclk_root0_freq = clk_get_rate(i2s_tdm->mclk_root0);
- i2s_tdm->mclk_root1_freq = clk_get_rate(i2s_tdm->mclk_root1);
- }
-
- return clk_set_rate(mclk_parent, mclk_parent_freq);
-}
-
-static int rockchip_i2s_tdm_set_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
- struct snd_pcm_substream *substream,
- struct clk **mclk)
-{
- unsigned int mclk_freq;
- int ret;
-
- if (i2s_tdm->clk_trcm) {
- if (i2s_tdm->mclk_tx_freq != i2s_tdm->mclk_rx_freq) {
- dev_err(i2s_tdm->dev,
- "clk_trcm, tx: %d and rx: %d should be the same\n",
- i2s_tdm->mclk_tx_freq,
- i2s_tdm->mclk_rx_freq);
- return -EINVAL;
- }
-
- ret = clk_set_rate(i2s_tdm->mclk_tx, i2s_tdm->mclk_tx_freq);
- if (ret)
- return ret;
-
- ret = clk_set_rate(i2s_tdm->mclk_rx, i2s_tdm->mclk_rx_freq);
- if (ret)
- return ret;
-
- /* mclk_rx is also ok. */
- *mclk = i2s_tdm->mclk_tx;
- } else {
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- *mclk = i2s_tdm->mclk_tx;
- mclk_freq = i2s_tdm->mclk_tx_freq;
- } else {
- *mclk = i2s_tdm->mclk_rx;
- mclk_freq = i2s_tdm->mclk_rx_freq;
- }
-
- ret = clk_set_rate(*mclk, mclk_freq);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
static int rockchip_i2s_ch_to_io(unsigned int ch, bool substream_capture)
{
if (substream_capture) {
@@ -849,19 +646,17 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
- struct clk *mclk;
- int ret = 0;
unsigned int val = 0;
unsigned int mclk_rate, bclk_rate, div_bclk = 4, div_lrck = 64;
+ int err;
if (i2s_tdm->is_master_mode) {
- if (i2s_tdm->mclk_calibrate)
- rockchip_i2s_tdm_calibrate_mclk(i2s_tdm, substream,
- params_rate(params));
+ struct clk *mclk = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ i2s_tdm->mclk_tx : i2s_tdm->mclk_rx;
- ret = rockchip_i2s_tdm_set_mclk(i2s_tdm, substream, &mclk);
- if (ret)
- return ret;
+ err = clk_set_rate(mclk, DEFAULT_MCLK_FS * params_rate(params));
+ if (err)
+ return err;
mclk_rate = clk_get_rate(mclk);
bclk_rate = i2s_tdm->frame_width * params_rate(params);
@@ -969,96 +764,6 @@ static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream,
return 0;
}
-static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int stream,
- unsigned int freq, int dir)
-{
- struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai);
-
- /* Put set mclk rate into rockchip_i2s_tdm_set_mclk() */
- if (i2s_tdm->clk_trcm) {
- i2s_tdm->mclk_tx_freq = freq;
- i2s_tdm->mclk_rx_freq = freq;
- } else {
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- i2s_tdm->mclk_tx_freq = freq;
- else
- i2s_tdm->mclk_rx_freq = freq;
- }
-
- dev_dbg(i2s_tdm->dev, "The target mclk_%s freq is: %d\n",
- stream ? "rx" : "tx", freq);
-
- return 0;
-}
-
-static int rockchip_i2s_tdm_clk_compensation_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = CLK_PPM_MIN;
- uinfo->value.integer.max = CLK_PPM_MAX;
- uinfo->value.integer.step = 1;
-
- return 0;
-}
-
-static int rockchip_i2s_tdm_clk_compensation_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
- struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
-
- ucontrol->value.integer.value[0] = i2s_tdm->clk_ppm;
-
- return 0;
-}
-
-static int rockchip_i2s_tdm_clk_compensation_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
- struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
- int ret = 0, ppm = 0;
- int changed = 0;
- unsigned long old_rate;
-
- if (ucontrol->value.integer.value[0] < CLK_PPM_MIN ||
- ucontrol->value.integer.value[0] > CLK_PPM_MAX)
- return -EINVAL;
-
- ppm = ucontrol->value.integer.value[0];
-
- old_rate = clk_get_rate(i2s_tdm->mclk_root0);
- ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, i2s_tdm->mclk_root0,
- i2s_tdm->mclk_root0_freq, ppm);
- if (ret)
- return ret;
- if (old_rate != clk_get_rate(i2s_tdm->mclk_root0))
- changed = 1;
-
- if (clk_is_match(i2s_tdm->mclk_root0, i2s_tdm->mclk_root1))
- return changed;
-
- old_rate = clk_get_rate(i2s_tdm->mclk_root1);
- ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, i2s_tdm->mclk_root1,
- i2s_tdm->mclk_root1_freq, ppm);
- if (ret)
- return ret;
- if (old_rate != clk_get_rate(i2s_tdm->mclk_root1))
- changed = 1;
-
- return changed;
-}
-
-static struct snd_kcontrol_new rockchip_i2s_tdm_compensation_control = {
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "PCM Clock Compensation in PPM",
- .info = rockchip_i2s_tdm_clk_compensation_info,
- .get = rockchip_i2s_tdm_clk_compensation_get,
- .put = rockchip_i2s_tdm_clk_compensation_put,
-};
-
static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
{
struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
@@ -1068,9 +773,6 @@ static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
if (i2s_tdm->has_playback)
dai->playback_dma_data = &i2s_tdm->playback_dma_data;
- if (i2s_tdm->mclk_calibrate)
- snd_soc_add_dai_controls(dai, &rockchip_i2s_tdm_compensation_control, 1);
-
return 0;
}
@@ -1110,7 +812,6 @@ static int rockchip_i2s_tdm_set_bclk_ratio(struct snd_soc_dai *dai,
static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = {
.hw_params = rockchip_i2s_tdm_hw_params,
.set_bclk_ratio = rockchip_i2s_tdm_set_bclk_ratio,
- .set_sysclk = rockchip_i2s_tdm_set_sysclk,
.set_fmt = rockchip_i2s_tdm_set_fmt,
.set_tdm_slot = rockchip_dai_tdm_slot,
.trigger = rockchip_i2s_tdm_trigger,
@@ -1433,35 +1134,6 @@ static void rockchip_i2s_tdm_path_config(struct rk_i2s_tdm_dev *i2s_tdm,
rockchip_i2s_tdm_tx_path_config(i2s_tdm, num);
}
-static int rockchip_i2s_tdm_get_calibrate_mclks(struct rk_i2s_tdm_dev *i2s_tdm)
-{
- int num_mclks = 0;
-
- i2s_tdm->mclk_tx_src = devm_clk_get(i2s_tdm->dev, "mclk_tx_src");
- if (!IS_ERR(i2s_tdm->mclk_tx_src))
- num_mclks++;
-
- i2s_tdm->mclk_rx_src = devm_clk_get(i2s_tdm->dev, "mclk_rx_src");
- if (!IS_ERR(i2s_tdm->mclk_rx_src))
- num_mclks++;
-
- i2s_tdm->mclk_root0 = devm_clk_get(i2s_tdm->dev, "mclk_root0");
- if (!IS_ERR(i2s_tdm->mclk_root0))
- num_mclks++;
-
- i2s_tdm->mclk_root1 = devm_clk_get(i2s_tdm->dev, "mclk_root1");
- if (!IS_ERR(i2s_tdm->mclk_root1))
- num_mclks++;
-
- if (num_mclks < 4 && num_mclks != 0)
- return -ENOENT;
-
- if (num_mclks == 4)
- i2s_tdm->mclk_calibrate = 1;
-
- return 0;
-}
-
static int rockchip_i2s_tdm_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm,
struct device_node *np,
bool is_rx_path)
@@ -1609,11 +1281,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
i2s_tdm->io_multiplex =
of_property_read_bool(node, "rockchip,io-multiplex");
- ret = rockchip_i2s_tdm_get_calibrate_mclks(i2s_tdm);
- if (ret)
- return dev_err_probe(i2s_tdm->dev, ret,
- "mclk-calibrate clocks missing");
-
regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(regs)) {
return dev_err_probe(i2s_tdm->dev, PTR_ERR(regs),
@@ -1666,13 +1333,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
goto err_disable_hclk;
}
- if (i2s_tdm->mclk_calibrate) {
- i2s_tdm->mclk_root0_initial_freq = clk_get_rate(i2s_tdm->mclk_root0);
- i2s_tdm->mclk_root1_initial_freq = clk_get_rate(i2s_tdm->mclk_root1);
- i2s_tdm->mclk_root0_freq = i2s_tdm->mclk_root0_initial_freq;
- i2s_tdm->mclk_root1_freq = i2s_tdm->mclk_root1_initial_freq;
- }
-
pm_runtime_enable(&pdev->dev);
regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 2d25748ca..b27e89ff6 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -263,7 +263,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
int max = mc->max;
int min = mc->min;
int sign_bit = mc->sign_bit;
- unsigned int mask = (1 << fls(max)) - 1;
+ unsigned int mask = (1ULL << fls(max)) - 1;
unsigned int invert = mc->invert;
int val;
int ret;
diff --git a/sound/soc/sof/ipc3-loader.c b/sound/soc/sof/ipc3-loader.c
index bf423ca4e..6e3ef0672 100644
--- a/sound/soc/sof/ipc3-loader.c
+++ b/sound/soc/sof/ipc3-loader.c
@@ -138,8 +138,7 @@ static ssize_t ipc3_fw_ext_man_size(struct snd_sof_dev *sdev, const struct firmw
static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev)
{
- struct snd_sof_pdata *plat_data = sdev->pdata;
- const struct firmware *fw = plat_data->fw;
+ const struct firmware *fw = sdev->basefw.fw;
const struct sof_ext_man_elem_header *elem_hdr;
const struct sof_ext_man_header *head;
ssize_t ext_man_size;
@@ -149,6 +148,8 @@ static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev)
head = (struct sof_ext_man_header *)fw->data;
remaining = head->full_size - head->header_size;
+ if (remaining < 0 || remaining > sdev->basefw.fw->size)
+ return -EINVAL;
ext_man_size = ipc3_fw_ext_man_size(sdev, fw);
/* Assert firmware starts with extended manifest */
@@ -310,18 +311,18 @@ static int sof_ipc3_parse_module_memcpy(struct snd_sof_dev *sdev,
static int sof_ipc3_load_fw_to_dsp(struct snd_sof_dev *sdev)
{
- struct snd_sof_pdata *plat_data = sdev->pdata;
- const struct firmware *fw = plat_data->fw;
+ u32 payload_offset = sdev->basefw.payload_offset;
+ const struct firmware *fw = sdev->basefw.fw;
struct snd_sof_fw_header *header;
struct snd_sof_mod_hdr *module;
int (*load_module)(struct snd_sof_dev *sof_dev, struct snd_sof_mod_hdr *hdr);
size_t remaining;
int ret, count;
- if (!plat_data->fw)
+ if (!fw)
return -EINVAL;
- header = (struct snd_sof_fw_header *)(fw->data + plat_data->fw_offset);
+ header = (struct snd_sof_fw_header *)(fw->data + payload_offset);
load_module = sof_ops(sdev)->load_module;
if (!load_module) {
dev_dbg(sdev->dev, "Using generic module loading\n");
@@ -331,9 +332,8 @@ static int sof_ipc3_load_fw_to_dsp(struct snd_sof_dev *sdev)
}
/* parse each module */
- module = (struct snd_sof_mod_hdr *)(fw->data + plat_data->fw_offset +
- sizeof(*header));
- remaining = fw->size - sizeof(*header) - plat_data->fw_offset;
+ module = (struct snd_sof_mod_hdr *)(fw->data + payload_offset + sizeof(*header));
+ remaining = fw->size - sizeof(*header) - payload_offset;
/* check for wrap */
if (remaining > fw->size) {
dev_err(sdev->dev, "%s: fw size smaller than header size\n", __func__);
@@ -374,19 +374,19 @@ static int sof_ipc3_load_fw_to_dsp(struct snd_sof_dev *sdev)
static int sof_ipc3_validate_firmware(struct snd_sof_dev *sdev)
{
- struct snd_sof_pdata *plat_data = sdev->pdata;
- const struct firmware *fw = plat_data->fw;
+ u32 payload_offset = sdev->basefw.payload_offset;
+ const struct firmware *fw = sdev->basefw.fw;
struct snd_sof_fw_header *header;
- size_t fw_size = fw->size - plat_data->fw_offset;
+ size_t fw_size = fw->size - payload_offset;
- if (fw->size <= plat_data->fw_offset) {
+ if (fw->size <= payload_offset) {
dev_err(sdev->dev,
"firmware size must be greater than firmware offset\n");
return -EINVAL;
}
/* Read the header information from the data pointer */
- header = (struct snd_sof_fw_header *)(fw->data + plat_data->fw_offset);
+ header = (struct snd_sof_fw_header *)(fw->data + payload_offset);
/* verify FW sig */
if (strncmp(header->sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE) != 0) {
diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c
index e635ae515..9f433e9b4 100644
--- a/sound/soc/sof/ipc4-loader.c
+++ b/sound/soc/sof/ipc4-loader.c
@@ -17,9 +17,8 @@
static size_t sof_ipc4_fw_parse_ext_man(struct snd_sof_dev *sdev)
{
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
- struct snd_sof_pdata *plat_data = sdev->pdata;
struct sof_man4_fw_binary_header *fw_header;
- const struct firmware *fw = plat_data->fw;
+ const struct firmware *fw = sdev->basefw.fw;
struct sof_ext_manifest4_hdr *ext_man_hdr;
struct sof_man4_module_config *fm_config;
struct sof_ipc4_fw_module *fw_module;
@@ -138,9 +137,8 @@ static int sof_ipc4_validate_firmware(struct snd_sof_dev *sdev)
{
struct sof_ipc4_fw_data *ipc4_data = sdev->private;
u32 fw_hdr_offset = ipc4_data->manifest_fw_hdr_offset;
- struct snd_sof_pdata *plat_data = sdev->pdata;
struct sof_man4_fw_binary_header *fw_header;
- const struct firmware *fw = plat_data->fw;
+ const struct firmware *fw = sdev->basefw.fw;
struct sof_ext_manifest4_hdr *ext_man_hdr;
ext_man_hdr = (struct sof_ext_manifest4_hdr *)fw->data;
diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c
index 5f51d936b..ba8e3aae0 100644
--- a/sound/soc/sof/loader.c
+++ b/sound/soc/sof/loader.c
@@ -22,7 +22,7 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev)
int ret;
/* Don't request firmware again if firmware is already requested */
- if (plat_data->fw)
+ if (sdev->basefw.fw)
return 0;
fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
@@ -31,7 +31,7 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev)
if (!fw_filename)
return -ENOMEM;
- ret = request_firmware(&plat_data->fw, fw_filename, sdev->dev);
+ ret = request_firmware(&sdev->basefw.fw, fw_filename, sdev->dev);
if (ret < 0) {
dev_err(sdev->dev,
@@ -48,7 +48,7 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev)
ext_man_size = sdev->ipc->ops->fw_loader->parse_ext_manifest(sdev);
if (ext_man_size > 0) {
/* when no error occurred, drop extended manifest */
- plat_data->fw_offset = ext_man_size;
+ sdev->basefw.payload_offset = ext_man_size;
} else if (!ext_man_size) {
/* No extended manifest, so nothing to skip during FW load */
dev_dbg(sdev->dev, "firmware doesn't contain extended manifest\n");
@@ -58,6 +58,12 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev)
fw_filename, ret);
}
+ /*
+ * Until the platform code is switched to use the new container the fw
+ * and payload offset must be set in plat_data
+ */
+ plat_data->fw = sdev->basefw.fw;
+ plat_data->fw_offset = sdev->basefw.payload_offset;
err:
kfree(fw_filename);
@@ -100,7 +106,8 @@ int snd_sof_load_firmware_memcpy(struct snd_sof_dev *sdev)
return 0;
error:
- release_firmware(plat_data->fw);
+ release_firmware(sdev->basefw.fw);
+ sdev->basefw.fw = NULL;
plat_data->fw = NULL;
return ret;
@@ -185,7 +192,8 @@ EXPORT_SYMBOL(snd_sof_run_firmware);
void snd_sof_fw_unload(struct snd_sof_dev *sdev)
{
/* TODO: support module unloading at runtime */
- release_firmware(sdev->pdata->fw);
+ release_firmware(sdev->basefw.fw);
+ sdev->basefw.fw = NULL;
sdev->pdata->fw = NULL;
}
EXPORT_SYMBOL(snd_sof_fw_unload);
diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
index de0882591..3d70b57e4 100644
--- a/sound/soc/sof/sof-priv.h
+++ b/sound/soc/sof/sof-priv.h
@@ -136,6 +136,17 @@ struct snd_sof_platform_stream_params {
bool cont_update_posn;
};
+/**
+ * struct sof_firmware - Container struct for SOF firmware
+ * @fw: Pointer to the firmware
+ * @payload_offset: Offset of the data within the loaded firmware image to be
+ * loaded to the DSP (skipping for example ext_manifest section)
+ */
+struct sof_firmware {
+ const struct firmware *fw;
+ u32 payload_offset;
+};
+
/*
* SOF DSP HW abstraction operations.
* Used to abstract DSP HW architecture and any IO busses between host CPU
@@ -487,6 +498,9 @@ struct snd_sof_dev {
spinlock_t ipc_lock; /* lock for IPC users */
spinlock_t hw_lock; /* lock for HW IO access */
+ /* Main, Base firmware image */
+ struct sof_firmware basefw;
+
/*
* ASoC components. plat_drv fields are set dynamically so
* can't use const