Skip to content

Commit 125d0f6

Browse files
committed
ASoC: stm32: i2s: add stm32mp25 support
Merge series from Olivier Moysan <[email protected]>: Update STM32 I2S driver and binding to support STM32MP25 SoCs.
2 parents b3ea5be + 20bf873 commit 125d0f6

File tree

2 files changed

+222
-25
lines changed

2 files changed

+222
-25
lines changed

Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@ description:
1313
The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
1414
Only some SPI instances support I2S.
1515

16-
allOf:
17-
- $ref: dai-common.yaml#
18-
1916
properties:
2017
compatible:
2118
enum:
2219
- st,stm32h7-i2s
20+
- st,stm32mp25-i2s
2321

2422
"#sound-dai-cells":
2523
const: 0
@@ -33,13 +31,15 @@ properties:
3331
- description: clock feeding the internal clock generator.
3432
- description: I2S parent clock for sampling rates multiple of 8kHz.
3533
- description: I2S parent clock for sampling rates multiple of 11.025kHz.
34+
minItems: 2
3635

3736
clock-names:
3837
items:
3938
- const: pclk
4039
- const: i2sclk
4140
- const: x8k
4241
- const: x11k
42+
minItems: 2
4343

4444
interrupts:
4545
maxItems: 1
@@ -79,6 +79,36 @@ required:
7979
- dmas
8080
- dma-names
8181

82+
allOf:
83+
- $ref: dai-common.yaml#
84+
- if:
85+
properties:
86+
compatible:
87+
contains:
88+
const: st,stm32h7-i2s
89+
90+
then:
91+
properties:
92+
clocks:
93+
minItems: 4
94+
95+
clock-names:
96+
minItems: 4
97+
98+
- if:
99+
properties:
100+
compatible:
101+
contains:
102+
const: st,stm32mp25-i2s
103+
104+
then:
105+
properties:
106+
clocks:
107+
maxItems: 2
108+
109+
clock-names:
110+
maxItems: 2
111+
82112
unevaluatedProperties: false
83113

84114
examples:

sound/soc/stm/stm32_i2s.c

Lines changed: 189 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,13 @@ enum i2s_datlen {
200200

201201
#define STM32_I2S_NAME_LEN 32
202202
#define STM32_I2S_RATE_11K 11025
203+
#define STM32_I2S_MAX_SAMPLE_RATE_8K 192000
204+
#define STM32_I2S_MAX_SAMPLE_RATE_11K 176400
205+
#define STM32_I2S_CLK_RATE_TOLERANCE 1000 /* ppm */
203206

204207
/**
205208
* struct stm32_i2s_data - private data of I2S
206-
* @regmap_conf: I2S register map configuration pointer
209+
* @conf: I2S configuration pointer
207210
* @regmap: I2S register map pointer
208211
* @pdev: device data pointer
209212
* @dai_drv: DAI driver pointer
@@ -224,11 +227,14 @@ enum i2s_datlen {
224227
* @divider: prescaler division ratio
225228
* @div: prescaler div field
226229
* @odd: prescaler odd field
230+
* @i2s_clk_flg: flag set while exclusivity on I2S kernel clock is active
227231
* @refcount: keep count of opened streams on I2S
228232
* @ms_flg: master mode flag.
233+
* @set_i2s_clk_rate: set I2S kernel clock rate
234+
* @put_i2s_clk_rate: put I2S kernel clock rate
229235
*/
230236
struct stm32_i2s_data {
231-
const struct regmap_config *regmap_conf;
237+
const struct stm32_i2s_conf *conf;
232238
struct regmap *regmap;
233239
struct platform_device *pdev;
234240
struct snd_soc_dai_driver *dai_drv;
@@ -249,8 +255,21 @@ struct stm32_i2s_data {
249255
unsigned int divider;
250256
unsigned int div;
251257
bool odd;
258+
bool i2s_clk_flg;
252259
int refcount;
253260
int ms_flg;
261+
int (*set_i2s_clk_rate)(struct stm32_i2s_data *i2s, unsigned int rate);
262+
void (*put_i2s_clk_rate)(struct stm32_i2s_data *i2s);
263+
};
264+
265+
/**
266+
* struct stm32_i2s_conf - I2S configuration
267+
* @regmap_conf: regmap configuration pointer
268+
* @get_i2s_clk_parent: get parent clock of I2S kernel clock
269+
*/
270+
struct stm32_i2s_conf {
271+
const struct regmap_config *regmap_conf;
272+
int (*get_i2s_clk_parent)(struct stm32_i2s_data *i2s);
254273
};
255274

256275
struct stm32_i2smclk_data {
@@ -261,6 +280,8 @@ struct stm32_i2smclk_data {
261280

262281
#define to_mclk_data(_hw) container_of(_hw, struct stm32_i2smclk_data, hw)
263282

283+
static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s);
284+
264285
static int stm32_i2s_calc_clk_div(struct stm32_i2s_data *i2s,
265286
unsigned long input_rate,
266287
unsigned long output_rate)
@@ -312,6 +333,33 @@ static int stm32_i2s_set_clk_div(struct stm32_i2s_data *i2s)
312333
cgfr_mask, cgfr);
313334
}
314335

336+
static bool stm32_i2s_rate_accurate(struct stm32_i2s_data *i2s,
337+
unsigned int max_rate, unsigned int rate)
338+
{
339+
struct platform_device *pdev = i2s->pdev;
340+
u64 delta, dividend;
341+
int ratio;
342+
343+
if (!rate) {
344+
dev_err(&pdev->dev, "Unexpected null rate\n");
345+
return false;
346+
}
347+
348+
ratio = DIV_ROUND_CLOSEST(max_rate, rate);
349+
if (!ratio)
350+
return false;
351+
352+
dividend = mul_u32_u32(1000000, abs(max_rate - (ratio * rate)));
353+
delta = div_u64(dividend, max_rate);
354+
355+
if (delta <= STM32_I2S_CLK_RATE_TOLERANCE)
356+
return true;
357+
358+
dev_dbg(&pdev->dev, "Rate [%u] not accurate\n", rate);
359+
360+
return false;
361+
}
362+
315363
static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s,
316364
unsigned int rate)
317365
{
@@ -332,6 +380,87 @@ static int stm32_i2s_set_parent_clock(struct stm32_i2s_data *i2s,
332380
return ret;
333381
}
334382

383+
static void stm32_i2s_put_parent_rate(struct stm32_i2s_data *i2s)
384+
{
385+
if (i2s->i2s_clk_flg) {
386+
i2s->i2s_clk_flg = false;
387+
clk_rate_exclusive_put(i2s->i2sclk);
388+
}
389+
}
390+
391+
static int stm32_i2s_set_parent_rate(struct stm32_i2s_data *i2s,
392+
unsigned int rate)
393+
{
394+
struct platform_device *pdev = i2s->pdev;
395+
unsigned int i2s_clk_rate, i2s_clk_max_rate, i2s_curr_rate, i2s_new_rate;
396+
int ret, div;
397+
398+
/*
399+
* Set maximum expected kernel clock frequency
400+
* - mclk on:
401+
* f_i2s_ck = MCKDIV * mclk-fs * fs
402+
* Here typical 256 ratio is assumed for mclk-fs
403+
* - mclk off:
404+
* f_i2s_ck = MCKDIV * FRL * fs
405+
* Where FRL=[16,32], MCKDIV=[1..256]
406+
* f_i2s_ck = i2s_clk_max_rate * 32 / 256
407+
*/
408+
if (!(rate % STM32_I2S_RATE_11K))
409+
i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_11K * 256;
410+
else
411+
i2s_clk_max_rate = STM32_I2S_MAX_SAMPLE_RATE_8K * 256;
412+
413+
if (!i2s->i2smclk)
414+
i2s_clk_max_rate /= 8;
415+
416+
/* Request exclusivity, as the clock may be shared by I2S instances */
417+
clk_rate_exclusive_get(i2s->i2sclk);
418+
i2s->i2s_clk_flg = true;
419+
420+
/*
421+
* Check current kernel clock rate. If it gives the expected accuracy
422+
* return immediately.
423+
*/
424+
i2s_curr_rate = clk_get_rate(i2s->i2sclk);
425+
if (stm32_i2s_rate_accurate(i2s, i2s_clk_max_rate, i2s_curr_rate))
426+
return 0;
427+
428+
/*
429+
* Otherwise try to set the maximum rate and check the new actual rate.
430+
* If the new rate does not give the expected accuracy, try to set
431+
* lower rates for the kernel clock.
432+
*/
433+
i2s_clk_rate = i2s_clk_max_rate;
434+
div = 1;
435+
do {
436+
/* Check new rate accuracy. Return if ok */
437+
i2s_new_rate = clk_round_rate(i2s->i2sclk, i2s_clk_rate);
438+
if (stm32_i2s_rate_accurate(i2s, i2s_clk_rate, i2s_new_rate)) {
439+
ret = clk_set_rate(i2s->i2sclk, i2s_clk_rate);
440+
if (ret) {
441+
dev_err(&pdev->dev, "Error %d setting i2s_clk_rate rate. %s",
442+
ret, ret == -EBUSY ?
443+
"Active stream rates may be in conflict\n" : "\n");
444+
goto err;
445+
}
446+
447+
return 0;
448+
}
449+
450+
/* Try a lower frequency */
451+
div++;
452+
i2s_clk_rate = i2s_clk_max_rate / div;
453+
} while (i2s_clk_rate > rate);
454+
455+
/* no accurate rate found */
456+
dev_err(&pdev->dev, "Failed to find an accurate rate");
457+
458+
err:
459+
stm32_i2s_put_parent_rate(i2s);
460+
461+
return -EINVAL;
462+
}
463+
335464
static long stm32_i2smclk_round_rate(struct clk_hw *hw, unsigned long rate,
336465
unsigned long *prate)
337466
{
@@ -635,12 +764,16 @@ static int stm32_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
635764
clk_rate_exclusive_put(i2s->i2smclk);
636765
i2s->mclk_rate = 0;
637766
}
767+
768+
if (i2s->put_i2s_clk_rate)
769+
i2s->put_i2s_clk_rate(i2s);
770+
638771
return regmap_update_bits(i2s->regmap,
639772
STM32_I2S_CGFR_REG,
640773
I2S_CGFR_MCKOE, 0);
641774
}
642775
/* If master clock is used, set parent clock now */
643-
ret = stm32_i2s_set_parent_clock(i2s, freq);
776+
ret = i2s->set_i2s_clk_rate(i2s, freq);
644777
if (ret)
645778
return ret;
646779
ret = clk_set_rate_exclusive(i2s->i2smclk, freq);
@@ -667,10 +800,11 @@ static int stm32_i2s_configure_clock(struct snd_soc_dai *cpu_dai,
667800
u32 cgfr;
668801
int ret;
669802

670-
if (!(rate % 11025))
671-
clk_set_parent(i2s->i2sclk, i2s->x11kclk);
672-
else
673-
clk_set_parent(i2s->i2sclk, i2s->x8kclk);
803+
if (!i2s->mclk_rate) {
804+
ret = i2s->set_i2s_clk_rate(i2s, rate);
805+
if (ret)
806+
return ret;
807+
}
674808
i2s_clock_rate = clk_get_rate(i2s->i2sclk);
675809

676810
/*
@@ -915,6 +1049,14 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream,
9151049

9161050
clk_disable_unprepare(i2s->i2sclk);
9171051

1052+
/*
1053+
* Release kernel clock if following conditions are fulfilled
1054+
* - Master clock is not used. Kernel clock won't be released trough sysclk
1055+
* - Put handler is defined. Involve that clock is managed exclusively
1056+
*/
1057+
if (!i2s->i2smclk && i2s->put_i2s_clk_rate)
1058+
i2s->put_i2s_clk_rate(i2s);
1059+
9181060
spin_lock_irqsave(&i2s->irq_lock, flags);
9191061
i2s->substream = NULL;
9201062
spin_unlock_irqrestore(&i2s->irq_lock, flags);
@@ -1012,14 +1154,36 @@ static int stm32_i2s_dais_init(struct platform_device *pdev,
10121154
return 0;
10131155
}
10141156

1157+
static const struct stm32_i2s_conf stm32_i2s_conf_h7 = {
1158+
.regmap_conf = &stm32_h7_i2s_regmap_conf,
1159+
.get_i2s_clk_parent = stm32_i2s_get_parent_clk,
1160+
};
1161+
1162+
static const struct stm32_i2s_conf stm32_i2s_conf_mp25 = {
1163+
.regmap_conf = &stm32_h7_i2s_regmap_conf
1164+
};
1165+
10151166
static const struct of_device_id stm32_i2s_ids[] = {
1016-
{
1017-
.compatible = "st,stm32h7-i2s",
1018-
.data = &stm32_h7_i2s_regmap_conf
1019-
},
1167+
{ .compatible = "st,stm32h7-i2s", .data = &stm32_i2s_conf_h7 },
1168+
{ .compatible = "st,stm32mp25-i2s", .data = &stm32_i2s_conf_mp25 },
10201169
{},
10211170
};
10221171

1172+
static int stm32_i2s_get_parent_clk(struct stm32_i2s_data *i2s)
1173+
{
1174+
struct device *dev = &i2s->pdev->dev;
1175+
1176+
i2s->x8kclk = devm_clk_get(dev, "x8k");
1177+
if (IS_ERR(i2s->x8kclk))
1178+
return dev_err_probe(dev, PTR_ERR(i2s->x8kclk), "Cannot get x8k parent clock\n");
1179+
1180+
i2s->x11kclk = devm_clk_get(dev, "x11k");
1181+
if (IS_ERR(i2s->x11kclk))
1182+
return dev_err_probe(dev, PTR_ERR(i2s->x11kclk), "Cannot get x11k parent clock\n");
1183+
1184+
return 0;
1185+
}
1186+
10231187
static int stm32_i2s_parse_dt(struct platform_device *pdev,
10241188
struct stm32_i2s_data *i2s)
10251189
{
@@ -1031,8 +1195,8 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
10311195
if (!np)
10321196
return -ENODEV;
10331197

1034-
i2s->regmap_conf = device_get_match_data(&pdev->dev);
1035-
if (!i2s->regmap_conf)
1198+
i2s->conf = device_get_match_data(&pdev->dev);
1199+
if (!i2s->conf)
10361200
return -EINVAL;
10371201

10381202
i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
@@ -1052,15 +1216,18 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
10521216
return dev_err_probe(&pdev->dev, PTR_ERR(i2s->i2sclk),
10531217
"Could not get i2sclk\n");
10541218

1055-
i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k");
1056-
if (IS_ERR(i2s->x8kclk))
1057-
return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x8kclk),
1058-
"Could not get x8k parent clock\n");
1219+
if (i2s->conf->get_i2s_clk_parent) {
1220+
i2s->set_i2s_clk_rate = stm32_i2s_set_parent_clock;
1221+
} else {
1222+
i2s->set_i2s_clk_rate = stm32_i2s_set_parent_rate;
1223+
i2s->put_i2s_clk_rate = stm32_i2s_put_parent_rate;
1224+
}
10591225

1060-
i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k");
1061-
if (IS_ERR(i2s->x11kclk))
1062-
return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x11kclk),
1063-
"Could not get x11k parent clock\n");
1226+
if (i2s->conf->get_i2s_clk_parent) {
1227+
ret = i2s->conf->get_i2s_clk_parent(i2s);
1228+
if (ret)
1229+
return ret;
1230+
}
10641231

10651232
/* Register mclk provider if requested */
10661233
if (of_property_present(np, "#clock-cells")) {
@@ -1126,7 +1293,7 @@ static int stm32_i2s_probe(struct platform_device *pdev)
11261293
return ret;
11271294

11281295
i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk",
1129-
i2s->base, i2s->regmap_conf);
1296+
i2s->base, i2s->conf->regmap_conf);
11301297
if (IS_ERR(i2s->regmap))
11311298
return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap),
11321299
"Regmap init error\n");

0 commit comments

Comments
 (0)