diff options
Diffstat (limited to 'sound/soc/stm')
-rw-r--r-- | sound/soc/stm/stm32_i2s.c | 25 | ||||
-rw-r--r-- | sound/soc/stm/stm32_spdifrx.c | 42 |
2 files changed, 48 insertions, 19 deletions
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 8968458eec62..952634258b02 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -179,7 +179,6 @@ enum i2s_datlen { I2S_I2SMOD_DATLEN_32, }; -#define STM32_I2S_DAI_NAME_SIZE 20 #define STM32_I2S_FIFO_SIZE 16 #define STM32_I2S_IS_MASTER(x) ((x)->ms_flg == I2S_MS_MASTER) @@ -202,7 +201,6 @@ enum i2s_datlen { * @phys_addr: I2S registers physical base address * @lock_fd: lock to manage race conditions in full duplex mode * @irq_lock: prevent race condition with IRQ - * @dais_name: DAI name * @mclk_rate: master clock frequency (Hz) * @fmt: DAI protocol * @refcount: keep count of opened streams on I2S @@ -224,7 +222,6 @@ struct stm32_i2s_data { dma_addr_t phys_addr; spinlock_t lock_fd; /* Manage race conditions for full duplex */ spinlock_t irq_lock; /* used to prevent race condition with IRQ */ - char dais_name[STM32_I2S_DAI_NAME_SIZE]; unsigned int mclk_rate; unsigned int fmt; int refcount; @@ -495,12 +492,6 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai, unsigned int fthlv; int ret; - if ((params_channels(params) == 1) && - ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_DSP_A)) { - dev_err(cpu_dai->dev, "Mono mode supported only by DSP_A\n"); - return -EINVAL; - } - switch (format) { case 16: cfgr = I2S_CGFR_DATLEN_SET(I2S_I2SMOD_DATLEN_16); @@ -550,6 +541,10 @@ static int stm32_i2s_startup(struct snd_pcm_substream *substream, i2s->substream = substream; spin_unlock_irqrestore(&i2s->irq_lock, flags); + if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_DSP_A) + snd_pcm_hw_constraint_single(substream->runtime, + SNDRV_PCM_HW_PARAM_CHANNELS, 2); + ret = clk_prepare_enable(i2s->i2sclk); if (ret < 0) { dev_err(cpu_dai->dev, "Failed to enable clock: %d\n", ret); @@ -592,7 +587,8 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* Enable i2s */ - dev_dbg(cpu_dai->dev, "start I2S\n"); + dev_dbg(cpu_dai->dev, "start I2S %s\n", + playback_flg ? "playback" : "capture"); cfg1_mask = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN; regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG, @@ -637,6 +633,9 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + dev_dbg(cpu_dai->dev, "stop I2S %s\n", + playback_flg ? "playback" : "capture"); + if (playback_flg) regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, I2S_IER_UDRIE, @@ -653,8 +652,6 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd, break; } - dev_dbg(cpu_dai->dev, "stop I2S\n"); - ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG, I2S_CR1_SPE, 0); if (ret < 0) { @@ -770,12 +767,8 @@ static int stm32_i2s_dais_init(struct platform_device *pdev, if (!dai_ptr) return -ENOMEM; - snprintf(i2s->dais_name, STM32_I2S_DAI_NAME_SIZE, - "%s", dev_name(&pdev->dev)); - dai_ptr->probe = stm32_i2s_dai_probe; dai_ptr->ops = &stm32_i2s_pcm_dai_ops; - dai_ptr->name = i2s->dais_name; dai_ptr->id = 1; stm32_i2s_dai_init(&dai_ptr->playback, "playback"); stm32_i2s_dai_init(&dai_ptr->capture, "capture"); diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index 373df4f24be1..b4c3d983e195 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -21,6 +21,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/of_platform.h> +#include <linux/pinctrl/consumer.h> #include <linux/regmap.h> #include <linux/reset.h> @@ -471,6 +472,8 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx) memset(spdifrx->cs, 0, SPDIFRX_CS_BYTES_NB); memset(spdifrx->ub, 0, SPDIFRX_UB_BYTES_NB); + pinctrl_pm_select_default_state(&spdifrx->pdev->dev); + ret = stm32_spdifrx_dma_ctrl_start(spdifrx); if (ret < 0) return ret; @@ -502,6 +505,7 @@ static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx) end: clk_disable_unprepare(spdifrx->kclk); + pinctrl_pm_select_sleep_state(&spdifrx->pdev->dev); return ret; } @@ -611,10 +615,15 @@ static bool stm32_spdifrx_readable_reg(struct device *dev, unsigned int reg) static bool stm32_spdifrx_volatile_reg(struct device *dev, unsigned int reg) { - if (reg == STM32_SPDIFRX_DR) + switch (reg) { + case STM32_SPDIFRX_DR: + case STM32_SPDIFRX_CSR: + case STM32_SPDIFRX_SR: + case STM32_SPDIFRX_DIR: return true; - - return false; + default: + return false; + } } static bool stm32_spdifrx_writeable_reg(struct device *dev, unsigned int reg) @@ -638,6 +647,7 @@ static const struct regmap_config stm32_h7_spdifrx_regmap_conf = { .volatile_reg = stm32_spdifrx_volatile_reg, .writeable_reg = stm32_spdifrx_writeable_reg, .fast_io = true, + .cache_type = REGCACHE_FLAT, }; static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) @@ -983,10 +993,36 @@ static int stm32_spdifrx_remove(struct platform_device *pdev) MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids); +#ifdef CONFIG_PM_SLEEP +static int stm32_spdifrx_suspend(struct device *dev) +{ + struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(dev); + + regcache_cache_only(spdifrx->regmap, true); + regcache_mark_dirty(spdifrx->regmap); + + return 0; +} + +static int stm32_spdifrx_resume(struct device *dev) +{ + struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(dev); + + regcache_cache_only(spdifrx->regmap, false); + + return regcache_sync(spdifrx->regmap); +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops stm32_spdifrx_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(stm32_spdifrx_suspend, stm32_spdifrx_resume) +}; + static struct platform_driver stm32_spdifrx_driver = { .driver = { .name = "st,stm32-spdifrx", .of_match_table = stm32_spdifrx_ids, + .pm = &stm32_spdifrx_pm_ops, }, .probe = stm32_spdifrx_probe, .remove = stm32_spdifrx_remove, |