Lines Matching +full:half +full:- +full:and +full:- +full:full +full:- +full:cycle
4 * SPDX-License-Identifier: Apache-2.0
22 #define dai_set_drvdata(dai, data) (dai->priv_data = data)
23 #define dai_get_drvdata(dai) dai->priv_data
24 #define dai_get_plat_data(dai) dai->ssp_plat_data
25 #define dai_get_mn(dai) dai->ssp_plat_data->mn_inst
26 #define dai_get_ftable(dai) dai->ssp_plat_data->ftable
27 #define dai_get_fsources(dai) dai->ssp_plat_data->fsources
28 #define dai_mn_base(dai) dai->ssp_plat_data->mn_inst->base
29 #define dai_base(dai) dai->ssp_plat_data->base
30 #define dai_ip_base(dai) dai->ssp_plat_data->ip_base
31 #define dai_shim_base(dai) dai->ssp_plat_data->shim_base
32 #define dai_hdamlssp_base(dai) dai->ssp_plat_data->hdamlssp_base
33 #define dai_i2svss_base(dai) dai->ssp_plat_data->i2svss_base
140 * gcd(a, b) = gcd(-a, -b) = gcd(-a, b) = gcd(a, -b) in dai_ssp_gcd()
143 a = -a; in dai_ssp_gcd()
147 b = -b; in dai_ssp_gcd()
150 /* Find the greatest power of 2 that devides both a and b */ in dai_ssp_gcd()
167 /* both a and b are odd now. Swap so a <= b in dai_ssp_gcd()
168 * then set b = b - a, which is also even in dai_ssp_gcd()
176 b = b - a; in dai_ssp_gcd()
196 for (i = 0; i < ARRAY_SIZE(mp->mclk_sources_ref); i++) { in dai_ssp_is_mclk_source_in_use()
197 if (mp->mclk_sources_ref[i] > 0) { in dai_ssp_is_mclk_source_in_use()
219 int clk_index = -1; in dai_ssp_setup_initial_mclk_source()
227 ret = -EINVAL; in dai_ssp_setup_initial_mclk_source()
241 ret = -EINVAL; in dai_ssp_setup_initial_mclk_source()
245 mp->mclk_source_clock = clk_index; in dai_ssp_setup_initial_mclk_source()
252 /* clear source mclk clock - bits 17-16 */ in dai_ssp_setup_initial_mclk_source()
260 mp->mclk_sources_ref[mclk_id]++; in dai_ssp_setup_initial_mclk_source()
279 LOG_INF("MCLK %d, source = %d", mclk_rate, mp->mclk_source_clock); in dai_ssp_check_current_mclk_source()
281 if (ft[mp->mclk_source_clock].freq % mclk_rate != 0) { in dai_ssp_check_current_mclk_source()
283 mclk_rate, mp->mclk_source_clock); in dai_ssp_check_current_mclk_source()
284 ret = -EINVAL; in dai_ssp_check_current_mclk_source()
288 if (mp->mclk_sources_ref[mclk_id] > 0) { in dai_ssp_check_current_mclk_source()
289 if (mp->mclk_rate[mclk_id] != mclk_rate) { in dai_ssp_check_current_mclk_source()
291 mclk_id, mclk_rate, mp->mclk_rate[mclk_id]); in dai_ssp_check_current_mclk_source()
292 return -EINVAL; in dai_ssp_check_current_mclk_source()
295 mp->mclk_sources_ref[mclk_id]++; in dai_ssp_check_current_mclk_source()
303 mp->mclk_sources_ref[mclk_id]++; in dai_ssp_check_current_mclk_source()
325 mdivr = mdivr_val - 2; /* 1/n */ in dai_ssp_set_mclk_divider()
329 return -EINVAL; in dai_ssp_set_mclk_divider()
346 return -EINVAL; in dai_ssp_mn_set_mclk()
349 key = k_spin_lock(&mp->lock); in dai_ssp_mn_set_mclk()
361 LOG_INF("mclk_rate %d, mclk_source_clock %d", mclk_rate, mp->mclk_source_clock); in dai_ssp_mn_set_mclk()
363 ret = dai_ssp_set_mclk_divider(dp, mclk_id, ft[mp->mclk_source_clock].freq / mclk_rate); in dai_ssp_mn_set_mclk()
365 mp->mclk_rate[mclk_id] = mclk_rate; in dai_ssp_mn_set_mclk()
369 k_spin_unlock(&mp->lock, key); in dai_ssp_mn_set_mclk()
388 key = k_spin_lock(&mp->lock); in dai_ssp_mn_release_mclk()
390 mp->mclk_sources_ref[mclk_id]--; in dai_ssp_mn_release_mclk()
393 if (!mp->mclk_sources_ref[mclk_id]) { in dai_ssp_mn_release_mclk()
404 /* clear source mclk clock - bits 17-16 */ in dai_ssp_mn_release_mclk()
409 mp->mclk_source_clock = 0; in dai_ssp_mn_release_mclk()
411 k_spin_unlock(&mp->lock, key); in dai_ssp_mn_release_mclk()
445 /* odd SCR gives lower duty cycle */ in dai_ssp_find_mn()
447 --scr_div; in dai_ssp_find_mn()
455 scr_div -= 2; in dai_ssp_find_mn()
458 /* compute M/N with smallest dividend and divisor */ in dai_ssp_find_mn()
485 * \return index of suitable clock if could find it, -EINVAL otherwise.
496 if (dai_ssp_find_mn(ft[mp->mclk_source_clock].freq, bclk, scr_div, m, n)) { in dai_ssp_find_bclk_source()
497 return mp->mclk_source_clock; in dai_ssp_find_bclk_source()
501 ft[mp->mclk_source_clock].freq); in dai_ssp_find_bclk_source()
519 return -EINVAL; in dai_ssp_find_bclk_source()
524 * \return the index in ssp_freq if could find it, -EINVAL otherwise.
538 return -EINVAL; in dai_ssp_find_clk_ssp_index()
552 for (i = 0; i < ARRAY_SIZE(mp->bclk_sources); i++) { in dai_ssp_is_bclk_source_in_use()
553 if (mp->bclk_sources[i] == clk_src) { in dai_ssp_is_bclk_source_in_use()
582 return -EINVAL; in dai_ssp_setup_initial_bclk_mn_source()
585 mp->bclk_source_mn_clock = clk_index; in dai_ssp_setup_initial_bclk_mn_source()
589 /* clear source bclk clock - 21-20 bits */ in dai_ssp_setup_initial_bclk_mn_source()
624 mp->bclk_source_mn_clock = clk_index; in dai_ssp_reset_bclk_mn_source()
644 if (dai_ssp_find_mn(ft[mp->bclk_source_mn_clock].freq, bclk, scr_div, m, n)) { in dai_ssp_setup_current_bclk_mn_source()
649 bclk, mp->bclk_source_mn_clock); in dai_ssp_setup_current_bclk_mn_source()
650 ret = -EINVAL; in dai_ssp_setup_current_bclk_mn_source()
674 key = k_spin_lock(&mp->lock); in dai_ssp_mn_set_bclk()
676 mp->bclk_sources[dai_index] = MN_BCLK_SOURCE_NONE; in dai_ssp_mn_set_bclk()
681 mp->bclk_sources[dai_index] = MN_BCLK_SOURCE_XTAL; in dai_ssp_mn_set_bclk()
695 mp->bclk_sources[dai_index] = MN_BCLK_SOURCE_MN; in dai_ssp_mn_set_bclk()
705 k_spin_unlock(&mp->lock, key); in dai_ssp_mn_set_bclk()
716 key = k_spin_lock(&mp->lock); in dai_ssp_mn_release_bclk()
717 mp->bclk_sources[ssp_index] = MN_BCLK_SOURCE_NONE; in dai_ssp_mn_release_bclk()
725 k_spin_unlock(&mp->lock, key); in dai_ssp_mn_release_bclk()
733 key = k_spin_lock(&mp->lock); in dai_ssp_mn_reset_bclk_divider()
738 k_spin_unlock(&mp->lock, key); in dai_ssp_mn_reset_bclk_divider()
748 return -EIO; in dai_ssp_poll_for_register_delay()
763 SHIM_CLKCTL_I2SEFDCGB(ssp_index - in dai_ssp_pm_runtime_dis_ssp_clk_gating()
781 SHIM_CLKCTL_I2SEFDCGB(ssp_index - in dai_ssp_pm_runtime_en_ssp_clk_gating()
864 uint16_t pcmsycm = cfg->link_config; in dai_ssp_program_channel_map()
866 pcmsycm = pcmsycm | (dp->ssp_plat_data->params.tdm_slots - 1) << 4; in dai_ssp_program_channel_map()
868 if (IS_BIT_SET(cfg->link_config, 15)) { in dai_ssp_program_channel_map()
881 uint16_t pcmsycm = cfg->link_config; in dai_ssp_program_channel_map()
884 if (IS_BIT_SET(cfg->link_config, 15)) { in dai_ssp_program_channel_map()
885 if (blob30->version == SSP_BLOB_VER_3_0) { in dai_ssp_program_channel_map()
887 blob30->i2s_ssp_config.ssmidytsa[cfg->tdm_slot_group]; in dai_ssp_program_channel_map()
890 blob->i2s_driver_config.i2s_config.ssmidytsa[cfg->tdm_slot_group]; in dai_ssp_program_channel_map()
893 pcmsycm = cfg->link_config | (slot_count - 1) << 4; in dai_ssp_program_channel_map()
895 PCMSyCM_OFFSET(cfg->tdm_slot_group); in dai_ssp_program_channel_map()
901 if (blob30->version == SSP_BLOB_VER_3_0) { in dai_ssp_program_channel_map()
903 blob30->i2s_ssp_config.ssmodytsa[cfg->tdm_slot_group]; in dai_ssp_program_channel_map()
906 blob->i2s_driver_config.i2s_config.ssmodytsa[cfg->tdm_slot_group]; in dai_ssp_program_channel_map()
909 pcmsycm = cfg->link_config | (slot_count - 1) << 4; in dai_ssp_program_channel_map()
911 PCMSyCM_OFFSET(cfg->tdm_slot_group + I2SOPCMC); in dai_ssp_program_channel_map()
931 * SSSR_TNF is cleared when TX FIFO is empty or full, in dai_ssp_empty_tx_fifo()
932 * so wait for set TNF then for TFL zero - order matter. in dai_ssp_empty_tx_fifo()
935 ret = dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(dp->tdm_slot_group), in dai_ssp_empty_tx_fifo()
939 ret |= dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(dp->tdm_slot_group), in dai_ssp_empty_tx_fifo()
942 (DAI_INTEL_SSP_FIFO_DEPTH - 1) / 2); in dai_ssp_empty_tx_fifo()
948 (DAI_INTEL_SSP_FIFO_DEPTH - 1) / 2); in dai_ssp_empty_tx_fifo()
981 /* Re-read the SSSR register */ in ssp_empty_rx_fifo_on_start()
986 while ((sys_read32(dai_base(dp) + SSMIDyCS(idx)) & SSMIDyCS_RNE) && retry--) { in ssp_empty_rx_fifo_on_start()
1003 uint64_t sample_ticks = ssp_plat_data->params.fsync_rate ? in ssp_empty_rx_fifo_on_stop()
1004 1000000 / ssp_plat_data->params.fsync_rate : 0; in ssp_empty_rx_fifo_on_stop()
1011 entries[0] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(dp->tdm_slot_group))); in ssp_empty_rx_fifo_on_stop()
1013 while ((sys_read32(dai_base(dp) + SSMIDyCS(dp->tdm_slot_group)) & in ssp_empty_rx_fifo_on_stop()
1014 SSMIDyCS_RNE) && retry--) { in ssp_empty_rx_fifo_on_stop()
1019 SSMIDyCS(dp->tdm_slot_group))); in ssp_empty_rx_fifo_on_stop()
1021 ssmidycs = sys_read32(dai_base(dp) + SSMIDyCS(dp->tdm_slot_group)); in ssp_empty_rx_fifo_on_stop()
1036 sys_read32(dai_base(dp) + SSMIDyD(dp->tdm_slot_group)); in ssp_empty_rx_fifo_on_stop()
1062 /* Re-read the SSSR register */ in ssp_empty_rx_fifo_on_start()
1066 while ((sssr & SSSR_RNE) && retry--) { in ssp_empty_rx_fifo_on_start()
1081 uint64_t sample_ticks = ssp_plat_data->params.fsync_rate ? in ssp_empty_rx_fifo_on_stop()
1082 1000000 / ssp_plat_data->params.fsync_rate : 0; in ssp_empty_rx_fifo_on_stop()
1090 while ((sssr & SSSR_RNE) && retry--) { in ssp_empty_rx_fifo_on_stop()
1128 if (ssp_plat_data->clk_active & SSP_CLK_MCLK_ACTIVE) { in dai_ssp_mclk_prepare_enable()
1133 ret = dai_ssp_mn_set_mclk(dp, ssp_plat_data->params.mclk_id, in dai_ssp_mclk_prepare_enable()
1134 ssp_plat_data->params.mclk_rate); in dai_ssp_mclk_prepare_enable()
1136 LOG_ERR("invalid mclk_rate = %d for mclk_id = %d", ssp_plat_data->params.mclk_rate, in dai_ssp_mclk_prepare_enable()
1137 ssp_plat_data->params.mclk_id); in dai_ssp_mclk_prepare_enable()
1139 ssp_plat_data->clk_active |= SSP_CLK_MCLK_ACTIVE; in dai_ssp_mclk_prepare_enable()
1149 if (!(ssp_plat_data->clk_active & SSP_CLK_MCLK_ACTIVE)) { in dai_ssp_mclk_disable_unprepare()
1153 dai_ssp_mn_release_mclk(dp, ssp_plat_data->params.mclk_id); in dai_ssp_mclk_disable_unprepare()
1155 ssp_plat_data->clk_active &= ~SSP_CLK_MCLK_ACTIVE; in dai_ssp_mclk_disable_unprepare()
1168 if (ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE) { in dai_ssp_bclk_prepare_enable()
1177 ret = dai_ssp_mn_set_bclk(dp, dp->dai_index, ssp_plat_data->params.bclk_rate, in dai_ssp_bclk_prepare_enable()
1181 ssp_plat_data->params.bclk_rate, dp->dai_index); in dai_ssp_bclk_prepare_enable()
1185 if (ft[DAI_INTEL_SSP_DEFAULT_IDX].freq % ssp_plat_data->params.bclk_rate != 0) { in dai_ssp_bclk_prepare_enable()
1187 ssp_plat_data->params.bclk_rate, dp->dai_index); in dai_ssp_bclk_prepare_enable()
1188 ret = -EINVAL; in dai_ssp_bclk_prepare_enable()
1192 mdiv = ft[DAI_INTEL_SSP_DEFAULT_IDX].freq / ssp_plat_data->params.bclk_rate; in dai_ssp_bclk_prepare_enable()
1202 mdiv -= 1; in dai_ssp_bclk_prepare_enable()
1207 ret = -EINVAL; in dai_ssp_bclk_prepare_enable()
1220 ssp_plat_data->clk_active |= SSP_CLK_BCLK_ACTIVE; in dai_ssp_bclk_prepare_enable()
1230 if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE)) { in dai_ssp_bclk_disable_unprepare()
1234 dai_ssp_mn_release_bclk(dp, ssp_plat_data->ssp_index); in dai_ssp_bclk_disable_unprepare()
1236 ssp_plat_data->clk_active &= ~SSP_CLK_BCLK_ACTIVE; in dai_ssp_bclk_disable_unprepare()
1241 LOG_INF("dai index: %u", dp->dai_index); in dai_ssp_log_ssp_data()
1242 LOG_INF("plat_data base: %u", dp->ssp_plat_data->base); in dai_ssp_log_ssp_data()
1243 LOG_INF("plat_data irq: %u", dp->ssp_plat_data->irq); in dai_ssp_log_ssp_data()
1245 dp->ssp_plat_data->fifo[DAI_DIR_PLAYBACK].offset); in dai_ssp_log_ssp_data()
1247 dp->ssp_plat_data->fifo[DAI_DIR_PLAYBACK].handshake); in dai_ssp_log_ssp_data()
1249 dp->ssp_plat_data->fifo[DAI_DIR_CAPTURE].offset); in dai_ssp_log_ssp_data()
1251 dp->ssp_plat_data->fifo[DAI_DIR_CAPTURE].handshake); in dai_ssp_log_ssp_data()
1292 key = k_spin_lock(&dp->lock); in dai_ssp_set_config_tplg()
1295 if (dp->state[DAI_DIR_PLAYBACK] > DAI_STATE_READY || in dai_ssp_set_config_tplg()
1296 dp->state[DAI_DIR_CAPTURE] > DAI_STATE_READY) { in dai_ssp_set_config_tplg()
1297 if (!memcmp(&ssp_plat_data->params, bespoke_cfg, in dai_ssp_set_config_tplg()
1303 if (ssp_plat_data->clk_active & in dai_ssp_set_config_tplg()
1309 /* safe to proceed and change HW config */ in dai_ssp_set_config_tplg()
1312 LOG_INF("SSP%d", dp->dai_index); in dai_ssp_set_config_tplg()
1334 ssp->config = *config; in dai_ssp_set_config_tplg()
1335 memcpy(&ssp_plat_data->params, bespoke_cfg, sizeof(struct dai_intel_ipc3_ssp_params)); in dai_ssp_set_config_tplg()
1347 sstsa = SSTSA_SSTSA(ssp_plat_data->params.tx_slots); in dai_ssp_set_config_tplg()
1350 ssrsa = SSRSA_SSRSA(ssp_plat_data->params.rx_slots); in dai_ssp_set_config_tplg()
1352 switch (config->format & DAI_INTEL_IPC3_SSP_FMT_CLOCK_PROVIDER_MASK) { in dai_ssp_set_config_tplg()
1372 ret = -EINVAL; in dai_ssp_set_config_tplg()
1377 switch (config->format & DAI_INTEL_IPC3_SSP_FMT_INV_MASK) { in dai_ssp_set_config_tplg()
1392 ret = -EINVAL; in dai_ssp_set_config_tplg()
1397 if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_IDLE_HIGH) { in dai_ssp_set_config_tplg()
1409 /* Receiver Time-out Interrupt Disabled/Enabled */ in dai_ssp_set_config_tplg()
1410 sscr1 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_TINTE) ? in dai_ssp_set_config_tplg()
1414 sscr1 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PINTE) ? in dai_ssp_set_config_tplg()
1420 sscr1 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_LBM) ? in dai_ssp_set_config_tplg()
1423 if (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_LBM) { in dai_ssp_set_config_tplg()
1432 sscr2 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_SMTATF) ? in dai_ssp_set_config_tplg()
1438 sscr2 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_MMRATF) ? in dai_ssp_set_config_tplg()
1442 * de-assertion before starting the second channel in dai_ssp_set_config_tplg()
1444 sscr2 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PSPSTWFDFD) ? in dai_ssp_set_config_tplg()
1450 sscr2 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PSPSRWFDFD) ? in dai_ssp_set_config_tplg()
1453 if (!ssp_plat_data->params.mclk_rate || in dai_ssp_set_config_tplg()
1454 ssp_plat_data->params.mclk_rate > ft[DAI_INTEL_SSP_MAX_FREQ_INDEX].freq) { in dai_ssp_set_config_tplg()
1455 LOG_ERR("invalid MCLK = %d Hz (valid < %d)", ssp_plat_data->params.mclk_rate, in dai_ssp_set_config_tplg()
1457 ret = -EINVAL; in dai_ssp_set_config_tplg()
1461 if (!ssp_plat_data->params.bclk_rate || in dai_ssp_set_config_tplg()
1462 ssp_plat_data->params.bclk_rate > ssp_plat_data->params.mclk_rate) { in dai_ssp_set_config_tplg()
1463 LOG_ERR("BCLK %d Hz = 0 or > MCLK %d Hz", ssp_plat_data->params.bclk_rate, in dai_ssp_set_config_tplg()
1464 ssp_plat_data->params.mclk_rate); in dai_ssp_set_config_tplg()
1465 ret = -EINVAL; in dai_ssp_set_config_tplg()
1469 /* calc frame width based on BCLK and rate - must be divisible */ in dai_ssp_set_config_tplg()
1470 if (ssp_plat_data->params.bclk_rate % ssp_plat_data->params.fsync_rate) { in dai_ssp_set_config_tplg()
1471 LOG_ERR("BCLK %d is not divisible by rate %d", ssp_plat_data->params.bclk_rate, in dai_ssp_set_config_tplg()
1472 ssp_plat_data->params.fsync_rate); in dai_ssp_set_config_tplg()
1473 ret = -EINVAL; in dai_ssp_set_config_tplg()
1478 bdiv = ssp_plat_data->params.bclk_rate / ssp_plat_data->params.fsync_rate; in dai_ssp_set_config_tplg()
1479 if (bdiv < ssp_plat_data->params.tdm_slot_width * ssp_plat_data->params.tdm_slots) { in dai_ssp_set_config_tplg()
1481 ssp_plat_data->params.tdm_slot_width * ssp_plat_data->params.tdm_slots); in dai_ssp_set_config_tplg()
1482 ret = -EINVAL; in dai_ssp_set_config_tplg()
1487 if (ssp_plat_data->params.tdm_slot_width > 38) { in dai_ssp_set_config_tplg()
1488 LOG_ERR("tdm_slot_width %d > 38", ssp_plat_data->params.tdm_slot_width); in dai_ssp_set_config_tplg()
1489 ret = -EINVAL; in dai_ssp_set_config_tplg()
1493 bdiv_min = ssp_plat_data->params.tdm_slots * in dai_ssp_set_config_tplg()
1494 (ssp_plat_data->params.tdm_per_slot_padding_flag ? in dai_ssp_set_config_tplg()
1495 ssp_plat_data->params.tdm_slot_width : ssp_plat_data->params.sample_valid_bits); in dai_ssp_set_config_tplg()
1498 ret = -EINVAL; in dai_ssp_set_config_tplg()
1502 frame_end_padding = bdiv - bdiv_min; in dai_ssp_set_config_tplg()
1505 ret = -EINVAL; in dai_ssp_set_config_tplg()
1510 switch (config->format & DAI_INTEL_IPC3_SSP_FMT_FORMAT_MASK) { in dai_ssp_set_config_tplg()
1515 sscr0 |= SSCR0_FRDC(ssp_plat_data->params.tdm_slots); in dai_ssp_set_config_tplg()
1519 ret = -EINVAL; in dai_ssp_set_config_tplg()
1523 /* set asserted frame length to half frame length */ in dai_ssp_set_config_tplg()
1528 * non-inverted(inverted_frame=0) -- active low(SFRMP=0), in dai_ssp_set_config_tplg()
1529 * inverted(inverted_frame=1) -- rising/active high(SFRMP=1), in dai_ssp_set_config_tplg()
1540 ret = -EINVAL; in dai_ssp_set_config_tplg()
1549 ret = -EINVAL; in dai_ssp_set_config_tplg()
1563 sscr0 |= SSCR0_FRDC(ssp_plat_data->params.tdm_slots); in dai_ssp_set_config_tplg()
1570 ret = -EINVAL; in dai_ssp_set_config_tplg()
1574 /* set asserted frame length to half frame length */ in dai_ssp_set_config_tplg()
1579 * non-inverted(inverted_frame=0) -- active high(SFRMP=1), in dai_ssp_set_config_tplg()
1580 * inverted(inverted_frame=1) -- falling/active low(SFRMP=0), in dai_ssp_set_config_tplg()
1591 ret = -EINVAL; in dai_ssp_set_config_tplg()
1600 ret = -EINVAL; in dai_ssp_set_config_tplg()
1619 sscr0 |= SSCR0_MOD | SSCR0_FRDC(ssp_plat_data->params.tdm_slots); in dai_ssp_set_config_tplg()
1624 if (cfs && ssp_plat_data->params.frame_pulse_width > 0 && in dai_ssp_set_config_tplg()
1625 ssp_plat_data->params.frame_pulse_width <= in dai_ssp_set_config_tplg()
1627 frame_len = ssp_plat_data->params.frame_pulse_width; in dai_ssp_set_config_tplg()
1631 if (ssp_plat_data->params.frame_pulse_width > in dai_ssp_set_config_tplg()
1634 ret = -EINVAL; in dai_ssp_set_config_tplg()
1639 * non-inverted(inverted_frame=0) -- active high(SFRMP=1), in dai_ssp_set_config_tplg()
1640 * inverted(inverted_frame=1) -- falling/active low(SFRMP=0), in dai_ssp_set_config_tplg()
1645 active_tx_slots = POPCOUNT(ssp_plat_data->params.tx_slots); in dai_ssp_set_config_tplg()
1646 active_rx_slots = POPCOUNT(ssp_plat_data->params.rx_slots); in dai_ssp_set_config_tplg()
1651 * subtracting slot width and valid bits per slot. in dai_ssp_set_config_tplg()
1653 if (ssp_plat_data->params.tdm_per_slot_padding_flag) { in dai_ssp_set_config_tplg()
1654 frame_end_padding = bdiv - ssp_plat_data->params.tdm_slots * in dai_ssp_set_config_tplg()
1655 ssp_plat_data->params.tdm_slot_width; in dai_ssp_set_config_tplg()
1657 slot_end_padding = ssp_plat_data->params.tdm_slot_width - in dai_ssp_set_config_tplg()
1658 ssp_plat_data->params.sample_valid_bits; in dai_ssp_set_config_tplg()
1664 ret = -EINVAL; in dai_ssp_set_config_tplg()
1677 LOG_ERR("invalid format 0x%04x", config->format); in dai_ssp_set_config_tplg()
1678 ret = -EINVAL; in dai_ssp_set_config_tplg()
1688 data_size = ssp_plat_data->params.sample_valid_bits; in dai_ssp_set_config_tplg()
1691 sscr0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16)); in dai_ssp_set_config_tplg()
1696 /* setting TFT and RFT */ in dai_ssp_set_config_tplg()
1697 switch (ssp_plat_data->params.sample_valid_bits) { in dai_ssp_set_config_tplg()
1708 LOG_ERR("sample_valid_bits %d", ssp_plat_data->params.sample_valid_bits); in dai_ssp_set_config_tplg()
1709 ret = -EINVAL; in dai_ssp_set_config_tplg()
1713 tft = MIN(DAI_INTEL_SSP_FIFO_DEPTH - DAI_INTEL_SSP_FIFO_WATERMARK, in dai_ssp_set_config_tplg()
1715 rft = MIN(DAI_INTEL_SSP_FIFO_DEPTH - DAI_INTEL_SSP_FIFO_WATERMARK, in dai_ssp_set_config_tplg()
1749 dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; in dai_ssp_set_config_tplg()
1750 dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; in dai_ssp_set_config_tplg()
1753 switch (config->options & DAI_INTEL_IPC3_SSP_CONFIG_FLAGS_CMD_MASK) { in dai_ssp_set_config_tplg()
1755 if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_MCLK_ES) { in dai_ssp_set_config_tplg()
1761 ssp_plat_data->clk_active |= SSP_CLK_MCLK_ES_REQ; in dai_ssp_set_config_tplg()
1764 dp->dai_index); in dai_ssp_set_config_tplg()
1767 if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_ES) { in dai_ssp_set_config_tplg()
1770 if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE)) { in dai_ssp_set_config_tplg()
1779 ssp_plat_data->clk_active |= SSP_CLK_BCLK_ES_REQ; in dai_ssp_set_config_tplg()
1784 dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), in dai_ssp_set_config_tplg()
1786 dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), in dai_ssp_set_config_tplg()
1792 LOG_INF("SSE set for SSP%d", ssp_plat_data->ssp_index); in dai_ssp_set_config_tplg()
1796 ssp_plat_data->ssp_index); in dai_ssp_set_config_tplg()
1801 if (dp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING || in dai_ssp_set_config_tplg()
1802 dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { in dai_ssp_set_config_tplg()
1804 dp->dai_index); in dai_ssp_set_config_tplg()
1808 if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_ES) { in dai_ssp_set_config_tplg()
1810 dp->dai_index); in dai_ssp_set_config_tplg()
1811 if (ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE) { in dai_ssp_set_config_tplg()
1823 LOG_INF("SSE clear for SSP%d", dp->dai_index); in dai_ssp_set_config_tplg()
1826 ssp_plat_data->clk_active &= ~SSP_CLK_BCLK_ES_REQ; in dai_ssp_set_config_tplg()
1828 if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_MCLK_ES) { in dai_ssp_set_config_tplg()
1830 dp->dai_index); in dai_ssp_set_config_tplg()
1832 ssp_plat_data->clk_active &= ~SSP_CLK_MCLK_ES_REQ; in dai_ssp_set_config_tplg()
1840 k_spin_unlock(&dp->lock, key); in dai_ssp_set_config_tplg()
1850 switch (aux_tlv->type) { in dai_ssp_check_aux_data()
1865 sync = (struct ssp_intel_sync_ctl *)&aux_tlv->val; in dai_ssp_check_aux_data()
1866 size += sync->count * sizeof(struct ssp_intel_node_ctl); in dai_ssp_check_aux_data()
1879 LOG_ERR("undefined aux data type %u", aux_tlv->type); in dai_ssp_check_aux_data()
1880 return -EINVAL; in dai_ssp_check_aux_data()
1884 size_left = aux_len - parsed_len - sizeof(struct ssp_intel_aux_tlv); in dai_ssp_check_aux_data()
1885 if (size > size_left || size != aux_tlv->size) { in dai_ssp_check_aux_data()
1887 size_left, aux_tlv->size); in dai_ssp_check_aux_data()
1888 return -EINVAL; in dai_ssp_check_aux_data()
1896 * TLV (Type-Length-Value) entries. It ensures that only specific types
1906 switch (aux_tlv->type) { in dai_ssp_check_dma_control()
1916 LOG_ERR("incorect config type %u", aux_tlv->type); in dai_ssp_check_dma_control()
1917 return -EINVAL; in dai_ssp_check_dma_control()
1920 hop = aux_tlv->size + sizeof(struct ssp_intel_aux_tlv); in dai_ssp_check_dma_control()
1948 return -EINVAL; in dai_ssp_parse_tlv()
1950 switch (aux_tlv->type) { in dai_ssp_parse_tlv()
1952 mn = (struct ssp_intel_mn_ctl *)&aux_tlv->val; in dai_ssp_parse_tlv()
1953 LOG_INF("mn div_m %u, div_n %u", mn->div_m, mn->div_n); in dai_ssp_parse_tlv()
1956 clk = (struct ssp_intel_clk_ctl *)&aux_tlv->val; in dai_ssp_parse_tlv()
1957 LOG_INF("clk start %u, stop %u", clk->start, clk->stop); in dai_ssp_parse_tlv()
1961 tr = (struct ssp_intel_tr_ctl *)&aux_tlv->val; in dai_ssp_parse_tlv()
1963 tr->sampling_frequency, tr->bit_depth, tr->channel_map); in dai_ssp_parse_tlv()
1965 tr->channel_config, tr->interleaving_style, tr->format); in dai_ssp_parse_tlv()
1968 run = (struct ssp_intel_run_ctl *)&aux_tlv->val; in dai_ssp_parse_tlv()
1969 LOG_INF("run enabled %u", run->enabled); in dai_ssp_parse_tlv()
1972 sync = (struct ssp_intel_sync_ctl *)&aux_tlv->val; in dai_ssp_parse_tlv()
1974 sync->sync_denominator, sync->count); in dai_ssp_parse_tlv()
1977 for (j = 0; j < sync->count; j++) { in dai_ssp_parse_tlv()
1979 node->node_id, node->sampling_rate); in dai_ssp_parse_tlv()
1984 ext = (struct ssp_intel_ext_ctl *)&aux_tlv->val; in dai_ssp_parse_tlv()
1985 LOG_INF("ext ext_data %u", ext->ext_data); in dai_ssp_parse_tlv()
1989 link = (struct ssp_intel_link_ctl *)&aux_tlv->val; in dai_ssp_parse_tlv()
1993 I2CLCTL_MLCS(link->clock_source), dai_ip_base(dp) + in dai_ssp_parse_tlv()
1996 ssp->link_clock = link->clock_source; in dai_ssp_parse_tlv()
1999 I2CLCTL_MLCS(link->clock_source), in dai_ssp_parse_tlv()
2002 LOG_INF("link clock_source %u", link->clock_source); in dai_ssp_parse_tlv()
2006 LOG_ERR("undefined aux data type %u", aux_tlv->type); in dai_ssp_parse_tlv()
2007 return -EINVAL; in dai_ssp_parse_tlv()
2010 hop = aux_tlv->size + sizeof(struct ssp_intel_aux_tlv); in dai_ssp_parse_tlv()
2024 if (blob15->version == SSP_BLOB_VER_1_5) { in dai_ssp_parse_aux_data()
2025 cfg_len = blob15->size; in dai_ssp_parse_aux_data()
2027 blob15->i2s_mclk_control.mdivrcnt * sizeof(uint32_t); in dai_ssp_parse_aux_data()
2028 aux_len = cfg_len - pre_aux_len; in dai_ssp_parse_aux_data()
2030 } else if (blob30->version == SSP_BLOB_VER_3_0) { in dai_ssp_parse_aux_data()
2031 cfg_len = blob30->size; in dai_ssp_parse_aux_data()
2033 blob30->i2s_mclk_control.mdivrcnt * sizeof(uint32_t); in dai_ssp_parse_aux_data()
2034 aux_len = cfg_len - pre_aux_len; in dai_ssp_parse_aux_data()
2038 return -EINVAL; in dai_ssp_parse_aux_data()
2052 if (cc->mdivrcnt != 1) { in dai_ssp_set_clock_control_ver_1_5()
2053 LOG_ERR("bad clock divider count %u", cc->mdivrcnt); in dai_ssp_set_clock_control_ver_1_5()
2054 return -EINVAL; in dai_ssp_set_clock_control_ver_1_5()
2058 * mclk and bclk at this time. in dai_ssp_set_clock_control_ver_1_5()
2060 dai_ssp_mn_set_mclk_blob(dp, cc->mdivctlr, cc->mdivr[0]); in dai_ssp_set_clock_control_ver_1_5()
2069 * mclk and bclk at this time. in dai_ssp_set_clock_control_ver_1()
2071 dai_ssp_mn_set_mclk_blob(dp, cc->mdivc, cc->mdivr); in dai_ssp_set_clock_control_ver_1()
2083 uint32_t ssc0 = regs->ssc0; in dai_ssp_set_reg_config()
2084 sscr1 = regs->ssc1 & ~(SSCR1_RSVD21); in dai_ssp_set_reg_config()
2086 LOG_INF("SSP%d configuration:", dp->dai_index); in dai_ssp_set_reg_config()
2089 sys_write32(regs->ssc2 & ~SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ in dai_ssp_set_reg_config()
2091 sys_write32(regs->ssc2 | SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ in dai_ssp_set_reg_config()
2092 sys_write32(regs->ssc2, dai_base(dp) + SSCR2); in dai_ssp_set_reg_config()
2093 sys_write32(regs->sspsp, dai_base(dp) + SSPSP); in dai_ssp_set_reg_config()
2094 sys_write32(regs->sspsp2, dai_base(dp) + SSPSP2); in dai_ssp_set_reg_config()
2095 sys_write32(regs->ssioc, dai_base(dp) + SSIOC); in dai_ssp_set_reg_config()
2096 sys_write32(regs->sscto, dai_base(dp) + SSTO); in dai_ssp_set_reg_config()
2099 sys_write64(regs->ssmidytsa[idx], dai_base(dp) + SSMIDyTSA(idx)); in dai_ssp_set_reg_config()
2103 sys_write64(regs->ssmodytsa[idx], dai_base(dp) + SSMODyTSA(idx)); in dai_ssp_set_reg_config()
2107 ssc0, sscr1, regs->sscto, regs->sspsp); in dai_ssp_set_reg_config()
2109 regs->ssc2, regs->sspsp2, regs->ssc3); in dai_ssp_set_reg_config()
2110 LOG_INF(" ssioc = 0x%08x", regs->ssioc); in dai_ssp_set_reg_config()
2112 ssp_plat_data->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); in dai_ssp_set_reg_config()
2114 ssp_plat_data->params.sample_valid_bits += 16; in dai_ssp_set_reg_config()
2117 ssp_plat_data->params.tx_slots = regs->ssmodytsa[dp->tdm_slot_group]; in dai_ssp_set_reg_config()
2118 ssp_plat_data->params.rx_slots = regs->ssmidytsa[dp->tdm_slot_group]; in dai_ssp_set_reg_config()
2120 ssp_plat_data->params.fsync_rate = cfg->rate; in dai_ssp_set_reg_config()
2121 dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; in dai_ssp_set_reg_config()
2122 dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; in dai_ssp_set_reg_config()
2133 uint32_t ssc0 = regs->ssc0; in dai_ssp_set_reg_config()
2135 sscr1 = regs->ssc1 & ~(SSCR1_RSRE | SSCR1_TSRE); in dai_ssp_set_reg_config()
2136 sstsa = SSTSA_GET(regs->sstsa); in dai_ssp_set_reg_config()
2137 ssrsa = SSRSA_GET(regs->ssrsa); in dai_ssp_set_reg_config()
2139 LOG_INF("SSP%d configuration:", dp->dai_index); in dai_ssp_set_reg_config()
2141 if (regs->sstsa & SSTSA_TXEN || regs->ssrsa & SSRSA_RXEN || in dai_ssp_set_reg_config()
2142 regs->ssc1 & (SSCR1_RSRE | SSCR1_TSRE)) { in dai_ssp_set_reg_config()
2144 regs->sstsa & SSTSA_TXEN ? "SSTSA:TXEN " : "", in dai_ssp_set_reg_config()
2145 regs->ssrsa & SSRSA_RXEN ? "SSRSA:RXEN " : "", in dai_ssp_set_reg_config()
2146 regs->ssc1 & SSCR1_TSRE ? "SSCR1:TSRE " : "", in dai_ssp_set_reg_config()
2147 regs->ssc1 & SSCR1_RSRE ? "SSCR1:RSRE " : ""); in dai_ssp_set_reg_config()
2151 sys_write32(regs->ssc2 & ~SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ in dai_ssp_set_reg_config()
2153 sys_write32(regs->ssc2 | SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ in dai_ssp_set_reg_config()
2154 sys_write32(regs->ssc2, dai_base(dp) + SSCR2); in dai_ssp_set_reg_config()
2155 sys_write32(regs->ssc3, dai_base(dp) + SSCR3); in dai_ssp_set_reg_config()
2156 sys_write32(regs->sspsp, dai_base(dp) + SSPSP); in dai_ssp_set_reg_config()
2157 sys_write32(regs->sspsp2, dai_base(dp) + SSPSP2); in dai_ssp_set_reg_config()
2158 sys_write32(regs->ssioc, dai_base(dp) + SSIOC); in dai_ssp_set_reg_config()
2159 sys_write32(regs->sscto, dai_base(dp) + SSTO); in dai_ssp_set_reg_config()
2164 ssc0, sscr1, regs->sscto, regs->sspsp); in dai_ssp_set_reg_config()
2166 regs->ssc2, regs->sspsp2, regs->ssc3); in dai_ssp_set_reg_config()
2168 regs->ssioc, ssrsa, sstsa); in dai_ssp_set_reg_config()
2170 ssp_plat_data->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); in dai_ssp_set_reg_config()
2172 ssp_plat_data->params.sample_valid_bits += 16; in dai_ssp_set_reg_config()
2175 ssp_plat_data->params.tdm_slots = SSCR0_FRDC_GET(ssc0); in dai_ssp_set_reg_config()
2176 ssp_plat_data->params.tx_slots = SSTSA_GET(sstsa); in dai_ssp_set_reg_config()
2177 ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); in dai_ssp_set_reg_config()
2178 ssp_plat_data->params.fsync_rate = cfg->rate; in dai_ssp_set_reg_config()
2179 dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; in dai_ssp_set_reg_config()
2180 dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; in dai_ssp_set_reg_config()
2194 dp->tdm_slot_group = cfg->tdm_slot_group; in dai_ssp_set_config_blob()
2198 if (ssp_plat_data->is_initialized) { in dai_ssp_set_config_blob()
2199 dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; in dai_ssp_set_config_blob()
2200 dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; in dai_ssp_set_config_blob()
2204 if (blob15->version == SSP_BLOB_VER_1_5) { in dai_ssp_set_config_blob()
2209 dai_ssp_set_reg_config(dp, cfg, (void *)&blob15->i2s_ssp_config); in dai_ssp_set_config_blob()
2210 err = dai_ssp_set_clock_control_ver_1_5(dp, &blob15->i2s_mclk_control); in dai_ssp_set_config_blob()
2214 } else if (blob30->version == SSP_BLOB_VER_3_0) { in dai_ssp_set_config_blob()
2219 dai_ssp_set_reg_config(dp, cfg, (void *)&blob30->i2s_ssp_config); in dai_ssp_set_config_blob()
2220 err = dai_ssp_set_clock_control_ver_1_5(dp, &blob30->i2s_mclk_control); in dai_ssp_set_config_blob()
2225 dai_ssp_set_reg_config(dp, cfg, (void *)&blob->i2s_driver_config.i2s_config); in dai_ssp_set_config_blob()
2226 err = dai_ssp_set_clock_control_ver_1(dp, &blob->i2s_driver_config.mclk_config); in dai_ssp_set_config_blob()
2232 ssp_plat_data->clk_active |= SSP_CLK_MCLK_ES_REQ; in dai_ssp_set_config_blob()
2236 ssp_plat_data->clk_active |= SSP_CLK_BCLK_ES_REQ; in dai_ssp_set_config_blob()
2237 ssp_plat_data->is_initialized = true; in dai_ssp_set_config_blob()
2256 if (!(ssp_plat_data->clk_active & SSP_CLK_MCLK_ES_REQ)) { in dai_ssp_pre_start()
2264 if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)) { in dai_ssp_pre_start()
2281 if (dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_RUNNING && in dai_ssp_post_stop()
2282 dp->state[DAI_DIR_CAPTURE] != DAI_STATE_RUNNING) { in dai_ssp_post_stop()
2283 if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)) { in dai_ssp_post_stop()
2284 LOG_INF("releasing BCLK clocks for SSP%d...", dp->dai_index); in dai_ssp_post_stop()
2287 if (!(ssp_plat_data->clk_active & SSP_CLK_MCLK_ES_REQ)) { in dai_ssp_post_stop()
2288 LOG_INF("releasing MCLK clocks for SSP%d...", dp->dai_index); in dai_ssp_post_stop()
2299 key = k_spin_lock(&dp->lock); in dai_ssp_early_start()
2303 LOG_INF("SSP%d RX", dp->dai_index); in dai_ssp_early_start()
2306 LOG_INF("SSP%d TX", dp->dai_index); in dai_ssp_early_start()
2312 if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)) { in dai_ssp_early_start()
2314 LOG_INF("SSP%d: set SSE", dp->dai_index); in dai_ssp_early_start()
2318 k_spin_unlock(&dp->lock, key); in dai_ssp_early_start()
2327 key = k_spin_lock(&dp->lock); in dai_ssp_start()
2332 LOG_INF("SSP%d TX", dp->dai_index); in dai_ssp_start()
2334 dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), in dai_ssp_start()
2336 dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), in dai_ssp_start()
2343 LOG_INF("SSP%d RX", dp->dai_index); in dai_ssp_start()
2345 dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), in dai_ssp_start()
2347 dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), in dai_ssp_start()
2355 dp->state[direction] = DAI_STATE_RUNNING; in dai_ssp_start()
2362 switch (ssp->config.format & DAI_INTEL_IPC3_SSP_FMT_CLOCK_PROVIDER_MASK) { in dai_ssp_start()
2366 /* delay for all SSP consumed clocks atm - see above */ in dai_ssp_start()
2372 k_spin_unlock(&dp->lock, key); in dai_ssp_start()
2381 key = k_spin_lock(&dp->lock); in dai_ssp_stop()
2388 switch (ssp->config.format & DAI_INTEL_IPC3_SSP_FMT_CLOCK_PROVIDER_MASK) { in dai_ssp_stop()
2392 /* delay for all SSP consumed clocks atm - see above */ in dai_ssp_stop()
2399 dp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING) { in dai_ssp_stop()
2400 LOG_INF("SSP%d RX", dp->dai_index); in dai_ssp_stop()
2403 dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), SSMIDyCS_RXEN, 0); in dai_ssp_stop()
2404 dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), SSMIDyCS_RSRE, 0); in dai_ssp_stop()
2410 dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; in dai_ssp_stop()
2415 dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { in dai_ssp_stop()
2416 LOG_INF("SSP%d TX", dp->dai_index); in dai_ssp_stop()
2419 dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), SSMODyCS_TSRE, 0); in dai_ssp_stop()
2421 dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), SSMODyCS_TXEN, 0); in dai_ssp_stop()
2427 dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; in dai_ssp_stop()
2430 k_spin_unlock(&dp->lock, key); in dai_ssp_stop()
2436 LOG_INF("SSP%d RX", dp->dai_index); in dai_ssp_pause()
2438 LOG_INF("SSP%d TX", dp->dai_index); in dai_ssp_pause()
2441 dp->state[direction] = DAI_STATE_PAUSED; in dai_ssp_pause()
2447 struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; in dai_ssp_trigger()
2450 LOG_DBG("SSP%d: cmd %d", dp->dai_index, cmd); in dai_ssp_trigger()
2454 if (dp->state[array_index] == DAI_STATE_PAUSED || in dai_ssp_trigger()
2455 dp->state[array_index] == DAI_STATE_PRE_RUNNING) { in dai_ssp_trigger()
2477 struct dai_config *params = (struct dai_config *)dev->config; in dai_ssp_config_get()
2478 struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; in dai_ssp_config_get()
2483 return -EINVAL; in dai_ssp_config_get()
2491 params->rate = ssp_plat_data->params.fsync_rate; in dai_ssp_config_get()
2494 params->channels = POPCOUNT(ssp_plat_data->params.tx_slots); in dai_ssp_config_get()
2496 params->channels = POPCOUNT(ssp_plat_data->params.rx_slots); in dai_ssp_config_get()
2499 params->word_size = ssp_plat_data->params.sample_valid_bits; in dai_ssp_config_get()
2509 struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; in dai_ssp_config_set()
2513 if (cfg->type == DAI_INTEL_SSP) { in dai_ssp_config_set()
2518 dai_ssp_program_channel_map(dp, cfg, ssp_plat_data->ssp_index, bespoke_cfg); in dai_ssp_config_set()
2526 struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; in dai_ssp_get_properties()
2529 struct dai_properties *prop = &ssp->props; in dai_ssp_get_properties()
2532 prop->fifo_address = ssp_plat_data->fifo[array_index].offset; in dai_ssp_get_properties()
2533 prop->dma_hs_id = ssp_plat_data->fifo[array_index].handshake; in dai_ssp_get_properties()
2535 if (ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE) { in dai_ssp_get_properties()
2536 prop->reg_init_delay = 0; in dai_ssp_get_properties()
2538 prop->reg_init_delay = ssp_plat_data->params.bclk_delay; in dai_ssp_get_properties()
2541 LOG_INF("SSP%u: fifo %u, handshake %u, init delay %u", dp->dai_index, prop->fifo_address, in dai_ssp_get_properties()
2542 prop->dma_hs_id, prop->reg_init_delay); in dai_ssp_get_properties()
2551 ssp->acquire_count++; in ssp_acquire_ip()
2553 if (ssp->acquire_count == 1) { in ssp_acquire_ip()
2555 dai_ssp_pm_runtime_en_ssp_power(dp, ssp->ssp_index); in ssp_acquire_ip()
2558 dai_ssp_pm_runtime_dis_ssp_clk_gating(dp, ssp->ssp_index); in ssp_acquire_ip()
2564 I2CLCTL_MLCS(ssp->link_clock), in ssp_acquire_ip()
2574 if (ssp->acquire_count == 0) { in ssp_release_ip()
2578 --ssp->acquire_count; in ssp_release_ip()
2580 if (ssp->acquire_count == 0) { in ssp_release_ip()
2582 if (dp->state[DAI_DIR_CAPTURE] == DAI_STATE_PRE_RUNNING && in ssp_release_ip()
2583 dp->state[DAI_DIR_PLAYBACK] == DAI_STATE_PRE_RUNNING && in ssp_release_ip()
2585 (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ)), (true))) { in ssp_release_ip()
2587 LOG_INF("%s SSE clear SSP%d", __func__, ssp->ssp_index); in ssp_release_ip()
2600 dai_ssp_pm_runtime_en_ssp_clk_gating(dp, ssp->ssp_index); in ssp_release_ip()
2606 dai_ssp_pm_runtime_dis_ssp_power(dp, ssp->ssp_index); in ssp_release_ip()
2607 ssp->is_initialized = false; in ssp_release_ip()
2617 return -EEXIST; /* already created */ in dai_ssp_probe()
2623 LOG_ERR("SSP%d: alloc failed", ssp_plat_data->ssp_index); in dai_ssp_probe()
2624 return -ENOMEM; in dai_ssp_probe()
2628 dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_READY; in dai_ssp_probe()
2629 dp->state[DAI_DIR_CAPTURE] = DAI_STATE_READY; in dai_ssp_probe()
2632 /* Reset M/N, power-gating functions need it */ in dai_ssp_probe()
2633 dai_ssp_mn_reset_bclk_divider(dp, ssp_plat_data->ssp_index); in dai_ssp_probe()
2653 struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; in ssp_pm_action()
2664 /* All device pm is handled during resume and suspend */ in ssp_pm_action()
2667 return -ENOTSUP; in ssp_pm_action()
2675 struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; in dai_intel_ssp_init_device()
2677 dp->ssp_plat_data = ssp_get_device_instance(dp->ssp_index); in dai_intel_ssp_init_device()
2692 struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; in dai_ssp_dma_control_set()
2695 dp->dai_index, (uint32_t)bespoke_cfg, size); in dai_ssp_dma_control_set()
2697 return -EINVAL; in dai_ssp_dma_control_set()
2700 if (dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_READY || in dai_ssp_dma_control_set()
2701 dp->state[DAI_DIR_CAPTURE] != DAI_STATE_READY) { in dai_ssp_dma_control_set()
2702 return -EIO; in dai_ssp_dma_control_set()
2706 return -EINVAL; in dai_ssp_dma_control_set()