Loading Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml +33 −3 Original line number Diff line number Diff line Loading @@ -13,13 +13,11 @@ description: The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode. Only some SPI instances support I2S. allOf: - $ref: dai-common.yaml# properties: compatible: enum: - st,stm32h7-i2s - st,stm32mp25-i2s "#sound-dai-cells": const: 0 Loading @@ -33,6 +31,7 @@ properties: - description: clock feeding the internal clock generator. - description: I2S parent clock for sampling rates multiple of 8kHz. - description: I2S parent clock for sampling rates multiple of 11.025kHz. minItems: 2 clock-names: items: Loading @@ -40,6 +39,7 @@ properties: - const: i2sclk - const: x8k - const: x11k minItems: 2 interrupts: maxItems: 1 Loading Loading @@ -79,6 +79,36 @@ required: - dmas - dma-names allOf: - $ref: dai-common.yaml# - if: properties: compatible: contains: const: st,stm32h7-i2s then: properties: clocks: minItems: 4 clock-names: minItems: 4 - if: properties: compatible: contains: const: st,stm32mp25-i2s then: properties: clocks: maxItems: 2 clock-names: maxItems: 2 unevaluatedProperties: false examples: Loading sound/soc/stm/stm32_i2s.c +189 −22 Original line number Diff line number Diff line Loading @@ -200,10 +200,13 @@ enum i2s_datlen { #define STM32_I2S_NAME_LEN 32 #define STM32_I2S_RATE_11K 11025 #define STM32_I2S_MAX_SAMPLE_RATE_8K 192000 #define STM32_I2S_MAX_SAMPLE_RATE_11K 176400 #define STM32_I2S_CLK_RATE_TOLERANCE 1000 /* ppm */ /** * struct stm32_i2s_data - private data of I2S * @regmap_conf: I2S register map configuration pointer * @conf: I2S configuration pointer * @regmap: I2S register map pointer * @pdev: device data pointer * @dai_drv: DAI driver pointer Loading @@ -224,11 +227,14 @@ enum i2s_datlen { * @divider: prescaler division ratio * @div: prescaler div field * @odd: prescaler odd field * @i2s_clk_flg: flag set while exclusivity on I2S kernel clock is active * @refcount: keep count of opened streams on I2S * @ms_flg: master mode flag. * @set_i2s_clk_rate: set I2S kernel clock rate * @put_i2s_clk_rate: put I2S kernel clock rate */ struct stm32_i2s_data { const struct regmap_config *regmap_conf; const struct stm32_i2s_conf *conf; struct regmap *regmap; struct platform_device *pdev; struct snd_soc_dai_driver *dai_drv; Loading @@ -249,8 +255,21 @@ struct stm32_i2s_data { unsigned int divider; unsigned int div; bool odd; bool i2s_clk_flg; int refcount; int ms_flg; int (*set_i2s_clk_rate)(struct stm32_i2s_data *i2s, unsigned int rate); void (*put_i2s_clk_rate)(struct stm32_i2s_data *i2s); }; /** * struct stm32_i2s_conf - I2S configuration * @regmap_conf: regmap configuration pointer * @get_i2s_clk_parent: get parent clock of I2S kernel clock */ struct stm32_i2s_conf { const struct regmap_config *regmap_conf; int (*get_i2s_clk_parent)(struct stm32_i2s_data *i2s); }; struct stm32_i2smclk_data { Loading @@ -261,6 +280,8 @@ struct stm32_i2smclk_data { #define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw) static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s); static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s, unsigned long input_rate, unsigned long output_rate) Loading Loading @@ -312,6 +333,33 @@ static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s) cgfr_mask, cgfr); } static bool stm32_i2s_rate_accurate(struct stm32_i2s_data *i2s, unsigned int max_rate, unsigned int rate) { struct platform_device *pdev = i2s->pdev; u64 delta, dividend; int ratio; if (!rate) { dev_err(&pdev->dev, "Unexpected null rate\n"); return false; } ratio = DIV_ROUND_CLOSEST(max_rate, rate); if (!ratio) return false; dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate))); delta = div_u64(dividend, max_rate); if (delta <= STM32_I2S_CLK_RATE_TOLERANCE) return true; dev_dbg(&pdev->dev, "Rate [%u] not accurate\n", rate); return false; } static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, unsigned int rate) { Loading @@ -332,6 +380,87 @@ static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, return ret; } static void stm32_i2s_put_parent_rate(struct stm32_i2s_data *i2s) { if (i2s->i2s_clk_flg) { i2s->i2s_clk_flg = false; clk_rate_exclusive_put(i2s->i2sclk); } } static int stm32_i2s_set_parent_rate(struct stm32_i2s_data *i2s, unsigned int rate) { struct platform_device *pdev = i2s->pdev; unsigned int i2s_clk_rate, i2s_clk_max_rate, i2s_curr_rate, i2s_new_rate; int ret, div; /* * Set maximum expected kernel clock frequency * - mclk on: * f_i2s_ck = MCKDIV * mclk-fs * fs * Here typical 256 ratio is assumed for mclk-fs * - mclk off: * f_i2s_ck = MCKDIV * FRL * fs * Where FRL=[16,32], MCKDIV=[1..256] * f_i2s_ck = i2s_clk_max_rate * 32 / 256 */ if (!(rate % STM32_I2S_RATE_11K)) i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_11K * 256; else i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_8K * 256; if (!i2s->i2smclk) i2s_clk_max_rate /= 8; /* Request exclusivity, as the clock may be shared by I2S instances */ clk_rate_exclusive_get(i2s->i2sclk); i2s->i2s_clk_flg = true; /* * Check current kernel clock rate. If it gives the expected accuracy * return immediately. */ i2s_curr_rate = clk_get_rate(i2s->i2sclk); if (stm32_i2s_rate_accurate(i2s, i2s_clk_max_rate, i2s_curr_rate)) return 0; /* * Otherwise try to set the maximum rate and check the new actual rate. * If the new rate does not give the expected accuracy, try to set * lower rates for the kernel clock. */ i2s_clk_rate = i2s_clk_max_rate; div = 1; do { /* Check new rate accuracy. Return if ok */ i2s_new_rate = clk_round_rate(i2s->i2sclk, i2s_clk_rate); if (stm32_i2s_rate_accurate(i2s, i2s_clk_rate, i2s_new_rate)) { ret = clk_set_rate(i2s->i2sclk, i2s_clk_rate); if (ret) { dev_err(&pdev->dev, "Error %d setting i2s_clk_rate rate. %s", ret, ret == -EBUSY ? "Active stream rates may be in conflict\n" : "\n"); goto err; } return 0; } /* Try a lower frequency */ div++; i2s_clk_rate = i2s_clk_max_rate / div; } while (i2s_clk_rate > rate); /* no accurate rate found */ dev_err(&pdev->dev, "Failed to find an accurate rate"); err: stm32_i2s_put_parent_rate(i2s); return -EINVAL; } static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { Loading Loading @@ -635,12 +764,16 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, clk_rate_exclusive_put(i2s->i2smclk); i2s->mclk_rate = 0; } if (i2s->put_i2s_clk_rate) i2s->put_i2s_clk_rate(i2s); return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_MCKOE, 0); } /* If master clock is used, set parent clock now */ ret = stm32_i2s_set_parent_clock(i2s, freq); ret = i2s->set_i2s_clk_rate(i2s, freq); if (ret) return ret; ret = clk_set_rate_exclusive(i2s->i2smclk, freq); Loading @@ -667,10 +800,11 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, u32 cgfr; int ret; if (!(rate % 11025)) clk_set_parent(i2s->i2sclk, i2s->x11kclk); else clk_set_parent(i2s->i2sclk, i2s->x8kclk); if (!i2s->mclk_rate) { ret = i2s->set_i2s_clk_rate(i2s, rate); if (ret) return ret; } i2s_clock_rate = clk_get_rate(i2s->i2sclk); /* Loading Loading @@ -915,6 +1049,14 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(i2s->i2sclk); /* * Release kernel clock if following conditions are fulfilled * - Master clock is not used. Kernel clock won't be released trough sysclk * - Put handler is defined. Involve that clock is managed exclusively */ if (!i2s->i2smclk && i2s->put_i2s_clk_rate) i2s->put_i2s_clk_rate(i2s); spin_lock_irqsave(&i2s->irq_lock, flags); i2s->substream = NULL; spin_unlock_irqrestore(&i2s->irq_lock, flags); Loading Loading @@ -1012,14 +1154,36 @@ static int stm32_i2s_dais_init(struct platform_device *pdev, return 0; } static const struct stm32_i2s_conf stm32_i2s_conf_h7 = { .regmap_conf = &stm32_h7_i2s_regmap_conf, .get_i2s_clk_parent = stm32_i2s_get_parent_clk, }; static const struct stm32_i2s_conf stm32_i2s_conf_mp25 = { .regmap_conf = &stm32_h7_i2s_regmap_conf }; static const struct of_device_id stm32_i2s_ids[] = { { .compatible = "st,stm32h7-i2s", .data = &stm32_h7_i2s_regmap_conf }, { .compatible = "st,stm32h7-i2s", .data = &stm32_i2s_conf_h7 }, { .compatible = "st,stm32mp25-i2s", .data = &stm32_i2s_conf_mp25 }, {}, }; static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s) { struct device *dev = &i2s->pdev->dev; i2s->x8kclk = devm_clk_get(dev, "x8k"); if (IS_ERR(i2s->x8kclk)) return dev_err_probe(dev, PTR_ERR(i2s->x8kclk), "Cannot get x8k parent clock\n"); i2s->x11kclk = devm_clk_get(dev, "x11k"); if (IS_ERR(i2s->x11kclk)) return dev_err_probe(dev, PTR_ERR(i2s->x11kclk), "Cannot get x11k parent clock\n"); return 0; } static int stm32_i2s_parse_dt(struct platform_device *pdev, struct stm32_i2s_data *i2s) { Loading @@ -1031,8 +1195,8 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, if (!np) return -ENODEV; i2s->regmap_conf = device_get_match_data(&pdev->dev); if (!i2s->regmap_conf) i2s->conf = device_get_match_data(&pdev->dev); if (!i2s->conf) return -EINVAL; i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); Loading @@ -1052,15 +1216,18 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, return dev_err_probe(&pdev->dev, PTR_ERR(i2s->i2sclk), "Could not get i2sclk\n"); i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k"); if (IS_ERR(i2s->x8kclk)) return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x8kclk), "Could not get x8k parent clock\n"); if (i2s->conf->get_i2s_clk_parent) { i2s->set_i2s_clk_rate = stm32_i2s_set_parent_clock; } else { i2s->set_i2s_clk_rate = stm32_i2s_set_parent_rate; i2s->put_i2s_clk_rate = stm32_i2s_put_parent_rate; } i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k"); if (IS_ERR(i2s->x11kclk)) return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x11kclk), "Could not get x11k parent clock\n"); if (i2s->conf->get_i2s_clk_parent) { ret = i2s->conf->get_i2s_clk_parent(i2s); if (ret) return ret; } /* Register mclk provider if requested */ if (of_property_present(np, "#clock-cells")) { Loading Loading @@ -1126,7 +1293,7 @@ static int stm32_i2s_probe(struct platform_device *pdev) return ret; i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk", i2s->base, i2s->regmap_conf); i2s->base, i2s->conf->regmap_conf); if (IS_ERR(i2s->regmap)) return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap), "Regmap init error\n"); Loading Loading
Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml +33 −3 Original line number Diff line number Diff line Loading @@ -13,13 +13,11 @@ description: The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode. Only some SPI instances support I2S. allOf: - $ref: dai-common.yaml# properties: compatible: enum: - st,stm32h7-i2s - st,stm32mp25-i2s "#sound-dai-cells": const: 0 Loading @@ -33,6 +31,7 @@ properties: - description: clock feeding the internal clock generator. - description: I2S parent clock for sampling rates multiple of 8kHz. - description: I2S parent clock for sampling rates multiple of 11.025kHz. minItems: 2 clock-names: items: Loading @@ -40,6 +39,7 @@ properties: - const: i2sclk - const: x8k - const: x11k minItems: 2 interrupts: maxItems: 1 Loading Loading @@ -79,6 +79,36 @@ required: - dmas - dma-names allOf: - $ref: dai-common.yaml# - if: properties: compatible: contains: const: st,stm32h7-i2s then: properties: clocks: minItems: 4 clock-names: minItems: 4 - if: properties: compatible: contains: const: st,stm32mp25-i2s then: properties: clocks: maxItems: 2 clock-names: maxItems: 2 unevaluatedProperties: false examples: Loading
sound/soc/stm/stm32_i2s.c +189 −22 Original line number Diff line number Diff line Loading @@ -200,10 +200,13 @@ enum i2s_datlen { #define STM32_I2S_NAME_LEN 32 #define STM32_I2S_RATE_11K 11025 #define STM32_I2S_MAX_SAMPLE_RATE_8K 192000 #define STM32_I2S_MAX_SAMPLE_RATE_11K 176400 #define STM32_I2S_CLK_RATE_TOLERANCE 1000 /* ppm */ /** * struct stm32_i2s_data - private data of I2S * @regmap_conf: I2S register map configuration pointer * @conf: I2S configuration pointer * @regmap: I2S register map pointer * @pdev: device data pointer * @dai_drv: DAI driver pointer Loading @@ -224,11 +227,14 @@ enum i2s_datlen { * @divider: prescaler division ratio * @div: prescaler div field * @odd: prescaler odd field * @i2s_clk_flg: flag set while exclusivity on I2S kernel clock is active * @refcount: keep count of opened streams on I2S * @ms_flg: master mode flag. * @set_i2s_clk_rate: set I2S kernel clock rate * @put_i2s_clk_rate: put I2S kernel clock rate */ struct stm32_i2s_data { const struct regmap_config *regmap_conf; const struct stm32_i2s_conf *conf; struct regmap *regmap; struct platform_device *pdev; struct snd_soc_dai_driver *dai_drv; Loading @@ -249,8 +255,21 @@ struct stm32_i2s_data { unsigned int divider; unsigned int div; bool odd; bool i2s_clk_flg; int refcount; int ms_flg; int (*set_i2s_clk_rate)(struct stm32_i2s_data *i2s, unsigned int rate); void (*put_i2s_clk_rate)(struct stm32_i2s_data *i2s); }; /** * struct stm32_i2s_conf - I2S configuration * @regmap_conf: regmap configuration pointer * @get_i2s_clk_parent: get parent clock of I2S kernel clock */ struct stm32_i2s_conf { const struct regmap_config *regmap_conf; int (*get_i2s_clk_parent)(struct stm32_i2s_data *i2s); }; struct stm32_i2smclk_data { Loading @@ -261,6 +280,8 @@ struct stm32_i2smclk_data { #define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw) static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s); static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s, unsigned long input_rate, unsigned long output_rate) Loading Loading @@ -312,6 +333,33 @@ static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s) cgfr_mask, cgfr); } static bool stm32_i2s_rate_accurate(struct stm32_i2s_data *i2s, unsigned int max_rate, unsigned int rate) { struct platform_device *pdev = i2s->pdev; u64 delta, dividend; int ratio; if (!rate) { dev_err(&pdev->dev, "Unexpected null rate\n"); return false; } ratio = DIV_ROUND_CLOSEST(max_rate, rate); if (!ratio) return false; dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate))); delta = div_u64(dividend, max_rate); if (delta <= STM32_I2S_CLK_RATE_TOLERANCE) return true; dev_dbg(&pdev->dev, "Rate [%u] not accurate\n", rate); return false; } static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, unsigned int rate) { Loading @@ -332,6 +380,87 @@ static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s, return ret; } static void stm32_i2s_put_parent_rate(struct stm32_i2s_data *i2s) { if (i2s->i2s_clk_flg) { i2s->i2s_clk_flg = false; clk_rate_exclusive_put(i2s->i2sclk); } } static int stm32_i2s_set_parent_rate(struct stm32_i2s_data *i2s, unsigned int rate) { struct platform_device *pdev = i2s->pdev; unsigned int i2s_clk_rate, i2s_clk_max_rate, i2s_curr_rate, i2s_new_rate; int ret, div; /* * Set maximum expected kernel clock frequency * - mclk on: * f_i2s_ck = MCKDIV * mclk-fs * fs * Here typical 256 ratio is assumed for mclk-fs * - mclk off: * f_i2s_ck = MCKDIV * FRL * fs * Where FRL=[16,32], MCKDIV=[1..256] * f_i2s_ck = i2s_clk_max_rate * 32 / 256 */ if (!(rate % STM32_I2S_RATE_11K)) i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_11K * 256; else i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_8K * 256; if (!i2s->i2smclk) i2s_clk_max_rate /= 8; /* Request exclusivity, as the clock may be shared by I2S instances */ clk_rate_exclusive_get(i2s->i2sclk); i2s->i2s_clk_flg = true; /* * Check current kernel clock rate. If it gives the expected accuracy * return immediately. */ i2s_curr_rate = clk_get_rate(i2s->i2sclk); if (stm32_i2s_rate_accurate(i2s, i2s_clk_max_rate, i2s_curr_rate)) return 0; /* * Otherwise try to set the maximum rate and check the new actual rate. * If the new rate does not give the expected accuracy, try to set * lower rates for the kernel clock. */ i2s_clk_rate = i2s_clk_max_rate; div = 1; do { /* Check new rate accuracy. Return if ok */ i2s_new_rate = clk_round_rate(i2s->i2sclk, i2s_clk_rate); if (stm32_i2s_rate_accurate(i2s, i2s_clk_rate, i2s_new_rate)) { ret = clk_set_rate(i2s->i2sclk, i2s_clk_rate); if (ret) { dev_err(&pdev->dev, "Error %d setting i2s_clk_rate rate. %s", ret, ret == -EBUSY ? "Active stream rates may be in conflict\n" : "\n"); goto err; } return 0; } /* Try a lower frequency */ div++; i2s_clk_rate = i2s_clk_max_rate / div; } while (i2s_clk_rate > rate); /* no accurate rate found */ dev_err(&pdev->dev, "Failed to find an accurate rate"); err: stm32_i2s_put_parent_rate(i2s); return -EINVAL; } static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { Loading Loading @@ -635,12 +764,16 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, clk_rate_exclusive_put(i2s->i2smclk); i2s->mclk_rate = 0; } if (i2s->put_i2s_clk_rate) i2s->put_i2s_clk_rate(i2s); return regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG, I2S_CGFR_MCKOE, 0); } /* If master clock is used, set parent clock now */ ret = stm32_i2s_set_parent_clock(i2s, freq); ret = i2s->set_i2s_clk_rate(i2s, freq); if (ret) return ret; ret = clk_set_rate_exclusive(i2s->i2smclk, freq); Loading @@ -667,10 +800,11 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai, u32 cgfr; int ret; if (!(rate % 11025)) clk_set_parent(i2s->i2sclk, i2s->x11kclk); else clk_set_parent(i2s->i2sclk, i2s->x8kclk); if (!i2s->mclk_rate) { ret = i2s->set_i2s_clk_rate(i2s, rate); if (ret) return ret; } i2s_clock_rate = clk_get_rate(i2s->i2sclk); /* Loading Loading @@ -915,6 +1049,14 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, clk_disable_unprepare(i2s->i2sclk); /* * Release kernel clock if following conditions are fulfilled * - Master clock is not used. Kernel clock won't be released trough sysclk * - Put handler is defined. Involve that clock is managed exclusively */ if (!i2s->i2smclk && i2s->put_i2s_clk_rate) i2s->put_i2s_clk_rate(i2s); spin_lock_irqsave(&i2s->irq_lock, flags); i2s->substream = NULL; spin_unlock_irqrestore(&i2s->irq_lock, flags); Loading Loading @@ -1012,14 +1154,36 @@ static int stm32_i2s_dais_init(struct platform_device *pdev, return 0; } static const struct stm32_i2s_conf stm32_i2s_conf_h7 = { .regmap_conf = &stm32_h7_i2s_regmap_conf, .get_i2s_clk_parent = stm32_i2s_get_parent_clk, }; static const struct stm32_i2s_conf stm32_i2s_conf_mp25 = { .regmap_conf = &stm32_h7_i2s_regmap_conf }; static const struct of_device_id stm32_i2s_ids[] = { { .compatible = "st,stm32h7-i2s", .data = &stm32_h7_i2s_regmap_conf }, { .compatible = "st,stm32h7-i2s", .data = &stm32_i2s_conf_h7 }, { .compatible = "st,stm32mp25-i2s", .data = &stm32_i2s_conf_mp25 }, {}, }; static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s) { struct device *dev = &i2s->pdev->dev; i2s->x8kclk = devm_clk_get(dev, "x8k"); if (IS_ERR(i2s->x8kclk)) return dev_err_probe(dev, PTR_ERR(i2s->x8kclk), "Cannot get x8k parent clock\n"); i2s->x11kclk = devm_clk_get(dev, "x11k"); if (IS_ERR(i2s->x11kclk)) return dev_err_probe(dev, PTR_ERR(i2s->x11kclk), "Cannot get x11k parent clock\n"); return 0; } static int stm32_i2s_parse_dt(struct platform_device *pdev, struct stm32_i2s_data *i2s) { Loading @@ -1031,8 +1195,8 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, if (!np) return -ENODEV; i2s->regmap_conf = device_get_match_data(&pdev->dev); if (!i2s->regmap_conf) i2s->conf = device_get_match_data(&pdev->dev); if (!i2s->conf) return -EINVAL; i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); Loading @@ -1052,15 +1216,18 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev, return dev_err_probe(&pdev->dev, PTR_ERR(i2s->i2sclk), "Could not get i2sclk\n"); i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k"); if (IS_ERR(i2s->x8kclk)) return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x8kclk), "Could not get x8k parent clock\n"); if (i2s->conf->get_i2s_clk_parent) { i2s->set_i2s_clk_rate = stm32_i2s_set_parent_clock; } else { i2s->set_i2s_clk_rate = stm32_i2s_set_parent_rate; i2s->put_i2s_clk_rate = stm32_i2s_put_parent_rate; } i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k"); if (IS_ERR(i2s->x11kclk)) return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x11kclk), "Could not get x11k parent clock\n"); if (i2s->conf->get_i2s_clk_parent) { ret = i2s->conf->get_i2s_clk_parent(i2s); if (ret) return ret; } /* Register mclk provider if requested */ if (of_property_present(np, "#clock-cells")) { Loading Loading @@ -1126,7 +1293,7 @@ static int stm32_i2s_probe(struct platform_device *pdev) return ret; i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk", i2s->base, i2s->regmap_conf); i2s->base, i2s->conf->regmap_conf); if (IS_ERR(i2s->regmap)) return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap), "Regmap init error\n"); Loading