Skip to content

Commit 30def77

Browse files
[nrf fromlist] drivers: i2s: nrfx_i2s: introduce prescaler calculation
Added usage of new API responsible for calculating I2S prescaler values. Upstream PR #: 96703 Signed-off-by: Michał Stasiak <[email protected]>
1 parent 0da33f6 commit 30def77

File tree

1 file changed

+6
-131
lines changed

1 file changed

+6
-131
lines changed

drivers/i2s/i2s_nrfx.c

Lines changed: 6 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,6 @@ static void find_suitable_clock(const struct i2s_nrfx_drv_cfg *drv_cfg,
6464
nrfx_i2s_config_t *config,
6565
const struct i2s_config *i2s_cfg)
6666
{
67-
static const struct {
68-
uint16_t ratio_val;
69-
nrf_i2s_ratio_t ratio_enum;
70-
} ratios[] = {
71-
{ 32, NRF_I2S_RATIO_32X },
72-
{ 48, NRF_I2S_RATIO_48X },
73-
{ 64, NRF_I2S_RATIO_64X },
74-
{ 96, NRF_I2S_RATIO_96X },
75-
{ 128, NRF_I2S_RATIO_128X },
76-
{ 192, NRF_I2S_RATIO_192X },
77-
{ 256, NRF_I2S_RATIO_256X },
78-
{ 384, NRF_I2S_RATIO_384X },
79-
{ 512, NRF_I2S_RATIO_512X }
80-
};
8167
const uint32_t src_freq =
8268
(NRF_I2S_HAS_CLKCONFIG && drv_cfg->clk_src == ACLK)
8369
/* The I2S_NRFX_DEVICE() macro contains build assertions that
@@ -89,123 +75,12 @@ static void find_suitable_clock(const struct i2s_nrfx_drv_cfg *drv_cfg,
8975
*/
9076
? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency, 0)
9177
: 32*1000*1000UL;
92-
uint32_t bits_per_frame = 2 * i2s_cfg->word_size;
93-
uint32_t best_diff = UINT32_MAX;
94-
uint8_t r, best_r = 0;
95-
nrf_i2s_mck_t best_mck_cfg = 0;
96-
uint32_t best_mck = 0;
97-
98-
#if defined(CONFIG_I2S_NRFX_ALLOW_MCK_BYPASS) && NRF_I2S_HAS_CLKCONFIG
99-
/* Check for bypass before calculating f_MCK */
100-
for (r = 0; r < ARRAY_SIZE(ratios); ++r) {
101-
if (i2s_cfg->frame_clk_freq * ratios[r].ratio_val == src_freq) {
102-
LOG_INF("MCK bypass calculated");
103-
best_r = r;
104-
best_mck = src_freq;
105-
best_diff = 0;
106-
107-
/* Set CONFIG.MCKFREQ register to non-zero reset value to
108-
* ensure peripheral functionality
109-
*/
110-
best_mck_cfg = NRF_I2S_MCK_32MDIV8;
111-
112-
config->enable_bypass = true;
113-
break;
114-
}
115-
}
116-
#endif
117-
118-
for (r = 0; (best_diff != 0) && (r < ARRAY_SIZE(ratios)); ++r) {
119-
/* Only multiples of the frame width can be used as ratios. */
120-
if ((ratios[r].ratio_val % bits_per_frame) != 0) {
121-
continue;
122-
}
123-
124-
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X) || IS_ENABLED(CONFIG_SOC_SERIES_NRF54LX)) {
125-
uint32_t requested_mck =
126-
i2s_cfg->frame_clk_freq * ratios[r].ratio_val;
127-
/* As specified in the nRF5340 PS:
128-
*
129-
* MCKFREQ = 4096 * floor(f_MCK * 1048576 /
130-
* (f_source + f_MCK / 2))
131-
* f_actual = f_source /
132-
* floor(1048576 * 4096 / MCKFREQ)
133-
*/
134-
enum { MCKCONST = 1048576 };
135-
uint32_t mck_factor =
136-
(uint32_t)(((uint64_t)requested_mck * MCKCONST) /
137-
(src_freq + requested_mck / 2));
138-
139-
/* skip cases when mck_factor is too big for dividing */
140-
if (mck_factor > MCKCONST) {
141-
continue;
142-
}
143-
uint32_t actual_mck = src_freq / (MCKCONST / mck_factor);
144-
145-
uint32_t lrck_freq = actual_mck / ratios[r].ratio_val;
146-
uint32_t diff = lrck_freq >= i2s_cfg->frame_clk_freq
147-
? (lrck_freq - i2s_cfg->frame_clk_freq)
148-
: (i2s_cfg->frame_clk_freq - lrck_freq);
149-
150-
if (diff < best_diff) {
151-
best_mck_cfg = mck_factor * 4096;
152-
best_mck = actual_mck;
153-
best_r = r;
154-
best_diff = diff;
155-
}
156-
} else {
157-
static const struct {
158-
uint8_t divider_val;
159-
nrf_i2s_mck_t divider_enum;
160-
} dividers[] = {
161-
{ 8, NRF_I2S_MCK_32MDIV8 },
162-
{ 10, NRF_I2S_MCK_32MDIV10 },
163-
{ 11, NRF_I2S_MCK_32MDIV11 },
164-
{ 15, NRF_I2S_MCK_32MDIV15 },
165-
{ 16, NRF_I2S_MCK_32MDIV16 },
166-
{ 21, NRF_I2S_MCK_32MDIV21 },
167-
{ 23, NRF_I2S_MCK_32MDIV23 },
168-
{ 30, NRF_I2S_MCK_32MDIV30 },
169-
{ 31, NRF_I2S_MCK_32MDIV31 },
170-
{ 32, NRF_I2S_MCK_32MDIV32 },
171-
{ 42, NRF_I2S_MCK_32MDIV42 },
172-
{ 63, NRF_I2S_MCK_32MDIV63 },
173-
{ 125, NRF_I2S_MCK_32MDIV125 }
174-
};
175-
176-
for (uint8_t d = 0; (best_diff != 0) && (d < ARRAY_SIZE(dividers)); ++d) {
177-
uint32_t mck_freq =
178-
src_freq / dividers[d].divider_val;
179-
uint32_t lrck_freq =
180-
mck_freq / ratios[r].ratio_val;
181-
uint32_t diff =
182-
lrck_freq >= i2s_cfg->frame_clk_freq
183-
? (lrck_freq - i2s_cfg->frame_clk_freq)
184-
: (i2s_cfg->frame_clk_freq - lrck_freq);
185-
186-
if (diff < best_diff) {
187-
best_mck_cfg = dividers[d].divider_enum;
188-
best_mck = mck_freq;
189-
best_r = r;
190-
best_diff = diff;
191-
}
19278

193-
/* Since dividers are in ascending order, stop
194-
* checking next ones for the current ratio
195-
* after resulting LRCK frequency falls below
196-
* the one requested.
197-
*/
198-
if (lrck_freq < i2s_cfg->frame_clk_freq) {
199-
break;
200-
}
201-
}
202-
}
79+
if (nrfx_i2s_prescalers_calc(src_freq, i2s_cfg->frame_clk_freq, config->sample_width,
80+
IS_ENABLED(CONFIG_I2S_NRFX_ALLOW_MCK_BYPASS),
81+
&config->prescalers) != NRFX_SUCCESS) {
82+
LOG_ERR("Failed to find suitable I2S clock configuration.");
20383
}
204-
205-
config->mck_setup = best_mck_cfg;
206-
config->ratio = ratios[best_r].ratio_enum;
207-
LOG_INF("I2S MCK frequency: %u, actual PCM rate: %u",
208-
best_mck, best_mck / ratios[best_r].ratio_val);
20984
}
21085

21186
static bool get_next_tx_buffer(struct i2s_nrfx_drv_data *drv_data,
@@ -551,7 +426,7 @@ static int i2s_nrfx_configure(const struct device *dev, enum i2s_dir dir,
551426
*/
552427
drv_data->request_clock = (drv_cfg->clk_src != PCLK32M);
553428
} else {
554-
nrfx_cfg.mck_setup = NRF_I2S_MCK_DISABLED;
429+
nrfx_cfg.prescalers.mck_setup = NRF_I2S_MCK_DISABLED;
555430
drv_data->request_clock = false;
556431
}
557432

@@ -780,7 +655,7 @@ static int trigger_start(const struct device *dev)
780655
nrf_i2s_clk_configure(drv_cfg->i2s.p_reg,
781656
drv_cfg->clk_src == ACLK ? NRF_I2S_CLKSRC_ACLK
782657
: NRF_I2S_CLKSRC_PCLK32M,
783-
nrfx_cfg->enable_bypass);
658+
nrfx_cfg->prescalers.enable_bypass);
784659
#endif
785660

786661
/* If it is required to use certain HF clock, request it to be running

0 commit comments

Comments
 (0)