mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
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:
commit
5542791d50
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user