ASoC: Fixes for v5.16

A relatively large collection of updates, the size is increased quite a
 bit by there being some repetitive changes for similar issues that occur
 multiple times with both notifying control value changes and runtime PM.
 
 The Rockchip update looks at first glance like a cleanup but fixes
 instantiation of the hardware on some systems.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmGuLfMACgkQJNaLcl1U
 h9DMbwf/aewIYwfyThs2O5W8Hhn/fxhr8qV6+k08W4dQDjFstUU3meJ9lsWNhb7W
 E2OkuZ7vpvIn3I4Z/1ffNTgvVYafwqg/PVnuUiYtEHr46J6kXZkiUta/e4hZzugb
 J+CGDf5c8Dy7bev26JAKRLxOoU3NlsS3ed5iV2NGZt0zf77og759NJf5fSnsebXw
 ycio8Tnjx15weS0ipl5nXQ74JMQvV5J+6SWQ0favxX2RpGSSekkj7tg5Jsuwx8R0
 nRiBrPHelVJqk5THyyiWe7pImeF2QtTcAWqz8IUR7OfWjBpPlTW6n5VVzKhbuLEr
 Qws4epxVeyeV4mbks9K2R9VryYFT5Q==
 =ufLK
 -----END PGP SIGNATURE-----

Merge tag 'asoc-fix-v5.16-rc4' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v5.16

A relatively large collection of updates, the size is increased quite a
bit by there being some repetitive changes for similar issues that occur
multiple times with both notifying control value changes and runtime PM.

The Rockchip update looks at first glance like a cleanup but fixes
instantiation of the hardware on some systems.
This commit is contained in:
Takashi Iwai 2021-12-06 17:25:10 +01:00
commit 38ddfb2699
14 changed files with 179 additions and 87 deletions

View File

@ -19,6 +19,9 @@ properties:
clocks:
maxItems: 1
interrupts:
maxItems: 1
"#sound-dai-cells":
const: 0

View File

@ -146,10 +146,11 @@ static int snd_acp6x_probe(struct pci_dev *pci,
{
struct acp6x_dev_data *adata;
struct platform_device_info pdevinfo[ACP6x_DEVS];
int ret, index;
int index = 0;
int val = 0x00;
u32 addr;
unsigned int irqflags;
int ret;
irqflags = IRQF_SHARED;
/* Yellow Carp device check */

View File

@ -2858,6 +2858,8 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682)
for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) {
struct clk_init_data init = { };
struct clk_parent_data parent_data;
const struct clk_hw *parent;
dai_clk_hw = &rt5682->dai_clks_hw[i];
@ -2865,17 +2867,17 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682)
case RT5682_DAI_WCLK_IDX:
/* Make MCLK the parent of WCLK */
if (rt5682->mclk) {
init.parent_data = &(struct clk_parent_data){
parent_data = (struct clk_parent_data){
.fw_name = "mclk",
};
init.parent_data = &parent_data;
init.num_parents = 1;
}
break;
case RT5682_DAI_BCLK_IDX:
/* Make WCLK the parent of BCLK */
init.parent_hws = &(const struct clk_hw *){
&rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX]
};
parent = &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX];
init.parent_hws = &parent;
init.num_parents = 1;
break;
default:

View File

@ -2693,6 +2693,8 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component)
for (i = 0; i < RT5682S_DAI_NUM_CLKS; ++i) {
struct clk_init_data init = { };
struct clk_parent_data parent_data;
const struct clk_hw *parent;
dai_clk_hw = &rt5682s->dai_clks_hw[i];
@ -2700,17 +2702,17 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component)
case RT5682S_DAI_WCLK_IDX:
/* Make MCLK the parent of WCLK */
if (rt5682s->mclk) {
init.parent_data = &(struct clk_parent_data){
parent_data = (struct clk_parent_data){
.fw_name = "mclk",
};
init.parent_data = &parent_data;
init.num_parents = 1;
}
break;
case RT5682S_DAI_BCLK_IDX:
/* Make WCLK the parent of BCLK */
init.parent_hws = &(const struct clk_hw *){
&rt5682s->dai_clks_hw[RT5682S_DAI_WCLK_IDX]
};
parent = &rt5682s->dai_clks_hw[RT5682S_DAI_WCLK_IDX];
init.parent_hws = &parent;
init.num_parents = 1;
break;
default:

View File

@ -3256,6 +3256,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,
int value = ucontrol->value.integer.value[0];
int sel;
if (wcd->comp_enabled[comp] == value)
return 0;
wcd->comp_enabled[comp] = value;
sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER :
WCD934X_HPH_GAIN_SRC_SEL_REGISTER;
@ -3279,10 +3282,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc,
case COMPANDER_8:
break;
default:
break;
return 0;
}
return 0;
return 1;
}
static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc,
@ -3326,6 +3329,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc,
return 0;
}
static int slim_rx_mux_to_dai_id(int mux)
{
int aif_id;
switch (mux) {
case 1:
aif_id = AIF1_PB;
break;
case 2:
aif_id = AIF2_PB;
break;
case 3:
aif_id = AIF3_PB;
break;
case 4:
aif_id = AIF4_PB;
break;
default:
aif_id = -1;
break;
}
return aif_id;
}
static int slim_rx_mux_put(struct snd_kcontrol *kc,
struct snd_ctl_elem_value *ucontrol)
{
@ -3333,43 +3361,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc,
struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev);
struct soc_enum *e = (struct soc_enum *)kc->private_value;
struct snd_soc_dapm_update *update = NULL;
struct wcd934x_slim_ch *ch, *c;
u32 port_id = w->shift;
bool found = false;
int mux_idx;
int prev_mux_idx = wcd->rx_port_value[port_id];
int aif_id;
if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0])
mux_idx = ucontrol->value.enumerated.item[0];
if (mux_idx == prev_mux_idx)
return 0;
wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
switch (wcd->rx_port_value[port_id]) {
switch(mux_idx) {
case 0:
list_del_init(&wcd->rx_chs[port_id].list);
aif_id = slim_rx_mux_to_dai_id(prev_mux_idx);
if (aif_id < 0)
return 0;
list_for_each_entry_safe(ch, c, &wcd->dai[aif_id].slim_ch_list, list) {
if (ch->port == port_id + WCD934X_RX_START) {
found = true;
list_del_init(&ch->list);
break;
}
}
if (!found)
return 0;
break;
case 1:
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[AIF1_PB].slim_ch_list);
break;
case 2:
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[AIF2_PB].slim_ch_list);
break;
case 3:
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[AIF3_PB].slim_ch_list);
break;
case 4:
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[AIF4_PB].slim_ch_list);
case 1 ... 4:
aif_id = slim_rx_mux_to_dai_id(mux_idx);
if (aif_id < 0)
return 0;
if (list_empty(&wcd->rx_chs[port_id].list)) {
list_add_tail(&wcd->rx_chs[port_id].list,
&wcd->dai[aif_id].slim_ch_list);
} else {
dev_err(wcd->dev ,"SLIM_RX%d PORT is busy\n", port_id);
return 0;
}
break;
default:
dev_err(wcd->dev, "Unknown AIF %d\n",
wcd->rx_port_value[port_id]);
dev_err(wcd->dev, "Unknown AIF %d\n", mux_idx);
goto err;
}
wcd->rx_port_value[port_id] = mux_idx;
snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id],
e, update);
return 0;
return 1;
err:
return -EINVAL;
}
@ -3815,6 +3859,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,
struct soc_mixer_control *mixer =
(struct soc_mixer_control *)kc->private_value;
int enable = ucontrol->value.integer.value[0];
struct wcd934x_slim_ch *ch, *c;
int dai_id = widget->shift;
int port_id = mixer->shift;
@ -3822,17 +3867,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc,
if (enable == wcd->tx_port_value[port_id])
return 0;
if (enable) {
if (list_empty(&wcd->tx_chs[port_id].list)) {
list_add_tail(&wcd->tx_chs[port_id].list,
&wcd->dai[dai_id].slim_ch_list);
} else {
dev_err(wcd->dev ,"SLIM_TX%d PORT is busy\n", port_id);
return 0;
}
} else {
bool found = false;
list_for_each_entry_safe(ch, c, &wcd->dai[dai_id].slim_ch_list, list) {
if (ch->port == port_id) {
found = true;
list_del_init(&wcd->tx_chs[port_id].list);
break;
}
}
if (!found)
return 0;
}
wcd->tx_port_value[port_id] = enable;
if (enable)
list_add_tail(&wcd->tx_chs[port_id].list,
&wcd->dai[dai_id].slim_ch_list);
else
list_del_init(&wcd->tx_chs[port_id].list);
snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update);
return 0;
return 1;
}
static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = {

View File

@ -772,7 +772,8 @@ static int wsa881x_put_pa_gain(struct snd_kcontrol *kc,
usleep_range(1000, 1010);
}
return 0;
return 1;
}
static int wsa881x_get_port(struct snd_kcontrol *kcontrol,
@ -816,15 +817,22 @@ static int wsa881x_set_port(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
int portidx = mixer->reg;
if (ucontrol->value.integer.value[0])
if (ucontrol->value.integer.value[0]) {
if (data->port_enable[portidx])
return 0;
data->port_enable[portidx] = true;
else
} else {
if (!data->port_enable[portidx])
return 0;
data->port_enable[portidx] = false;
}
if (portidx == WSA881X_PORT_BOOST) /* Boost Switch */
wsa881x_boost_ctrl(comp, data->port_enable[portidx]);
return 0;
return 1;
}
static const char * const smart_boost_lvl_text[] = {

View File

@ -498,14 +498,16 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
struct session_data *session = &data->sessions[session_id];
if (ucontrol->value.integer.value[0]) {
if (session->port_id == be_id)
return 0;
session->port_id = be_id;
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update);
} else {
if (session->port_id == be_id) {
session->port_id = -1;
if (session->port_id == -1 || session->port_id != be_id)
return 0;
}
session->port_id = -1;
snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update);
}

View File

@ -95,6 +95,7 @@ struct rk_i2s_tdm_dev {
spinlock_t lock; /* xfer lock */
bool has_playback;
bool has_capture;
struct snd_soc_dai_driver *dai;
};
static int to_ch_num(unsigned int val)
@ -1310,19 +1311,14 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = {
{},
};
static struct snd_soc_dai_driver i2s_tdm_dai = {
static const struct snd_soc_dai_driver i2s_tdm_dai = {
.probe = rockchip_i2s_tdm_dai_probe,
.playback = {
.stream_name = "Playback",
},
.capture = {
.stream_name = "Capture",
},
.ops = &rockchip_i2s_tdm_dai_ops,
};
static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
{
struct snd_soc_dai_driver *dai;
struct property *dma_names;
const char *dma_name;
u64 formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
@ -1337,19 +1333,33 @@ static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm)
i2s_tdm->has_capture = true;
}
dai = devm_kmemdup(i2s_tdm->dev, &i2s_tdm_dai,
sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
if (i2s_tdm->has_playback) {
i2s_tdm_dai.playback.channels_min = 2;
i2s_tdm_dai.playback.channels_max = 8;
i2s_tdm_dai.playback.rates = SNDRV_PCM_RATE_8000_192000;
i2s_tdm_dai.playback.formats = formats;
dai->playback.stream_name = "Playback";
dai->playback.channels_min = 2;
dai->playback.channels_max = 8;
dai->playback.rates = SNDRV_PCM_RATE_8000_192000;
dai->playback.formats = formats;
}
if (i2s_tdm->has_capture) {
i2s_tdm_dai.capture.channels_min = 2;
i2s_tdm_dai.capture.channels_max = 8;
i2s_tdm_dai.capture.rates = SNDRV_PCM_RATE_8000_192000;
i2s_tdm_dai.capture.formats = formats;
dai->capture.stream_name = "Capture";
dai->capture.channels_min = 2;
dai->capture.channels_max = 8;
dai->capture.rates = SNDRV_PCM_RATE_8000_192000;
dai->capture.formats = formats;
}
if (i2s_tdm->clk_trcm != TRCM_TXRX)
dai->symmetric_rate = 1;
i2s_tdm->dai = dai;
return 0;
}
static int rockchip_i2s_tdm_path_check(struct rk_i2s_tdm_dev *i2s_tdm,
@ -1541,8 +1551,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
spin_lock_init(&i2s_tdm->lock);
i2s_tdm->soc_data = (struct rk_i2s_soc_data *)of_id->data;
rockchip_i2s_tdm_init_dai(i2s_tdm);
i2s_tdm->frame_width = 64;
i2s_tdm->clk_trcm = TRCM_TXRX;
@ -1555,8 +1563,10 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
}
i2s_tdm->clk_trcm = TRCM_RX;
}
if (i2s_tdm->clk_trcm != TRCM_TXRX)
i2s_tdm_dai.symmetric_rate = 1;
ret = rockchip_i2s_tdm_init_dai(i2s_tdm);
if (ret)
return ret;
i2s_tdm->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
if (IS_ERR(i2s_tdm->grf))
@ -1678,7 +1688,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_component(&pdev->dev,
&rockchip_i2s_tdm_component,
&i2s_tdm_dai, 1);
i2s_tdm->dai, 1);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI\n");

View File

@ -22,6 +22,7 @@
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
#define IDISP_VID_INTEL 0x80860000
#define CODEC_PROBE_RETRIES 3
/* load the legacy HDA codec driver */
static int request_codec_module(struct hda_codec *codec)
@ -121,12 +122,15 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) |
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
u32 resp = -1;
int ret;
int ret, retry = 0;
do {
mutex_lock(&hbus->core.cmd_mutex);
snd_hdac_bus_send_cmd(&hbus->core, hda_cmd);
snd_hdac_bus_get_response(&hbus->core, address, &resp);
mutex_unlock(&hbus->core.cmd_mutex);
} while (resp == -1 && retry++ < CODEC_PROBE_RETRIES);
mutex_lock(&hbus->core.cmd_mutex);
snd_hdac_bus_send_cmd(&hbus->core, hda_cmd);
snd_hdac_bus_get_response(&hbus->core, address, &resp);
mutex_unlock(&hbus->core.cmd_mutex);
if (resp == -1)
return -EIO;
dev_dbg(sdev->dev, "HDA codec #%d probed OK: response: %x\n",

View File

@ -514,8 +514,8 @@ static int tegra210_adx_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_adx_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
tegra210_adx_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_adx_driver = {

View File

@ -583,8 +583,8 @@ static int tegra210_amx_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_amx_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend,
tegra210_amx_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_amx_driver = {

View File

@ -666,8 +666,8 @@ static int tegra210_mixer_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_mixer_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend,
tegra210_mixer_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_mixer_driver = {

View File

@ -164,7 +164,7 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol,
if (err < 0)
goto end;
return 1;
err = 1;
end:
pm_runtime_put(cmpnt->dev);
@ -236,7 +236,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
TEGRA210_MVC_VOLUME_SWITCH_MASK,
TEGRA210_MVC_VOLUME_SWITCH_TRIGGER);
return 1;
err = 1;
end:
pm_runtime_put(cmpnt->dev);
@ -639,8 +639,8 @@ static int tegra210_mvc_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_mvc_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend,
tegra210_mvc_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_mvc_driver = {

View File

@ -3594,8 +3594,8 @@ static int tegra210_sfc_platform_remove(struct platform_device *pdev)
static const struct dev_pm_ops tegra210_sfc_pm_ops = {
SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
tegra210_sfc_runtime_resume, NULL)
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static struct platform_driver tegra210_sfc_driver = {