diff options
Diffstat (limited to 'sound/soc/stm/stm32_sai.c')
-rw-r--r-- | sound/soc/stm/stm32_sai.c | 89 |
1 files changed, 53 insertions, 36 deletions
diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 058757c721f0..fa821e3fb427 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -19,26 +19,42 @@ #include "stm32_sai.h" +static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai); + static const struct stm32_sai_conf stm32_sai_conf_f4 = { .version = STM_SAI_STM32F4, .fifo_size = 8, .has_spdif_pdm = false, + .get_sai_ck_parent = stm32_sai_get_parent_clk, }; /* - * Default settings for stm32 H7 socs and next. + * Default settings for STM32H7x socs and STM32MP1x. * These default settings will be overridden if the soc provides * support of hardware configuration registers. + * - STM32H7: rely on default settings + * - STM32MP1: retrieve settings from registers */ static const struct stm32_sai_conf stm32_sai_conf_h7 = { .version = STM_SAI_STM32H7, .fifo_size = 8, .has_spdif_pdm = true, + .get_sai_ck_parent = stm32_sai_get_parent_clk, +}; + +/* + * STM32MP2x: + * - do not use SAI parent clock source selection + * - do not use DMA burst mode + */ +static const struct stm32_sai_conf stm32_sai_conf_mp25 = { + .no_dma_burst = true, }; static const struct of_device_id stm32_sai_ids[] = { { .compatible = "st,stm32f4-sai", .data = (void *)&stm32_sai_conf_f4 }, { .compatible = "st,stm32h7-sai", .data = (void *)&stm32_sai_conf_h7 }, + { .compatible = "st,stm32mp25-sai", .data = (void *)&stm32_sai_conf_mp25 }, {} }; @@ -148,11 +164,28 @@ error: return ret; } +static int stm32_sai_get_parent_clk(struct stm32_sai_data *sai) +{ + struct device *dev = &sai->pdev->dev; + + sai->clk_x8k = devm_clk_get(dev, "x8k"); + if (IS_ERR(sai->clk_x8k)) + return dev_err_probe(dev, PTR_ERR(sai->clk_x8k), + "missing x8k parent clock\n"); + + sai->clk_x11k = devm_clk_get(dev, "x11k"); + if (IS_ERR(sai->clk_x11k)) + return dev_err_probe(dev, PTR_ERR(sai->clk_x11k), + "missing x11k parent clock\n"); + + return 0; +} + static int stm32_sai_probe(struct platform_device *pdev) { struct stm32_sai_data *sai; + const struct stm32_sai_conf *conf; struct reset_control *rst; - const struct of_device_id *of_id; u32 val; int ret; @@ -160,41 +193,30 @@ static int stm32_sai_probe(struct platform_device *pdev) if (!sai) return -ENOMEM; + sai->pdev = pdev; + sai->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sai->base)) return PTR_ERR(sai->base); - of_id = of_match_device(stm32_sai_ids, &pdev->dev); - if (of_id) - memcpy(&sai->conf, (const struct stm32_sai_conf *)of_id->data, + conf = device_get_match_data(&pdev->dev); + if (conf) + memcpy(&sai->conf, (const struct stm32_sai_conf *)conf, sizeof(struct stm32_sai_conf)); else return -EINVAL; if (!STM_SAI_IS_F4(sai)) { sai->pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(sai->pclk)) { - if (PTR_ERR(sai->pclk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "missing bus clock pclk: %ld\n", - PTR_ERR(sai->pclk)); - return PTR_ERR(sai->pclk); - } + if (IS_ERR(sai->pclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(sai->pclk), + "missing bus clock pclk\n"); } - sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k"); - if (IS_ERR(sai->clk_x8k)) { - if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER) - dev_err(&pdev->dev, "missing x8k parent clock: %ld\n", - PTR_ERR(sai->clk_x8k)); - return PTR_ERR(sai->clk_x8k); - } - - sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k"); - if (IS_ERR(sai->clk_x11k)) { - if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER) - dev_err(&pdev->dev, "missing x11k parent clock: %ld\n", - PTR_ERR(sai->clk_x11k)); - return PTR_ERR(sai->clk_x11k); + if (sai->conf.get_sai_ck_parent) { + ret = sai->conf.get_sai_ck_parent(sai); + if (ret) + return ret; } /* init irqs */ @@ -204,12 +226,10 @@ static int stm32_sai_probe(struct platform_device *pdev) /* reset */ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); - if (IS_ERR(rst)) { - if (PTR_ERR(rst) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Reset controller error %ld\n", - PTR_ERR(rst)); - return PTR_ERR(rst); - } + if (IS_ERR(rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(rst), + "Reset controller error\n"); + reset_control_assert(rst); udelay(2); reset_control_deassert(rst); @@ -238,14 +258,12 @@ static int stm32_sai_probe(struct platform_device *pdev) } clk_disable_unprepare(sai->pclk); - sai->pdev = pdev; sai->set_sync = &stm32_sai_set_sync; platform_set_drvdata(pdev, sai); return devm_of_platform_populate(&pdev->dev); } -#ifdef CONFIG_PM_SLEEP /* * When pins are shared by two sai sub instances, pins have to be defined * in sai parent node. In this case, pins state is not managed by alsa fw. @@ -280,10 +298,9 @@ static int stm32_sai_resume(struct device *dev) return pinctrl_pm_select_default_state(dev); } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops stm32_sai_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(stm32_sai_suspend, stm32_sai_resume) + SYSTEM_SLEEP_PM_OPS(stm32_sai_suspend, stm32_sai_resume) }; MODULE_DEVICE_TABLE(of, stm32_sai_ids); @@ -292,7 +309,7 @@ static struct platform_driver stm32_sai_driver = { .driver = { .name = "st,stm32-sai", .of_match_table = stm32_sai_ids, - .pm = &stm32_sai_pm_ops, + .pm = pm_ptr(&stm32_sai_pm_ops), }, .probe = stm32_sai_probe, }; |