ASoC: rockchip: Use guard() for spin locks

bui duc phuc <phucduc.bui@gmail.com> says:

This series converts spinlock handling in the Rockchip sound drivers
to use guard() helpers.
The changes are code cleanup only and should have no functional impact.

Link: https://patch.msgid.link/20260604033554.96996-1-phucduc.bui@gmail.com
This commit is contained in:
Mark Brown 2026-06-11 20:50:31 +01:00
commit 5542791d50
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
3 changed files with 217 additions and 225 deletions

View File

@ -127,52 +127,52 @@ static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
unsigned int val = 0;
int ret = 0;
spin_lock(&i2s->lock);
if (on) {
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE,
I2S_DMACR_TDE_ENABLE);
if (ret < 0)
goto end;
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
I2S_XFER_TXS_START | I2S_XFER_RXS_START);
if (ret < 0)
goto end;
i2s->tx_start = true;
} else {
i2s->tx_start = false;
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE,
I2S_DMACR_TDE_DISABLE);
if (ret < 0)
goto end;
if (!i2s->rx_start) {
scoped_guard(spinlock, &i2s->lock) {
if (on) {
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE,
I2S_DMACR_TDE_ENABLE);
if (ret < 0)
break;
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
I2S_XFER_TXS_START | I2S_XFER_RXS_START);
if (ret < 0)
goto end;
udelay(150);
ret = regmap_update_bits(i2s->regmap, I2S_CLR,
I2S_CLR_TXC | I2S_CLR_RXC,
break;
i2s->tx_start = true;
} else {
i2s->tx_start = false;
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE,
I2S_DMACR_TDE_DISABLE);
if (ret < 0)
break;
if (!i2s->rx_start) {
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
if (ret < 0)
break;
udelay(150);
ret = regmap_update_bits(i2s->regmap, I2S_CLR,
I2S_CLR_TXC | I2S_CLR_RXC,
I2S_CLR_TXC | I2S_CLR_RXC);
if (ret < 0)
goto end;
ret = regmap_read_poll_timeout_atomic(i2s->regmap,
I2S_CLR,
val,
val == 0,
20,
200);
if (ret < 0)
dev_warn(i2s->dev, "fail to clear: %d\n", ret);
if (ret < 0)
break;
ret = regmap_read_poll_timeout_atomic(i2s->regmap,
I2S_CLR,
val,
val == 0,
20,
200);
if (ret < 0)
dev_warn(i2s->dev, "fail to clear: %d\n", ret);
}
}
}
end:
spin_unlock(&i2s->lock);
if (ret < 0)
dev_err(i2s->dev, "lrclk update failed\n");
@ -184,53 +184,53 @@ static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
unsigned int val = 0;
int ret = 0;
spin_lock(&i2s->lock);
if (on) {
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE,
I2S_DMACR_RDE_ENABLE);
if (ret < 0)
goto end;
scoped_guard(spinlock, &i2s->lock) {
if (on) {
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE,
I2S_DMACR_RDE_ENABLE);
if (ret < 0)
break;
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
I2S_XFER_TXS_START | I2S_XFER_RXS_START);
if (ret < 0)
goto end;
i2s->rx_start = true;
} else {
i2s->rx_start = false;
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE,
I2S_DMACR_RDE_DISABLE);
if (ret < 0)
goto end;
if (!i2s->tx_start) {
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
I2S_XFER_TXS_START | I2S_XFER_RXS_START);
if (ret < 0)
goto end;
udelay(150);
ret = regmap_update_bits(i2s->regmap, I2S_CLR,
I2S_CLR_TXC | I2S_CLR_RXC,
I2S_CLR_TXC | I2S_CLR_RXC);
break;
i2s->rx_start = true;
} else {
i2s->rx_start = false;
ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE,
I2S_DMACR_RDE_DISABLE);
if (ret < 0)
goto end;
ret = regmap_read_poll_timeout_atomic(i2s->regmap,
I2S_CLR,
val,
val == 0,
20,
200);
if (ret < 0)
dev_warn(i2s->dev, "fail to clear: %d\n", ret);
break;
if (!i2s->tx_start) {
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
if (ret < 0)
break;
udelay(150);
ret = regmap_update_bits(i2s->regmap, I2S_CLR,
I2S_CLR_TXC | I2S_CLR_RXC,
I2S_CLR_TXC | I2S_CLR_RXC);
if (ret < 0)
break;
ret = regmap_read_poll_timeout_atomic(i2s->regmap,
I2S_CLR,
val,
val == 0,
20,
200);
if (ret < 0)
dev_warn(i2s->dev, "fail to clear: %d\n", ret);
}
}
}
end:
spin_unlock(&i2s->lock);
if (ret < 0)
dev_err(i2s->dev, "lrclk update failed\n");

View File

@ -285,9 +285,8 @@ static void rockchip_snd_txrxctrl(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai, int on)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
unsigned long flags;
spin_lock_irqsave(&i2s_tdm->lock, flags);
guard(spinlock_irqsave)(&i2s_tdm->lock);
if (on) {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
rockchip_enable_tde(i2s_tdm->regmap);
@ -313,7 +312,6 @@ static void rockchip_snd_txrxctrl(struct snd_pcm_substream *substream,
I2S_CLR_TXC | I2S_CLR_RXC);
}
}
spin_unlock_irqrestore(&i2s_tdm->lock, flags);
}
static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on)
@ -587,12 +585,11 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream,
unsigned int fmt)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
unsigned long flags;
if (!i2s_tdm->clk_trcm)
return 0;
spin_lock_irqsave(&i2s_tdm->lock, flags);
guard(spinlock_irqsave)(&i2s_tdm->lock);
if (i2s_tdm->refcount)
rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm);
@ -614,7 +611,6 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream,
if (i2s_tdm->refcount)
rockchip_i2s_tdm_xfer_resume(substream, i2s_tdm);
spin_unlock_irqrestore(&i2s_tdm->lock, flags);
return 0;
}

View File

@ -18,7 +18,6 @@
#include <sound/pcm_params.h>
#include <sound/dmaengine_pcm.h>
#include <sound/tlv.h>
#include "rockchip_sai.h"
#define DRV_NAME "rockchip-sai"
@ -216,14 +215,12 @@ static void rockchip_sai_xfer_clk_stop_and_wait(struct rk_sai_dev *sai, unsigned
static int rockchip_sai_runtime_suspend(struct device *dev)
{
struct rk_sai_dev *sai = dev_get_drvdata(dev);
unsigned long flags;
rockchip_sai_fsync_lost_detect(sai, 0);
rockchip_sai_fsync_err_detect(sai, 0);
spin_lock_irqsave(&sai->xfer_lock, flags);
rockchip_sai_xfer_clk_stop_and_wait(sai, NULL);
spin_unlock_irqrestore(&sai->xfer_lock, flags);
scoped_guard(spinlock_irqsave, &sai->xfer_lock)
rockchip_sai_xfer_clk_stop_and_wait(sai, NULL);
regcache_cache_only(sai->regmap, true);
/*
@ -483,7 +480,6 @@ static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
unsigned int mask = 0, val = 0;
unsigned int clk_gates;
unsigned long flags;
int ret = 0;
pm_runtime_get_sync(dai->dev);
@ -499,56 +495,56 @@ static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
sai->is_master_mode = false;
break;
default:
ret = -EINVAL;
goto err_pm_put;
pm_runtime_put(dai->dev);
return -EINVAL;
}
spin_lock_irqsave(&sai->xfer_lock, flags);
rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates);
if (sai->initialized) {
if (sai->has_capture && sai->has_playback)
rockchip_sai_xfer_stop(sai, -1);
else if (sai->has_capture)
rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_CAPTURE);
else
rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_PLAYBACK);
} else {
rockchip_sai_clear(sai, 0);
sai->initialized = true;
scoped_guard(spinlock_irqsave, &sai->xfer_lock) {
rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates);
if (sai->initialized) {
if (sai->has_capture && sai->has_playback)
rockchip_sai_xfer_stop(sai, -1);
else if (sai->has_capture)
rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_CAPTURE);
else
rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_PLAYBACK);
} else {
rockchip_sai_clear(sai, 0);
sai->initialized = true;
}
regmap_update_bits(sai->regmap, SAI_CKR, mask, val);
mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL;
break;
case SND_SOC_DAIFMT_NB_IF:
val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED;
break;
case SND_SOC_DAIFMT_IB_NF:
val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL;
break;
case SND_SOC_DAIFMT_IB_IF:
val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED;
break;
default:
ret = -EINVAL;
break;
}
if (ret == 0) {
regmap_update_bits(sai->regmap, SAI_CKR, mask, val);
rockchip_sai_fmt_create(sai, fmt);
}
if (clk_gates)
regmap_update_bits(sai->regmap, SAI_XFER,
SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK,
clk_gates);
}
regmap_update_bits(sai->regmap, SAI_CKR, mask, val);
mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL;
break;
case SND_SOC_DAIFMT_NB_IF:
val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED;
break;
case SND_SOC_DAIFMT_IB_NF:
val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL;
break;
case SND_SOC_DAIFMT_IB_IF:
val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED;
break;
default:
ret = -EINVAL;
goto err_xfer_unlock;
}
regmap_update_bits(sai->regmap, SAI_CKR, mask, val);
rockchip_sai_fmt_create(sai, fmt);
err_xfer_unlock:
if (clk_gates)
regmap_update_bits(sai->regmap, SAI_XFER,
SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK,
clk_gates);
spin_unlock_irqrestore(&sai->xfer_lock, flags);
err_pm_put:
pm_runtime_put(dai->dev);
return ret;
@ -564,7 +560,6 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream,
unsigned int ch_per_lane, slot_width;
unsigned int val, fscr, reg;
unsigned int lanes, req_lanes;
unsigned long flags;
int ret = 0;
if (!rockchip_sai_stream_valid(substream, dai))
@ -591,8 +586,8 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream,
dev_err(sai->dev, "not enough lanes (%d) for requested number of %s channels (%d)\n",
lanes, reg == SAI_TXCR ? "playback" : "capture",
params_channels(params));
ret = -EINVAL;
goto err_pm_put;
pm_runtime_put(sai->dev);
return -EINVAL;
} else {
lanes = req_lanes;
}
@ -618,84 +613,88 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream,
val = SAI_XCR_VDW(32);
break;
default:
ret = -EINVAL;
goto err_pm_put;
pm_runtime_put(sai->dev);
return -EINVAL;
}
val |= SAI_XCR_CSR(lanes);
spin_lock_irqsave(&sai->xfer_lock, flags);
scoped_guard(spinlock_irqsave, &sai->xfer_lock) {
regmap_update_bits(sai->regmap, reg, SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK, val);
regmap_update_bits(sai->regmap, reg, SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK, val);
if (!sai->is_tdm)
regmap_update_bits(sai->regmap, reg, SAI_XCR_SBW_MASK,
SAI_XCR_SBW(params_physical_width(params)));
if (!sai->is_tdm)
regmap_update_bits(sai->regmap, reg, SAI_XCR_SBW_MASK,
SAI_XCR_SBW(params_physical_width(params)));
regmap_read(sai->regmap, reg, &val);
regmap_read(sai->regmap, reg, &val);
slot_width = SAI_XCR_SBW_V(val);
ch_per_lane = params_channels(params) / lanes;
slot_width = SAI_XCR_SBW_V(val);
ch_per_lane = params_channels(params) / lanes;
regmap_update_bits(sai->regmap, reg, SAI_XCR_SNB_MASK,
SAI_XCR_SNB(ch_per_lane));
regmap_update_bits(sai->regmap, reg, SAI_XCR_SNB_MASK,
SAI_XCR_SNB(ch_per_lane));
fscr = SAI_FSCR_FW(sai->fw_ratio * slot_width * ch_per_lane);
fscr = SAI_FSCR_FW(sai->fw_ratio * slot_width * ch_per_lane);
switch (sai->fpw) {
case FPW_ONE_BCLK_WIDTH:
fscr |= SAI_FSCR_FPW(1);
break;
case FPW_ONE_SLOT_WIDTH:
fscr |= SAI_FSCR_FPW(slot_width);
break;
case FPW_HALF_FRAME_WIDTH:
fscr |= SAI_FSCR_FPW(sai->fw_ratio * slot_width * ch_per_lane / 2);
break;
default:
dev_err(sai->dev, "Invalid Frame Pulse Width %d\n", sai->fpw);
ret = -EINVAL;
goto err_xfer_unlock;
switch (sai->fpw) {
case FPW_ONE_BCLK_WIDTH:
fscr |= SAI_FSCR_FPW(1);
break;
case FPW_ONE_SLOT_WIDTH:
fscr |= SAI_FSCR_FPW(slot_width);
break;
case FPW_HALF_FRAME_WIDTH:
fscr |= SAI_FSCR_FPW(sai->fw_ratio * slot_width * ch_per_lane / 2);
break;
default:
dev_err(sai->dev, "Invalid Frame Pulse Width %d\n", sai->fpw);
ret = -EINVAL;
break;
}
if (ret == 0) {
regmap_update_bits(sai->regmap, SAI_FSCR,
SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK, fscr);
if (sai->is_master_mode) {
bclk_rate = sai->fw_ratio * slot_width *
ch_per_lane * params_rate(params);
ret = clk_set_rate(sai->mclk, sai->mclk_rate);
if (ret)
dev_err(sai->dev, "Failed to set mclk to %u: %pe\n",
sai->mclk_rate, ERR_PTR(ret));
else {
mclk_rate = clk_get_rate(sai->mclk);
if (mclk_rate < bclk_rate) {
dev_err(sai->dev, "Mismatch mclk: %u, at least %u\n",
mclk_rate, bclk_rate);
ret = -EINVAL;
} else {
div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
mclk_req_rate = bclk_rate * div_bclk;
if (mclk_rate <
mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX ||
mclk_rate >
mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX) {
dev_err(sai->dev,
"Mismatch mclk: %u, expected %u (+/- %dHz)\n",
mclk_rate, mclk_req_rate,
CLK_SHIFT_RATE_HZ_MAX);
ret = -EINVAL;
} else
regmap_update_bits(sai->regmap,
SAI_CKR,
SAI_CKR_MDIV_MASK,
SAI_CKR_MDIV(div_bclk));
}
}
}
}
}
regmap_update_bits(sai->regmap, SAI_FSCR,
SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK, fscr);
if (sai->is_master_mode) {
bclk_rate = sai->fw_ratio * slot_width * ch_per_lane * params_rate(params);
ret = clk_set_rate(sai->mclk, sai->mclk_rate);
if (ret) {
dev_err(sai->dev, "Failed to set mclk to %u: %pe\n",
sai->mclk_rate, ERR_PTR(ret));
goto err_xfer_unlock;
}
mclk_rate = clk_get_rate(sai->mclk);
if (mclk_rate < bclk_rate) {
dev_err(sai->dev, "Mismatch mclk: %u, at least %u\n",
mclk_rate, bclk_rate);
ret = -EINVAL;
goto err_xfer_unlock;
}
div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate);
mclk_req_rate = bclk_rate * div_bclk;
if (mclk_rate < mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX ||
mclk_rate > mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX) {
dev_err(sai->dev, "Mismatch mclk: %u, expected %u (+/- %dHz)\n",
mclk_rate, mclk_req_rate, CLK_SHIFT_RATE_HZ_MAX);
ret = -EINVAL;
goto err_xfer_unlock;
}
regmap_update_bits(sai->regmap, SAI_CKR, SAI_CKR_MDIV_MASK,
SAI_CKR_MDIV(div_bclk));
}
err_xfer_unlock:
spin_unlock_irqrestore(&sai->xfer_lock, flags);
err_pm_put:
pm_runtime_put(sai->dev);
return ret;
@ -705,7 +704,6 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
unsigned long flags;
if (!rockchip_sai_stream_valid(substream, dai))
return 0;
@ -726,13 +724,12 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream,
* udelay falls short.
*/
udelay(20);
spin_lock_irqsave(&sai->xfer_lock, flags);
regmap_update_bits(sai->regmap, SAI_XFER,
SAI_XFER_CLK_MASK |
SAI_XFER_FSS_MASK,
SAI_XFER_CLK_EN |
SAI_XFER_FSS_EN);
spin_unlock_irqrestore(&sai->xfer_lock, flags);
scoped_guard(spinlock_irqsave, &sai->xfer_lock)
regmap_update_bits(sai->regmap, SAI_XFER,
SAI_XFER_CLK_MASK |
SAI_XFER_FSS_MASK,
SAI_XFER_CLK_EN |
SAI_XFER_FSS_EN);
}
rockchip_sai_fsync_lost_detect(sai, 1);
@ -915,7 +912,6 @@ static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai,
int slots, int slot_width)
{
struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai);
unsigned long flags;
unsigned int clk_gates;
int sw = slot_width;
@ -931,16 +927,16 @@ static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai,
return -EINVAL;
pm_runtime_get_sync(dai->dev);
spin_lock_irqsave(&sai->xfer_lock, flags);
rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates);
regmap_update_bits(sai->regmap, SAI_TXCR, SAI_XCR_SBW_MASK,
SAI_XCR_SBW(sw));
regmap_update_bits(sai->regmap, SAI_RXCR, SAI_XCR_SBW_MASK,
SAI_XCR_SBW(sw));
regmap_update_bits(sai->regmap, SAI_XFER,
SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK,
clk_gates);
spin_unlock_irqrestore(&sai->xfer_lock, flags);
scoped_guard(spinlock_irqsave, &sai->xfer_lock) {
rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates);
regmap_update_bits(sai->regmap, SAI_TXCR, SAI_XCR_SBW_MASK,
SAI_XCR_SBW(sw));
regmap_update_bits(sai->regmap, SAI_RXCR, SAI_XCR_SBW_MASK,
SAI_XCR_SBW(sw));
regmap_update_bits(sai->regmap, SAI_XFER,
SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK,
clk_gates);
}
pm_runtime_put(dai->dev);
return 0;