Commit 220c8f67 authored by Takashi Iwai's avatar Takashi Iwai

Merge tag 'asoc-fix-v6.5-rc6' of...

Merge tag 'asoc-fix-v6.5-rc6' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v6.5

A fairly large collection of fixes here, mostly SOF and Intel related.
The one core fix is Hans' change which reduces the log spam when working
out new use cases for DPCM.
parents 7c761166 37aba319
...@@ -185,10 +185,10 @@ static int max98363_io_init(struct sdw_slave *slave) ...@@ -185,10 +185,10 @@ static int max98363_io_init(struct sdw_slave *slave)
pm_runtime_get_noresume(dev); pm_runtime_get_noresume(dev);
ret = regmap_read(max98363->regmap, MAX98363_R21FF_REV_ID, &reg); ret = regmap_read(max98363->regmap, MAX98363_R21FF_REV_ID, &reg);
if (!ret) { if (!ret)
dev_info(dev, "Revision ID: %X\n", reg); dev_info(dev, "Revision ID: %X\n", reg);
return ret; else
} goto out;
if (max98363->first_hw_init) { if (max98363->first_hw_init) {
regcache_cache_bypass(max98363->regmap, false); regcache_cache_bypass(max98363->regmap, false);
...@@ -198,10 +198,11 @@ static int max98363_io_init(struct sdw_slave *slave) ...@@ -198,10 +198,11 @@ static int max98363_io_init(struct sdw_slave *slave)
max98363->first_hw_init = true; max98363->first_hw_init = true;
max98363->hw_init = true; max98363->hw_init = true;
out:
pm_runtime_mark_last_busy(dev); pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev); pm_runtime_put_autosuspend(dev);
return 0; return ret;
} }
#define MAX98363_RATES SNDRV_PCM_RATE_8000_192000 #define MAX98363_RATES SNDRV_PCM_RATE_8000_192000
......
...@@ -52,6 +52,7 @@ static bool rt1308_volatile_register(struct device *dev, unsigned int reg) ...@@ -52,6 +52,7 @@ static bool rt1308_volatile_register(struct device *dev, unsigned int reg)
case 0x300a: case 0x300a:
case 0xc000: case 0xc000:
case 0xc710: case 0xc710:
case 0xcf01:
case 0xc860 ... 0xc863: case 0xc860 ... 0xc863:
case 0xc870 ... 0xc873: case 0xc870 ... 0xc873:
return true; return true;
...@@ -213,7 +214,7 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave) ...@@ -213,7 +214,7 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave)
{ {
struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev); struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
unsigned int tmp; unsigned int tmp, hibernation_flag;
if (rt1308->hw_init) if (rt1308->hw_init)
return 0; return 0;
...@@ -242,6 +243,10 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave) ...@@ -242,6 +243,10 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave)
pm_runtime_get_noresume(&slave->dev); pm_runtime_get_noresume(&slave->dev);
regmap_read(rt1308->regmap, 0xcf01, &hibernation_flag);
if ((hibernation_flag != 0x00) && rt1308->first_hw_init)
goto _preset_ready_;
/* sw reset */ /* sw reset */
regmap_write(rt1308->regmap, RT1308_SDW_RESET, 0); regmap_write(rt1308->regmap, RT1308_SDW_RESET, 0);
...@@ -282,6 +287,12 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave) ...@@ -282,6 +287,12 @@ static int rt1308_io_init(struct device *dev, struct sdw_slave *slave)
regmap_write(rt1308->regmap, 0xc100, 0xd7); regmap_write(rt1308->regmap, 0xc100, 0xd7);
regmap_write(rt1308->regmap, 0xc101, 0xd7); regmap_write(rt1308->regmap, 0xc101, 0xd7);
/* apply BQ params */
rt1308_apply_bq_params(rt1308);
regmap_write(rt1308->regmap, 0xcf01, 0x01);
_preset_ready_:
if (rt1308->first_hw_init) { if (rt1308->first_hw_init) {
regcache_cache_bypass(rt1308->regmap, false); regcache_cache_bypass(rt1308->regmap, false);
regcache_mark_dirty(rt1308->regmap); regcache_mark_dirty(rt1308->regmap);
......
...@@ -4472,6 +4472,8 @@ static void rt5665_remove(struct snd_soc_component *component) ...@@ -4472,6 +4472,8 @@ static void rt5665_remove(struct snd_soc_component *component)
struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component); struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component);
regmap_write(rt5665->regmap, RT5665_RESET, 0); regmap_write(rt5665->regmap, RT5665_RESET, 0);
regulator_bulk_disable(ARRAY_SIZE(rt5665->supplies), rt5665->supplies);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -476,7 +476,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { ...@@ -476,7 +476,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"), DMI_MATCH(DMI_PRODUCT_NAME, "Lunar Lake Client Platform"),
}, },
.driver_data = (void *)(RT711_JD2_100K), .driver_data = (void *)(RT711_JD2),
}, },
{} {}
}; };
......
...@@ -99,9 +99,9 @@ static int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd) ...@@ -99,9 +99,9 @@ static int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd)
jack = &ctx->sdw_headset; jack = &ctx->sdw_headset;
snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
ret = snd_soc_component_set_jack(component, jack, NULL); ret = snd_soc_component_set_jack(component, jack, NULL);
......
...@@ -30,27 +30,32 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map, ...@@ -30,27 +30,32 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map,
struct axg_tdm_stream *ts, struct axg_tdm_stream *ts,
unsigned int offset) unsigned int offset)
{ {
unsigned int val, ch = ts->channels; unsigned int ch = ts->channels;
unsigned long mask; u32 val[AXG_TDM_NUM_LANES];
int i, j; int i, j, k;
/*
* We need to mimick the slot distribution used by the HW to keep the
* channel placement consistent regardless of the number of channel
* in the stream. This is why the odd algorithm below is used.
*/
memset(val, 0, sizeof(*val) * AXG_TDM_NUM_LANES);
/* /*
* Distribute the channels of the stream over the available slots * Distribute the channels of the stream over the available slots
* of each TDM lane * of each TDM lane. We need to go over the 32 slots ...
*/ */
for (i = 0; i < AXG_TDM_NUM_LANES; i++) { for (i = 0; (i < 32) && ch; i += 2) {
val = 0; /* ... of all the lanes ... */
mask = ts->mask[i]; for (j = 0; j < AXG_TDM_NUM_LANES; j++) {
/* ... then distribute the channels in pairs */
for (j = find_first_bit(&mask, 32); for (k = 0; k < 2; k++) {
(j < 32) && ch; if ((BIT(i + k) & ts->mask[j]) && ch) {
j = find_next_bit(&mask, 32, j + 1)) { val[j] |= BIT(i + k);
val |= 1 << j; ch -= 1;
ch -= 1; }
}
} }
regmap_write(map, offset, val);
offset += regmap_get_reg_stride(map);
} }
/* /*
...@@ -63,6 +68,11 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map, ...@@ -63,6 +68,11 @@ int axg_tdm_formatter_set_channel_masks(struct regmap *map,
return -EINVAL; return -EINVAL;
} }
for (i = 0; i < AXG_TDM_NUM_LANES; i++) {
regmap_write(map, offset, val[i]);
offset += regmap_get_reg_stride(map);
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks); EXPORT_SYMBOL_GPL(axg_tdm_formatter_set_channel_masks);
......
...@@ -38,6 +38,7 @@ static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd, ...@@ -38,6 +38,7 @@ static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd,
switch (ret) { switch (ret) {
case -EPROBE_DEFER: case -EPROBE_DEFER:
case -ENOTSUPP: case -ENOTSUPP:
case -EINVAL:
break; break;
default: default:
dev_err(rtd->dev, dev_err(rtd->dev,
...@@ -2466,8 +2467,11 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) ...@@ -2466,8 +2467,11 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
/* there is no point preparing this FE if there are no BEs */ /* there is no point preparing this FE if there are no BEs */
if (list_empty(&fe->dpcm[stream].be_clients)) { if (list_empty(&fe->dpcm[stream].be_clients)) {
dev_err(fe->dev, "ASoC: no backend DAIs enabled for %s\n", /* dev_err_once() for visibility, dev_dbg() for debugging UCM profiles */
fe->dai_link->name); dev_err_once(fe->dev, "ASoC: no backend DAIs enabled for %s, possibly missing ALSA mixer-based routing or UCM profile\n",
fe->dai_link->name);
dev_dbg(fe->dev, "ASoC: no backend DAIs enabled for %s\n",
fe->dai_link->name);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
......
...@@ -372,6 +372,7 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = { ...@@ -372,6 +372,7 @@ static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = {
static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream, int cmd) struct snd_pcm_substream *substream, int cmd)
{ {
struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
switch (cmd) { switch (cmd) {
...@@ -379,9 +380,17 @@ static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c ...@@ -379,9 +380,17 @@ static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
{ {
struct snd_sof_dai_config_data data = { 0 }; struct snd_sof_dai_config_data data = { 0 };
int ret;
data.dai_data = DMA_CHAN_INVALID; data.dai_data = DMA_CHAN_INVALID;
return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data);
if (ret < 0)
return ret;
if (cmd == SNDRV_PCM_TRIGGER_STOP)
return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
break;
} }
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL);
......
...@@ -107,9 +107,8 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai ...@@ -107,9 +107,8 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai
return sdai->platform_private; return sdai->platform_private;
} }
static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream,
struct hdac_ext_stream *hext_stream, struct snd_soc_dai *cpu_dai)
struct snd_soc_dai *cpu_dai)
{ {
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
struct sof_intel_hda_stream *hda_stream; struct sof_intel_hda_stream *hda_stream;
......
...@@ -963,5 +963,7 @@ const struct hda_dai_widget_dma_ops * ...@@ -963,5 +963,7 @@ const struct hda_dai_widget_dma_ops *
hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
struct snd_sof_dai_config_data *data); struct snd_sof_dai_config_data *data);
int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream,
struct snd_soc_dai *cpu_dai);
#endif #endif
...@@ -1001,7 +1001,7 @@ void sof_ipc3_do_rx_work(struct snd_sof_dev *sdev, struct sof_ipc_cmd_hdr *hdr, ...@@ -1001,7 +1001,7 @@ void sof_ipc3_do_rx_work(struct snd_sof_dev *sdev, struct sof_ipc_cmd_hdr *hdr,
ipc3_log_header(sdev->dev, "ipc rx", hdr->cmd); ipc3_log_header(sdev->dev, "ipc rx", hdr->cmd);
if (hdr->size < sizeof(hdr) || hdr->size > SOF_IPC_MSG_MAX_SIZE) { if (hdr->size < sizeof(*hdr) || hdr->size > SOF_IPC_MSG_MAX_SIZE) {
dev_err(sdev->dev, "The received message size is invalid: %u\n", dev_err(sdev->dev, "The received message size is invalid: %u\n",
hdr->size); hdr->size);
return; return;
......
...@@ -1731,6 +1731,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, ...@@ -1731,6 +1731,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
*ipc_config_size = ipc_size; *ipc_config_size = ipc_size;
/* update pipeline memory usage */
sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config);
/* copy IPC data */ /* copy IPC data */
memcpy(*ipc_config_data, (void *)copier_data, sizeof(*copier_data)); memcpy(*ipc_config_data, (void *)copier_data, sizeof(*copier_data));
if (gtw_cfg_config_length) if (gtw_cfg_config_length)
...@@ -1743,9 +1746,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, ...@@ -1743,9 +1746,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
gtw_cfg_config_length, gtw_cfg_config_length,
&ipc4_copier->dma_config_tlv, dma_config_tlv_size); &ipc4_copier->dma_config_tlv, dma_config_tlv_size);
/* update pipeline memory usage */
sof_ipc4_update_resource_usage(sdev, swidget, &copier_data->base_config);
return 0; return 0;
} }
......
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