From 602fdadc547f3e623db32409eeea8a59a1baaf24 Mon Sep 17 00:00:00 2001 From: olivier moysan Date: Fri, 16 Jun 2017 14:15:30 +0200 Subject: ASoC: stm32: sai: typo fixes Fix typos in sai driver. Signed-off-by: olivier moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'sound/soc/stm/stm32_sai_sub.c') diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index ae4706ca265b..d7aeed3ec3c8 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -181,29 +181,29 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid) SAI_XCLRFR_MASK); if (flags & SAI_XIMR_OVRUDRIE) { - dev_err(&pdev->dev, "IT %s\n", + dev_err(&pdev->dev, "IRQ %s\n", STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun"); status = SNDRV_PCM_STATE_XRUN; } if (flags & SAI_XIMR_MUTEDETIE) - dev_dbg(&pdev->dev, "IT mute detected\n"); + dev_dbg(&pdev->dev, "IRQ mute detected\n"); if (flags & SAI_XIMR_WCKCFGIE) { - dev_err(&pdev->dev, "IT wrong clock configuration\n"); + dev_err(&pdev->dev, "IRQ wrong clock configuration\n"); status = SNDRV_PCM_STATE_DISCONNECTED; } if (flags & SAI_XIMR_CNRDYIE) - dev_warn(&pdev->dev, "IT Codec not ready\n"); + dev_err(&pdev->dev, "IRQ Codec not ready\n"); if (flags & SAI_XIMR_AFSDETIE) { - dev_warn(&pdev->dev, "IT Anticipated frame synchro\n"); + dev_err(&pdev->dev, "IRQ Anticipated frame synchro\n"); status = SNDRV_PCM_STATE_XRUN; } if (flags & SAI_XIMR_LFSDETIE) { - dev_warn(&pdev->dev, "IT Late frame synchro\n"); + dev_err(&pdev->dev, "IRQ Late frame synchro\n"); status = SNDRV_PCM_STATE_XRUN; } @@ -235,7 +235,7 @@ static int stm32_sai_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask, struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); int slotr, slotr_mask, slot_size; - dev_dbg(cpu_dai->dev, "masks tx/rx:%#x/%#x, slots:%d, width:%d\n", + dev_dbg(cpu_dai->dev, "Masks tx/rx:%#x/%#x, slots:%d, width:%d\n", tx_mask, rx_mask, slots, slot_width); switch (slot_width) { @@ -377,7 +377,7 @@ static int stm32_sai_startup(struct snd_pcm_substream *substream, ret = clk_prepare_enable(sai->sai_ck); if (ret < 0) { - dev_err(cpu_dai->dev, "failed to enable clock: %d\n", ret); + dev_err(cpu_dai->dev, "Failed to enable clock: %d\n", ret); return ret; } @@ -497,7 +497,7 @@ static int stm32_sai_set_slots(struct snd_soc_dai *cpu_dai) SAI_XSLOTR_SLOTEN_SET(sai->slot_mask)); } - dev_dbg(cpu_dai->dev, "slots %d, slot width %d\n", + dev_dbg(cpu_dai->dev, "Slots %d, slot width %d\n", sai->slots, sai->slot_width); return 0; @@ -521,7 +521,7 @@ static void stm32_sai_set_frame(struct snd_soc_dai *cpu_dai) frcr |= SAI_XFRCR_FSALL_SET((fs_active - 1)); frcr_mask = SAI_XFRCR_FRL_MASK | SAI_XFRCR_FSALL_MASK; - dev_dbg(cpu_dai->dev, "frame length %d, frame active %d\n", + dev_dbg(cpu_dai->dev, "Frame length %d, frame active %d\n", sai->fs_length, fs_active); regmap_update_bits(sai->regmap, STM_SAI_FRCR_REGX, frcr_mask, frcr); @@ -784,7 +784,7 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); if (IS_ERR(sai->sai_ck)) { - dev_err(&pdev->dev, "missing kernel clock sai_ck\n"); + dev_err(&pdev->dev, "Missing kernel clock sai_ck\n"); return PTR_ERR(sai->sai_ck); } @@ -849,7 +849,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, sai->pdata->irq, stm32_sai_isr, IRQF_SHARED, dev_name(&pdev->dev), sai); if (ret) { - dev_err(&pdev->dev, "irq request returned %d\n", ret); + dev_err(&pdev->dev, "IRQ request returned %d\n", ret); return ret; } @@ -861,7 +861,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) ret = devm_snd_dmaengine_pcm_register(&pdev->dev, &stm32_sai_pcm_config, 0); if (ret) { - dev_err(&pdev->dev, "could not register pcm dma\n"); + dev_err(&pdev->dev, "Could not register pcm dma\n"); return ret; } @@ -879,6 +879,6 @@ static struct platform_driver stm32_sai_sub_driver = { module_platform_driver(stm32_sai_sub_driver); MODULE_DESCRIPTION("STM32 Soc SAI sub-block Interface"); -MODULE_AUTHOR("Olivier Moysan, "); +MODULE_AUTHOR("Olivier Moysan "); MODULE_ALIAS("platform:st,stm32-sai-sub"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 607c61d40b9c29ab0902541d0d372b18793d6831 Mon Sep 17 00:00:00 2001 From: olivier moysan Date: Fri, 16 Jun 2017 14:15:31 +0200 Subject: ASoC: stm32: sai: remove spurious trace Remove spurious trace in sai driver. Signed-off-by: olivier moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound/soc/stm/stm32_sai_sub.c') diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index d7aeed3ec3c8..24b8874cfe5f 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -761,9 +761,6 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - dev_err(&pdev->dev, "res %pr\n", res); - base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) return PTR_ERR(base); -- cgit v1.2.3 From 4fa17938ea400b6478b24565483f2ac54122316f Mon Sep 17 00:00:00 2001 From: olivier moysan Date: Fri, 16 Jun 2017 14:15:32 +0200 Subject: ASoC: stm32: sai: change stop sequence Disable SAI before stopping DMA data transfers. Signed-off-by: olivier moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/stm/stm32_sai_sub.c') diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 24b8874cfe5f..97b69a3ab46e 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -629,12 +629,12 @@ static int stm32_sai_trigger(struct snd_pcm_substream *substream, int cmd, dev_dbg(cpu_dai->dev, "Disable DMA and SAI\n"); regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, - SAI_XCR1_DMAEN, - (unsigned int)~SAI_XCR1_DMAEN); + SAI_XCR1_SAIEN, + (unsigned int)~SAI_XCR1_SAIEN); ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, - SAI_XCR1_SAIEN, - (unsigned int)~SAI_XCR1_SAIEN); + SAI_XCR1_DMAEN, + (unsigned int)~SAI_XCR1_DMAEN); if (ret < 0) dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); break; -- cgit v1.2.3 From 1c77603136d00368b8cd7c10d1ca4bad5952a136 Mon Sep 17 00:00:00 2001 From: olivier moysan Date: Fri, 16 Jun 2017 14:15:33 +0200 Subject: ASoC: stm32: sai: fix clock management Allow peripheral clock enable/disable on regmap accesses. Signed-off-by: olivier moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/stm/stm32_sai_sub.c') diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 97b69a3ab46e..2466af0343db 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -766,8 +766,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, return PTR_ERR(base); sai->phys_addr = res->start; - sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, - &stm32_sai_sub_regmap_config); + sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "sai_ck", base, + &stm32_sai_sub_regmap_config); /* Get direction property */ if (of_property_match_string(np, "dma-names", "tx") >= 0) { -- cgit v1.2.3 From 701a6ec3a3f8d30bdb45ee025fb61f7a934b6cad Mon Sep 17 00:00:00 2001 From: olivier moysan Date: Fri, 16 Jun 2017 14:15:34 +0200 Subject: ASoC: stm32: sai: manage master clock Disable master clock by default, and activate it only when requested. Signed-off-by: olivier moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'sound/soc/stm/stm32_sai_sub.c') diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 2466af0343db..ce48c02db051 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -220,8 +220,15 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); + int ret; if ((dir == SND_SOC_CLOCK_OUT) && sai->master) { + ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, + SAI_XCR1_NODIV, + (unsigned int)~SAI_XCR1_NODIV); + if (ret < 0) + return ret; + sai->mclk_rate = freq; dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq); } @@ -356,6 +363,10 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) } cr1_mask |= SAI_XCR1_SLAVE; + /* do not generate master by default */ + cr1 |= SAI_XCR1_NODIV; + cr1_mask |= SAI_XCR1_NODIV; + ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, cr1_mask, cr1); if (ret < 0) { dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); @@ -652,6 +663,9 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream, regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0); + regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV, + SAI_XCR1_NODIV); + clk_disable_unprepare(sai->sai_ck); sai->substream = NULL; } -- cgit v1.2.3 From 03e78a242a15eca68e5c7cb606c94959382e2b18 Mon Sep 17 00:00:00 2001 From: olivier moysan Date: Fri, 16 Jun 2017 14:16:24 +0200 Subject: ASoC: stm32: sai: add h7 support Add support of SAI on STM32H7 family. Signed-off-by: olivier moysan Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai.c | 13 +++++- sound/soc/stm/stm32_sai.h | 72 ++++++++++++++++++++++++++++++--- sound/soc/stm/stm32_sai_sub.c | 92 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 155 insertions(+), 22 deletions(-) (limited to 'sound/soc/stm/stm32_sai_sub.c') diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 6159d66c2c54..f7713314913b 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -27,8 +27,17 @@ #include "stm32_sai.h" +static const struct stm32_sai_conf stm32_sai_conf_f4 = { + .version = SAI_STM32F4, +}; + +static const struct stm32_sai_conf stm32_sai_conf_h7 = { + .version = SAI_STM32H7, +}; + static const struct of_device_id stm32_sai_ids[] = { - { .compatible = "st,stm32f4-sai", .data = (void *)SAI_STM32F4 }, + { .compatible = "st,stm32f4-sai", .data = (void *)&stm32_sai_conf_f4 }, + { .compatible = "st,stm32h7-sai", .data = (void *)&stm32_sai_conf_h7 }, {} }; @@ -52,7 +61,7 @@ static int stm32_sai_probe(struct platform_device *pdev) of_id = of_match_device(stm32_sai_ids, &pdev->dev); if (of_id) - sai->version = (enum stm32_sai_version)of_id->data; + sai->conf = (struct stm32_sai_conf *)of_id->data; else return -EINVAL; diff --git a/sound/soc/stm/stm32_sai.h b/sound/soc/stm/stm32_sai.h index 270be93b845e..889974dc62d9 100644 --- a/sound/soc/stm/stm32_sai.h +++ b/sound/soc/stm/stm32_sai.h @@ -31,6 +31,10 @@ #define STM_SAI_CLRFR_REGX 0x18 #define STM_SAI_DR_REGX 0x1C +/* Sub-block A registers, relative to sub-block A address */ +#define STM_SAI_PDMCR_REGX 0x40 +#define STM_SAI_PDMLY_REGX 0x44 + /******************** Bit definition for SAI_GCR register *******************/ #define SAI_GCR_SYNCIN_SHIFT 0 #define SAI_GCR_SYNCIN_MASK GENMASK(1, SAI_GCR_SYNCIN_SHIFT) @@ -75,10 +79,11 @@ #define SAI_XCR1_NODIV BIT(SAI_XCR1_NODIV_SHIFT) #define SAI_XCR1_MCKDIV_SHIFT 20 -#define SAI_XCR1_MCKDIV_WIDTH 4 -#define SAI_XCR1_MCKDIV_MASK GENMASK(24, SAI_XCR1_MCKDIV_SHIFT) +#define SAI_XCR1_MCKDIV_WIDTH(x) (((x) == SAI_STM32F4) ? 4 : 6) +#define SAI_XCR1_MCKDIV_MASK(x) GENMASK((SAI_XCR1_MCKDIV_SHIFT + (x) - 1),\ + SAI_XCR1_MCKDIV_SHIFT) #define SAI_XCR1_MCKDIV_SET(x) ((x) << SAI_XCR1_MCKDIV_SHIFT) -#define SAI_XCR1_MCKDIV_MAX ((1 << SAI_XCR1_MCKDIV_WIDTH) - 1) +#define SAI_XCR1_MCKDIV_MAX(x) ((1 << SAI_XCR1_MCKDIV_WIDTH(x)) - 1) #define SAI_XCR1_OSR_SHIFT 26 #define SAI_XCR1_OSR BIT(SAI_XCR1_OSR_SHIFT) @@ -178,8 +183,65 @@ #define SAI_XCLRFR_SHIFT 0 #define SAI_XCLRFR_MASK GENMASK(6, SAI_XCLRFR_SHIFT) +/****************** Bit definition for SAI_PDMCR register ******************/ +#define SAI_PDMCR_PDMEN BIT(0) + +#define SAI_PDMCR_MICNBR_SHIFT 4 +#define SAI_PDMCR_MICNBR_MASK GENMASK(5, SAI_PDMCR_MICNBR_SHIFT) +#define SAI_PDMCR_MICNBR_SET(x) ((x) << SAI_PDMCR_MICNBR_SHIFT) + +#define SAI_PDMCR_CKEN1 BIT(8) +#define SAI_PDMCR_CKEN2 BIT(9) +#define SAI_PDMCR_CKEN3 BIT(10) +#define SAI_PDMCR_CKEN4 BIT(11) + +/****************** Bit definition for (SAI_PDMDLY register ****************/ +#define SAI_PDMDLY_1L_SHIFT 0 +#define SAI_PDMDLY_1L_MASK GENMASK(2, SAI_PDMDLY_1L_SHIFT) +#define SAI_PDMDLY_1L_WIDTH 3 + +#define SAI_PDMDLY_1R_SHIFT 4 +#define SAI_PDMDLY_1R_MASK GENMASK(6, SAI_PDMDLY_1R_SHIFT) +#define SAI_PDMDLY_1R_WIDTH 3 + +#define SAI_PDMDLY_2L_SHIFT 8 +#define SAI_PDMDLY_2L_MASK GENMASK(10, SAI_PDMDLY_2L_SHIFT) +#define SAI_PDMDLY_2L_WIDTH 3 + +#define SAI_PDMDLY_2R_SHIFT 12 +#define SAI_PDMDLY_2R_MASK GENMASK(14, SAI_PDMDLY_2R_SHIFT) +#define SAI_PDMDLY_2R_WIDTH 3 + +#define SAI_PDMDLY_3L_SHIFT 16 +#define SAI_PDMDLY_3L_MASK GENMASK(18, SAI_PDMDLY_3L_SHIFT) +#define SAI_PDMDLY_3L_WIDTH 3 + +#define SAI_PDMDLY_3R_SHIFT 20 +#define SAI_PDMDLY_3R_MASK GENMASK(22, SAI_PDMDLY_3R_SHIFT) +#define SAI_PDMDLY_3R_WIDTH 3 + +#define SAI_PDMDLY_4L_SHIFT 24 +#define SAI_PDMDLY_4L_MASK GENMASK(26, SAI_PDMDLY_4L_SHIFT) +#define SAI_PDMDLY_4L_WIDTH 3 + +#define SAI_PDMDLY_4R_SHIFT 28 +#define SAI_PDMDLY_4R_MASK GENMASK(30, SAI_PDMDLY_4R_SHIFT) +#define SAI_PDMDLY_4R_WIDTH 3 + +#define STM_SAI_IS_F4(ip) ((ip)->conf->version == SAI_STM32F4) +#define STM_SAI_IS_H7(ip) ((ip)->conf->version == SAI_STM32H7) + enum stm32_sai_version { - SAI_STM32F4 + SAI_STM32F4, + SAI_STM32H7 +}; + +/** + * struct stm32_sai_conf - SAI configuration + * @version: SAI version + */ +struct stm32_sai_conf { + int version; }; /** @@ -194,6 +256,6 @@ struct stm32_sai_data { struct platform_device *pdev; struct clk *clk_x8k; struct clk *clk_x11k; - int version; + struct stm32_sai_conf *conf; int irq; }; diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index ce48c02db051..ba3fdc777ed8 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -51,12 +51,15 @@ #define STM_SAI_A_ID 0x0 #define STM_SAI_B_ID 0x1 +#define STM_SAI_IS_SUB_A(x) ((x)->id == STM_SAI_A_ID) +#define STM_SAI_IS_SUB_B(x) ((x)->id == STM_SAI_B_ID) #define STM_SAI_BLOCK_NAME(x) (((x)->id == STM_SAI_A_ID) ? "A" : "B") /** * struct stm32_sai_sub_data - private data of SAI sub block (block A or B) * @pdev: device data pointer * @regmap: SAI register map pointer + * @regmap_config: SAI sub block register map configuration pointer * @dma_params: dma configuration data for rx or tx channel * @cpu_dai_drv: DAI driver data pointer * @cpu_dai: DAI runtime data pointer @@ -79,6 +82,7 @@ struct stm32_sai_sub_data { struct platform_device *pdev; struct regmap *regmap; + const struct regmap_config *regmap_config; struct snd_dmaengine_dai_dma_data dma_params; struct snd_soc_dai_driver *cpu_dai_drv; struct snd_soc_dai *cpu_dai; @@ -118,6 +122,8 @@ static bool stm32_sai_sub_readable_reg(struct device *dev, unsigned int reg) case STM_SAI_SR_REGX: case STM_SAI_CLRFR_REGX: case STM_SAI_DR_REGX: + case STM_SAI_PDMCR_REGX: + case STM_SAI_PDMLY_REGX: return true; default: return false; @@ -145,13 +151,15 @@ static bool stm32_sai_sub_writeable_reg(struct device *dev, unsigned int reg) case STM_SAI_SR_REGX: case STM_SAI_CLRFR_REGX: case STM_SAI_DR_REGX: + case STM_SAI_PDMCR_REGX: + case STM_SAI_PDMLY_REGX: return true; default: return false; } } -static const struct regmap_config stm32_sai_sub_regmap_config = { +static const struct regmap_config stm32_sai_sub_regmap_config_f4 = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, @@ -162,6 +170,17 @@ static const struct regmap_config stm32_sai_sub_regmap_config = { .fast_io = true, }; +static const struct regmap_config stm32_sai_sub_regmap_config_h7 = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = STM_SAI_PDMLY_REGX, + .readable_reg = stm32_sai_sub_readable_reg, + .volatile_reg = stm32_sai_sub_volatile_reg, + .writeable_reg = stm32_sai_sub_writeable_reg, + .fast_io = true, +}; + static irqreturn_t stm32_sai_isr(int irq, void *devid) { struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid; @@ -551,7 +570,8 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, { struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); int cr1, mask, div = 0; - int sai_clk_rate, ret; + int sai_clk_rate, mclk_ratio, den, ret; + int version = sai->pdata->conf->version; if (!sai->mclk_rate) { dev_err(cpu_dai->dev, "Mclk rate is null\n"); @@ -564,22 +584,54 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k); sai_clk_rate = clk_get_rate(sai->sai_ck); - /* - * mclk_rate = 256 * fs - * MCKDIV = 0 if sai_ck < 3/2 * mclk_rate - * MCKDIV = sai_ck / (2 * mclk_rate) otherwise - */ - if (2 * sai_clk_rate >= 3 * sai->mclk_rate) - div = DIV_ROUND_CLOSEST(sai_clk_rate, 2 * sai->mclk_rate); - - if (div > SAI_XCR1_MCKDIV_MAX) { + if (STM_SAI_IS_F4(sai->pdata)) { + /* + * mclk_rate = 256 * fs + * MCKDIV = 0 if sai_ck < 3/2 * mclk_rate + * MCKDIV = sai_ck / (2 * mclk_rate) otherwise + */ + if (2 * sai_clk_rate >= 3 * sai->mclk_rate) + div = DIV_ROUND_CLOSEST(sai_clk_rate, + 2 * sai->mclk_rate); + } else { + /* + * TDM mode : + * mclk on + * MCKDIV = sai_ck / (ws x 256) (NOMCK=0. OSR=0) + * MCKDIV = sai_ck / (ws x 512) (NOMCK=0. OSR=1) + * mclk off + * MCKDIV = sai_ck / (frl x ws) (NOMCK=1) + * Note: NOMCK/NODIV correspond to same bit. + */ + if (sai->mclk_rate) { + mclk_ratio = sai->mclk_rate / params_rate(params); + if (mclk_ratio != 256) { + if (mclk_ratio == 512) { + mask = SAI_XCR1_OSR; + cr1 = SAI_XCR1_OSR; + } else { + dev_err(cpu_dai->dev, + "Wrong mclk ratio %d\n", + mclk_ratio); + return -EINVAL; + } + } + div = DIV_ROUND_CLOSEST(sai_clk_rate, sai->mclk_rate); + } else { + /* mclk-fs not set, master clock not active. NOMCK=1 */ + den = sai->fs_length * params_rate(params); + div = DIV_ROUND_CLOSEST(sai_clk_rate, den); + } + } + + if (div > SAI_XCR1_MCKDIV_MAX(version)) { dev_err(cpu_dai->dev, "Divider %d out of range\n", div); return -EINVAL; } dev_dbg(cpu_dai->dev, "SAI clock %d, divider %d\n", sai_clk_rate, div); - mask = SAI_XCR1_MCKDIV_MASK; - cr1 = SAI_XCR1_MCKDIV_SET(div); + mask = SAI_XCR1_MCKDIV_MASK(SAI_XCR1_MCKDIV_WIDTH(version)); + cr1 = SAI_XCR1_MCKDIV_SET(div); ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1); if (ret < 0) { dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); @@ -780,8 +832,18 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, return PTR_ERR(base); sai->phys_addr = res->start; - sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "sai_ck", base, - &stm32_sai_sub_regmap_config); + + sai->regmap_config = &stm32_sai_sub_regmap_config_f4; + /* Note: PDM registers not available for H7 sub-block B */ + if (STM_SAI_IS_H7(sai->pdata) && STM_SAI_IS_SUB_A(sai)) + sai->regmap_config = &stm32_sai_sub_regmap_config_h7; + + sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "sai_ck", + base, sai->regmap_config); + if (IS_ERR(sai->regmap)) { + dev_err(&pdev->dev, "Failed to initialize MMIO\n"); + return PTR_ERR(sai->regmap); + } /* Get direction property */ if (of_property_match_string(np, "dma-names", "tx") >= 0) { -- cgit v1.2.3 From 81321fe9fb69004e71353a602f9d51f656469cdd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 28 Jun 2017 15:20:06 +0300 Subject: ASoC: stm32: sai: remove some stray tabs This line was accidentally indented too far. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/stm/stm32_sai_sub.c') diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index ba3fdc777ed8..90d439613899 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -631,7 +631,7 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, dev_dbg(cpu_dai->dev, "SAI clock %d, divider %d\n", sai_clk_rate, div); mask = SAI_XCR1_MCKDIV_MASK(SAI_XCR1_MCKDIV_WIDTH(version)); - cr1 = SAI_XCR1_MCKDIV_SET(div); + cr1 = SAI_XCR1_MCKDIV_SET(div); ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, mask, cr1); if (ret < 0) { dev_err(cpu_dai->dev, "Failed to update CR1 register\n"); -- cgit v1.2.3