ASoC: rockchip: i2s: Fix regmap_ops hang
authorSugar Zhang <sugar.zhang@rock-chips.com>
Thu, 26 Aug 2021 04:01:50 +0000 (12:01 +0800)
committerMark Brown <broonie@kernel.org>
Thu, 26 Aug 2021 12:59:33 +0000 (13:59 +0100)
API 'set_fmt' maybe called when PD is off, in the situation,
any register access will hang the system. so, enable PD
before r/w register.

Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Link: https://lore.kernel.org/r/1629950520-14190-4-git-send-email-sugar.zhang@rock-chips.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/rockchip/rockchip_i2s.c

index 2e0047d..90877e8 100644 (file)
@@ -187,7 +187,9 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
 {
        struct rk_i2s_dev *i2s = to_info(cpu_dai);
        unsigned int mask = 0, val = 0;
+       int ret = 0;
 
+       pm_runtime_get_sync(cpu_dai->dev);
        mask = I2S_CKR_MSS_MASK;
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
@@ -200,7 +202,8 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                i2s->is_master_mode = false;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_pm_put;
        }
 
        regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
@@ -214,7 +217,8 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                val = I2S_CKR_CKP_POS;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_pm_put;
        }
 
        regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
@@ -237,7 +241,8 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1);
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_pm_put;
        }
 
        regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
@@ -260,12 +265,16 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1);
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_pm_put;
        }
 
        regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
 
-       return 0;
+err_pm_put:
+       pm_runtime_put(cpu_dai->dev);
+
+       return ret;
 }
 
 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,