diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index f630a656967a33..5e53bdc41ebf42 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -18,24 +18,119 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include "ssp.h" -#define DT_DRV_COMPAT intel_ssp_dai #define dai_set_drvdata(dai, data) (dai->priv_data = data) #define dai_get_drvdata(dai) dai->priv_data -#define dai_get_mn(dai) dai->plat_data.mn_inst -#define dai_get_ftable(dai) dai->plat_data.ftable -#define dai_get_fsources(dai) dai->plat_data.fsources -#define dai_mn_base(dai) dai->plat_data.mn_inst->base -#define dai_base(dai) dai->plat_data.base -#define dai_ip_base(dai) dai->plat_data.ip_base -#define dai_shim_base(dai) dai->plat_data.shim_base -#define dai_hdamlssp_base(dai) dai->plat_data.hdamlssp_base -#define dai_i2svss_base(dai) dai->plat_data.i2svss_base +#define dai_get_plat_data(dai) dai->ssp_plat_data +#define dai_get_mn(dai) dai->ssp_plat_data->mn_inst +#define dai_get_ftable(dai) dai->ssp_plat_data->ftable +#define dai_get_fsources(dai) dai->ssp_plat_data->fsources +#define dai_mn_base(dai) dai->ssp_plat_data->mn_inst->base +#define dai_base(dai) dai->ssp_plat_data->base +#define dai_ip_base(dai) dai->ssp_plat_data->ip_base +#define dai_shim_base(dai) dai->ssp_plat_data->shim_base +#define dai_hdamlssp_base(dai) dai->ssp_plat_data->hdamlssp_base +#define dai_i2svss_base(dai) dai->ssp_plat_data->i2svss_base #define DAI_DIR_PLAYBACK 0 #define DAI_DIR_CAPTURE 1 #define SSP_ARRAY_INDEX(dir) dir == DAI_DIR_RX ? DAI_DIR_CAPTURE : DAI_DIR_PLAYBACK +static const char irq_name_level5_z[] = "level5"; + +static struct dai_intel_ssp_freq_table ssp_freq_table[] = { + { DT_PROP(DT_NODELABEL(audioclk), clock_frequency), + DT_PROP(DT_NODELABEL(audioclk), clock_frequency) / 1000}, + { DT_PROP(DT_NODELABEL(sysclk), clock_frequency), + DT_PROP(DT_NODELABEL(sysclk), clock_frequency) / 1000}, + { DT_PROP(DT_NODELABEL(pllclk), clock_frequency), + DT_PROP(DT_NODELABEL(pllclk), clock_frequency) / 1000}, +}; + +static uint32_t ssp_freq_sources[] = { + DAI_INTEL_SSP_CLOCK_AUDIO_CARDINAL, + DAI_INTEL_SSP_CLOCK_XTAL_OSCILLATOR, + DAI_INTEL_SSP_CLOCK_PLL_FIXED, +}; + +static struct dai_intel_ssp_mn ssp_mn_divider = { + .base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(ssp0), 1), +}; + + +#define INTEL_SSP_INST_DEFINE(node_id) { \ + .is_initialized = false, \ + .is_power_en = false, \ + .acquire_count = 0, \ + .ssp_index = DT_PROP(node_id, ssp_index), \ + .base = DT_REG_ADDR_BY_IDX(node_id, 0), \ + IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(sspbase)), \ + (.ip_base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(sspbase), 0),)) \ + .shim_base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(shim), 0), \ + IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(hdamlssp)), \ + (.hdamlssp_base = DT_REG_ADDR(DT_NODELABEL(hdamlssp)),))\ + IF_ENABLED(DT_PROP_HAS_IDX(node_id, i2svss, 0), \ + (.i2svss_base = DT_PROP_BY_IDX(node_id, i2svss, 0),)) \ + .irq = DT_NUM_IRQS(node_id), \ + .irq_name = irq_name_level5_z, \ + .fifo[DAI_DIR_PLAYBACK].offset = \ + DT_REG_ADDR_BY_IDX(node_id, 0) + SSDR, \ + .fifo[DAI_DIR_PLAYBACK].handshake = \ + DT_DMAS_CELL_BY_NAME(node_id, tx, channel), \ + .fifo[DAI_DIR_CAPTURE].offset = \ + DT_REG_ADDR_BY_IDX(node_id, 0) + SSDR, \ + .fifo[DAI_DIR_CAPTURE].handshake = \ + DT_DMAS_CELL_BY_NAME(node_id, rx, channel), \ + .mn_inst = &ssp_mn_divider, \ + .ftable = ssp_freq_table, \ + .fsources = ssp_freq_sources, \ + .clk_active = 0, \ +}, + +static struct dai_intel_ssp_plat_data ssp_plat_data_table[] = { + DT_FOREACH_STATUS_OKAY(intel_ssp, INTEL_SSP_INST_DEFINE) +}; + + +static uint32_t ssp_get_instance_count(void) +{ + return ARRAY_SIZE(ssp_plat_data_table); +} + + +static struct dai_intel_ssp_plat_data *ssp_get_device_instance(uint32_t ssp_index) +{ + uint32_t ssp_instance = ssp_get_instance_count(); + uint32_t i; + + for (i = 0; i < ssp_instance; i++) { + if (ssp_plat_data_table[i].ssp_index == ssp_index) { + return &ssp_plat_data_table[i]; + } + } + + return NULL; +} + +static void ssp_acquire_port(struct dai_intel_ssp_plat_data *ssp) +{ + ssp->acquire_count++; +} + +static void ssp_release_port(struct dai_intel_ssp_plat_data *ssp) +{ + if (ssp->acquire_count == 0) { + return; + } + + --ssp->acquire_count; +} + +static bool ssp_is_acquired(struct dai_intel_ssp_plat_data *ssp) +{ + return (ssp->acquire_count != 0); +} + static void dai_ssp_update_bits(struct dai_intel_ssp *dp, uint32_t reg, uint32_t mask, uint32_t val) { uint32_t dest = dai_base(dp) + reg; @@ -629,14 +724,14 @@ static int dai_ssp_mn_set_bclk(struct dai_intel_ssp *dp, uint32_t dai_index, uin return ret; } -static void dai_ssp_mn_release_bclk(struct dai_intel_ssp *dp, uint32_t dai_index) +static void dai_ssp_mn_release_bclk(struct dai_intel_ssp *dp, uint32_t ssp_index) { struct dai_intel_ssp_mn *mp = dai_get_mn(dp); k_spinlock_key_t key; bool mn_in_use; key = k_spin_lock(&mp->lock); - mp->bclk_sources[dai_index] = MN_BCLK_SOURCE_NONE; + mp->bclk_sources[ssp_index] = MN_BCLK_SOURCE_NONE; mn_in_use = dai_ssp_is_bclk_source_in_use(dp, MN_BCLK_SOURCE_MN); /* release the M/N clock source if not used */ @@ -647,15 +742,15 @@ static void dai_ssp_mn_release_bclk(struct dai_intel_ssp *dp, uint32_t dai_index k_spin_unlock(&mp->lock, key); } -static void dai_ssp_mn_reset_bclk_divider(struct dai_intel_ssp *dp, uint32_t dai_index) +static void dai_ssp_mn_reset_bclk_divider(struct dai_intel_ssp *dp, uint32_t ssp_index) { struct dai_intel_ssp_mn *mp = dai_get_mn(dp); k_spinlock_key_t key; key = k_spin_lock(&mp->lock); - sys_write32(1, dai_mn_base(dp) + MN_MDIV_M_VAL(dai_index)); - sys_write32(1, dai_mn_base(dp) + MN_MDIV_N_VAL(dai_index)); + sys_write32(1, dai_mn_base(dp) + MN_MDIV_M_VAL(ssp_index)); + sys_write32(1, dai_mn_base(dp) + MN_MDIV_N_VAL(ssp_index)); k_spin_unlock(&mp->lock, key); } @@ -672,131 +767,131 @@ static int dai_ssp_poll_for_register_delay(uint32_t reg, uint32_t mask, return 0; } -static inline void dai_ssp_pm_runtime_dis_ssp_clk_gating(struct dai_intel_ssp *dp, uint32_t index) +static inline void dai_ssp_pm_runtime_dis_ssp_clk_gating(struct dai_intel_ssp *dp, + uint32_t ssp_index) { #if CONFIG_DAI_SSP_CLK_FORCE_DYNAMIC_CLOCK_GATING uint32_t shim_reg; shim_reg = sys_read32(dai_shim_base(dp) + SHIM_CLKCTL) | - (index < CONFIG_DAI_INTEL_SSP_NUM_BASE ? - SHIM_CLKCTL_I2SFDCGB(index) : - SHIM_CLKCTL_I2SEFDCGB(index - + (ssp_index < CONFIG_DAI_INTEL_SSP_NUM_BASE ? + SHIM_CLKCTL_I2SFDCGB(ssp_index) : + SHIM_CLKCTL_I2SEFDCGB(ssp_index - CONFIG_DAI_INTEL_SSP_NUM_BASE)); sys_write32(shim_reg, dai_shim_base(dp) + SHIM_CLKCTL); - LOG_INF("index %d CLKCTL %08x", index, shim_reg); + LOG_INF("ssp_index %d CLKCTL %08x", ssp_index, shim_reg); #endif } -static inline void dai_ssp_pm_runtime_en_ssp_clk_gating(struct dai_intel_ssp *dp, uint32_t index) +static inline void dai_ssp_pm_runtime_en_ssp_clk_gating(struct dai_intel_ssp *dp, + uint32_t ssp_index) { #if CONFIG_DAI_SSP_CLK_FORCE_DYNAMIC_CLOCK_GATING uint32_t shim_reg; shim_reg = sys_read32(dai_shim_base(dp) + SHIM_CLKCTL) & - ~(index < CONFIG_DAI_INTEL_SSP_NUM_BASE ? - SHIM_CLKCTL_I2SFDCGB(index) : - SHIM_CLKCTL_I2SEFDCGB(index - + ~(ssp_index < CONFIG_DAI_INTEL_SSP_NUM_BASE ? + SHIM_CLKCTL_I2SFDCGB(ssp_index) : + SHIM_CLKCTL_I2SEFDCGB(ssp_index - CONFIG_DAI_INTEL_SSP_NUM_BASE)); sys_write32(shim_reg, dai_shim_base(dp) + SHIM_CLKCTL); - LOG_INF("index %d CLKCTL %08x", index, shim_reg); + LOG_INF("ssp_index %d CLKCTL %08x", ssp_index, shim_reg); #endif } -static void dai_ssp_pm_runtime_en_ssp_power(struct dai_intel_ssp *dp, uint32_t index) +static void dai_ssp_pm_runtime_en_ssp_power(struct dai_intel_ssp *dp, uint32_t ssp_index) { #if CONFIG_DAI_SSP_HAS_POWER_CONTROL int ret; - LOG_INF("SSP%d", dp->index); + LOG_INF("SSP%d", ssp_index); #if CONFIG_SOC_INTEL_ACE15_MTPM || CONFIG_SOC_SERIES_INTEL_ADSP_CAVS - sys_write32(sys_read32(dai_ip_base(dp) + I2SLCTL_OFFSET) | I2SLCTL_SPA(index), + sys_write32(sys_read32(dai_ip_base(dp) + I2SLCTL_OFFSET) | I2SLCTL_SPA(ssp_index), dai_ip_base(dp) + I2SLCTL_OFFSET); /* Check if powered on. */ ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET, - I2SLCTL_CPA(index), I2SLCTL_CPA(index), + I2SLCTL_CPA(ssp_index), I2SLCTL_CPA(ssp_index), DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); #elif CONFIG_SOC_INTEL_ACE20_LNL sys_write32(sys_read32(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET) | - I2SLCTL_SPA(index), + I2SLCTL_SPA(ssp_index), dai_hdamlssp_base(dp) + I2SLCTL_OFFSET); /* Check if powered on. */ ret = dai_ssp_poll_for_register_delay(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET, - I2SLCTL_CPA(index), I2SLCTL_CPA(index), + I2SLCTL_CPA(ssp_index), I2SLCTL_CPA(ssp_index), DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); #else #error need to define SOC #endif if (ret) { - LOG_WRN("SSP%d: timeout", dp->index); + LOG_WRN("SSP%d: timeout", ssp_index); } #else ARG_UNUSED(dp); - ARG_UNUSED(index); + ARG_UNUSED(ssp_index); #endif /* CONFIG_DAI_SSP_HAS_POWER_CONTROL */ } -static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t index) +static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t ssp_index) { #if CONFIG_DAI_SSP_HAS_POWER_CONTROL int ret; - LOG_INF("SSP%d", dp->index); + LOG_INF("SSP%d", ssp_index); #if CONFIG_SOC_INTEL_ACE15_MTPM || CONFIG_SOC_SERIES_INTEL_ADSP_CAVS - sys_write32(sys_read32(dai_ip_base(dp) + I2SLCTL_OFFSET) & (~I2SLCTL_SPA(index)), + sys_write32(sys_read32(dai_ip_base(dp) + I2SLCTL_OFFSET) & (~I2SLCTL_SPA(ssp_index)), dai_ip_base(dp) + I2SLCTL_OFFSET); /* Check if powered off. */ ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET, - I2SLCTL_CPA(index), 0, + I2SLCTL_CPA(ssp_index), 0, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); #elif CONFIG_SOC_INTEL_ACE20_LNL - sys_write32(sys_read32(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET) & (~I2SLCTL_SPA(index)), + sys_write32(sys_read32(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET) & (~I2SLCTL_SPA(ssp_index)), dai_hdamlssp_base(dp) + I2SLCTL_OFFSET); /* Check if powered off. */ ret = dai_ssp_poll_for_register_delay(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET, - I2SLCTL_CPA(index), 0, + I2SLCTL_CPA(ssp_index), 0, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); #else #error need to define SOC #endif if (ret) { - LOG_WRN("SSP%d: timeout", dp->index); + LOG_WRN("SSP%d: timeout", ssp_index); } #else ARG_UNUSED(dp); - ARG_UNUSED(index); + ARG_UNUSED(ssp_index); #endif /* CONFIG_DAI_SSP_HAS_POWER_CONTROL */ } static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp, - const struct dai_config *cfg, uint32_t index) + const struct dai_config *cfg, uint32_t ssp_index) { #ifdef CONFIG_SOC_INTEL_ACE20_LNL uint16_t pcmsycm = cfg->link_config; - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); - - /* Set upper slot number from configuration */ - pcmsycm = pcmsycm | (ssp->params.tdm_slots - 1) << 4; + /* Set upper slot number from configuration */ + pcmsycm = pcmsycm | (dp->ssp_plat_data->params.tdm_slots - 1) << 4; - if (DAI_INTEL_SSP_IS_BIT_SET(pcmsycm, 15)) { - uint32_t reg_add = dai_ip_base(dp) + 0x1000 * index + PCMS0CM_OFFSET; + if (DAI_INTEL_SSP_IS_BIT_SET(cfg->link_config, 15)) { + uint32_t reg_add = dai_ip_base(dp) + 0x1000 * ssp_index + PCMS0CM_OFFSET; /* Program HDA output stream parameters */ sys_write16((pcmsycm & 0xffff), reg_add); } else { - uint32_t reg_add = dai_ip_base(dp) + 0x1000 * index + PCMS1CM_OFFSET; + uint32_t reg_add = dai_ip_base(dp) + 0x1000 * ssp_index + PCMS1CM_OFFSET; /* Program HDA input stream parameters */ sys_write16((pcmsycm & 0xffff), reg_add); } #else ARG_UNUSED(dp); ARG_UNUSED(cfg); - ARG_UNUSED(index); + ARG_UNUSED(ssp_index); #endif /* CONFIG_SOC_INTEL_ACE20_LNL */ } @@ -859,8 +954,9 @@ static void ssp_empty_rx_fifo_on_start(struct dai_intel_ssp *dp) static void ssp_empty_rx_fifo_on_stop(struct dai_intel_ssp *dp) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); - uint64_t sample_ticks = ssp->params.fsync_rate ? 1000000 / ssp->params.fsync_rate : 0; + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + uint64_t sample_ticks = ssp_plat_data->params.fsync_rate ? + 1000000 / ssp_plat_data->params.fsync_rate : 0; uint32_t retry = DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX; uint32_t entries[2]; uint32_t i, sssr; @@ -900,20 +996,21 @@ static void ssp_empty_rx_fifo_on_stop(struct dai_intel_ssp *dp) static int dai_ssp_mclk_prepare_enable(struct dai_intel_ssp *dp) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); int ret; - if (ssp->clk_active & SSP_CLK_MCLK_ACTIVE) { + if (ssp_plat_data->clk_active & SSP_CLK_MCLK_ACTIVE) { return 0; } /* MCLK config */ - ret = dai_ssp_mn_set_mclk(dp, ssp->params.mclk_id, ssp->params.mclk_rate); + ret = dai_ssp_mn_set_mclk(dp, ssp_plat_data->params.mclk_id, + ssp_plat_data->params.mclk_rate); if (ret < 0) { - LOG_ERR("invalid mclk_rate = %d for mclk_id = %d", ssp->params.mclk_rate, - ssp->params.mclk_id); + LOG_ERR("invalid mclk_rate = %d for mclk_id = %d", ssp_plat_data->params.mclk_rate, + ssp_plat_data->params.mclk_id); } else { - ssp->clk_active |= SSP_CLK_MCLK_ACTIVE; + ssp_plat_data->clk_active |= SSP_CLK_MCLK_ACTIVE; } return ret; @@ -921,15 +1018,15 @@ static int dai_ssp_mclk_prepare_enable(struct dai_intel_ssp *dp) static void dai_ssp_mclk_disable_unprepare(struct dai_intel_ssp *dp) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); - if (!(ssp->clk_active & SSP_CLK_MCLK_ACTIVE)) { + if (!(ssp_plat_data->clk_active & SSP_CLK_MCLK_ACTIVE)) { return; } - dai_ssp_mn_release_mclk(dp, ssp->params.mclk_id); + dai_ssp_mn_release_mclk(dp, ssp_plat_data->params.mclk_id); - ssp->clk_active &= ~SSP_CLK_MCLK_ACTIVE; + ssp_plat_data->clk_active &= ~SSP_CLK_MCLK_ACTIVE; } static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) @@ -937,14 +1034,13 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) #if !(CONFIG_INTEL_MN) struct dai_intel_ssp_freq_table *ft = dai_get_ftable(dp); #endif - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); - struct dai_config *config = &ssp->config; + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); uint32_t sscr0; uint32_t mdiv; bool need_ecs = false; int ret = 0; - if (ssp->clk_active & SSP_CLK_BCLK_ACTIVE) { + if (ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE) { return 0; } @@ -952,22 +1048,22 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) #if CONFIG_INTEL_MN /* BCLK config */ - ret = dai_ssp_mn_set_bclk(dp, config->dai_index, ssp->params.bclk_rate, + ret = dai_ssp_mn_set_bclk(dp, dp->dai_index, ssp_plat_data->params.bclk_rate, &mdiv, &need_ecs); if (ret < 0) { - LOG_ERR("invalid bclk_rate = %d for dai_index = %d", - ssp->params.bclk_rate, config->dai_index); + LOG_ERR("invalid bclk_rate = %d for ssp_index = %d", + ssp_plat_data->params.bclk_rate, dp->dai_index); goto out; } #else - if (ft[DAI_INTEL_SSP_DEFAULT_IDX].freq % ssp->params.bclk_rate != 0) { - LOG_ERR("invalid bclk_rate = %d for dai_index = %d", - ssp->params.bclk_rate, config->dai_index); + if (ft[DAI_INTEL_SSP_DEFAULT_IDX].freq % ssp_plat_data->params.bclk_rate != 0) { + LOG_ERR("invalid bclk_rate = %d for ssp_index = %d", + ssp_plat_data->params.bclk_rate, dp->dai_index); ret = -EINVAL; goto out; } - mdiv = ft[DAI_INTEL_SSP_DEFAULT_IDX].freq / ssp->params.bclk_rate; + mdiv = ft[DAI_INTEL_SSP_DEFAULT_IDX].freq / ssp_plat_data->params.bclk_rate; #endif if (need_ecs) { @@ -993,7 +1089,7 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) LOG_INF("sscr0 = 0x%08x", sscr0); out: if (!ret) { - ssp->clk_active |= SSP_CLK_BCLK_ACTIVE; + ssp_plat_data->clk_active |= SSP_CLK_BCLK_ACTIVE; } return ret; @@ -1001,29 +1097,30 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) static void dai_ssp_bclk_disable_unprepare(struct dai_intel_ssp *dp) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); - if (!(ssp->clk_active & SSP_CLK_BCLK_ACTIVE)) { + if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE)) { return; } #if CONFIG_INTEL_MN - dai_ssp_mn_release_bclk(dp, dp->index); + dai_ssp_mn_release_bclk(dp, ssp_plat_data->ssp_index); #endif - ssp->clk_active &= ~SSP_CLK_BCLK_ACTIVE; + ssp_plat_data->clk_active &= ~SSP_CLK_BCLK_ACTIVE; } static void dai_ssp_log_ssp_data(struct dai_intel_ssp *dp) { - LOG_INF("dai index: %u", dp->index); - LOG_INF("plat_data base: %u", dp->plat_data.base); - LOG_INF("plat_data irq: %u", dp->plat_data.irq); - LOG_INF("plat_data fifo playback offset: %u", dp->plat_data.fifo[DAI_DIR_PLAYBACK].offset); + LOG_INF("dai index: %u", dp->dai_index); + LOG_INF("plat_data base: %u", dp->ssp_plat_data->base); + LOG_INF("plat_data irq: %u", dp->ssp_plat_data->irq); + LOG_INF("plat_data fifo playback offset: %u", + dp->ssp_plat_data->fifo[DAI_DIR_PLAYBACK].offset); LOG_INF("plat_data fifo playback handshake: %u", - dp->plat_data.fifo[DAI_DIR_PLAYBACK].handshake); + dp->ssp_plat_data->fifo[DAI_DIR_PLAYBACK].handshake); LOG_INF("plat_data fifo capture offset: %u", - dp->plat_data.fifo[DAI_DIR_CAPTURE].offset); + dp->ssp_plat_data->fifo[DAI_DIR_CAPTURE].offset); LOG_INF("plat_data fifo capture handshake: %u", - dp->plat_data.fifo[DAI_DIR_CAPTURE].handshake); + dp->ssp_plat_data->fifo[DAI_DIR_CAPTURE].handshake); } /* Digital Audio interface formatting */ @@ -1031,6 +1128,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co const void *bespoke_cfg) { struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); struct dai_intel_ssp_freq_table *ft = dai_get_ftable(dp); uint32_t sscr0; uint32_t sscr1; @@ -1066,14 +1164,16 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co key = k_spin_lock(&dp->lock); /* ignore config if SSP is already configured */ - if (ssp->state[DAI_DIR_PLAYBACK] > DAI_STATE_READY || - ssp->state[DAI_DIR_CAPTURE] > DAI_STATE_READY) { - if (!memcmp(&ssp->params, bespoke_cfg, sizeof(struct dai_intel_ipc3_ssp_params))) { + if (dp->state[DAI_DIR_PLAYBACK] > DAI_STATE_READY || + dp->state[DAI_DIR_CAPTURE] > DAI_STATE_READY) { + if (!memcmp(&ssp_plat_data->params, bespoke_cfg, + sizeof(struct dai_intel_ipc3_ssp_params))) { LOG_INF("Already configured. Ignore config"); goto clk; } - if (ssp->clk_active & (SSP_CLK_MCLK_ACTIVE | SSP_CLK_BCLK_ACTIVE)) { + if (ssp_plat_data->clk_active & + (SSP_CLK_MCLK_ACTIVE | SSP_CLK_BCLK_ACTIVE)) { LOG_WRN("SSP active, cannot change config"); goto clk; } @@ -1081,7 +1181,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co /* safe to proceed and change HW config */ } - LOG_INF("SSP%d", dp->index); + LOG_INF("SSP%d", dp->dai_index); /* reset SSP settings */ /* sscr0 dynamic settings are DSS, EDSS, SCR, FRDC, ECS */ @@ -1104,7 +1204,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sspsp = 0; ssp->config = *config; - memcpy(&ssp->params, bespoke_cfg, sizeof(struct dai_intel_ipc3_ssp_params)); + memcpy(&ssp_plat_data->params, bespoke_cfg, sizeof(struct dai_intel_ipc3_ssp_params)); /* sspsp2 no dynamic setting */ sspsp2 = 0x0; @@ -1116,10 +1216,10 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co ssto = 0x0; /* sstsa dynamic setting is TTSA, default 2 slots */ - sstsa = SSTSA_SSTSA(ssp->params.tx_slots); + sstsa = SSTSA_SSTSA(ssp_plat_data->params.tx_slots); /* ssrsa dynamic setting is RTSA, default 2 slots */ - ssrsa = SSRSA_SSRSA(ssp->params.rx_slots); + ssrsa = SSRSA_SSRSA(ssp_plat_data->params.rx_slots); switch (config->format & DAI_INTEL_IPC3_SSP_FMT_CLOCK_PROVIDER_MASK) { case DAI_INTEL_IPC3_SSP_FMT_CBP_CFP: @@ -1166,7 +1266,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co } /* supporting bclk idle state */ - if (ssp->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_IDLE_HIGH) { + if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_IDLE_HIGH) { /* bclk idle state high */ sspsp |= SSPSP_SCMODE((inverted_bclk ^ 0x3) & 0x3); } else { @@ -1179,20 +1279,20 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co /* Additional hardware settings */ /* Receiver Time-out Interrupt Disabled/Enabled */ - sscr1 |= (ssp->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_TINTE) ? + sscr1 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_TINTE) ? SSCR1_TINTE : 0; /* Peripheral Trailing Byte Interrupts Disable/Enable */ - sscr1 |= (ssp->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PINTE) ? + sscr1 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PINTE) ? SSCR1_PINTE : 0; /* Enable/disable internal loopback. Output of transmit serial * shifter connected to input of receive serial shifter, internally. */ - sscr1 |= (ssp->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_LBM) ? + sscr1 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_LBM) ? SSCR1_LBM : 0; - if (ssp->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_LBM) { + if (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_LBM) { LOG_INF("going for loopback!"); } else { LOG_INF("no loopback!"); @@ -1201,69 +1301,70 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co /* Transmit data are driven at the same/opposite clock edge specified * in SSPSP.SCMODE[1:0] */ - sscr2 |= (ssp->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_SMTATF) ? + sscr2 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_SMTATF) ? SSCR2_SMTATF : 0; /* Receive data are sampled at the same/opposite clock edge specified * in SSPSP.SCMODE[1:0] */ - sscr2 |= (ssp->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_MMRATF) ? + sscr2 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_MMRATF) ? SSCR2_MMRATF : 0; /* Enable/disable the fix for PSP consumer mode TXD wait for frame * de-assertion before starting the second channel */ - sscr2 |= (ssp->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PSPSTWFDFD) ? + sscr2 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PSPSTWFDFD) ? SSCR2_PSPSTWFDFD : 0; /* Enable/disable the fix for PSP provider mode FSRT with dummy stop & * frame end padding capability */ - sscr2 |= (ssp->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PSPSRWFDFD) ? + sscr2 |= (ssp_plat_data->params.quirks & DAI_INTEL_IPC3_SSP_QUIRK_PSPSRWFDFD) ? SSCR2_PSPSRWFDFD : 0; - if (!ssp->params.mclk_rate || - ssp->params.mclk_rate > ft[DAI_INTEL_SSP_MAX_FREQ_INDEX].freq) { - LOG_ERR("invalid MCLK = %d Hz (valid < %d)", ssp->params.mclk_rate, + if (!ssp_plat_data->params.mclk_rate || + ssp_plat_data->params.mclk_rate > ft[DAI_INTEL_SSP_MAX_FREQ_INDEX].freq) { + LOG_ERR("invalid MCLK = %d Hz (valid < %d)", ssp_plat_data->params.mclk_rate, ft[DAI_INTEL_SSP_MAX_FREQ_INDEX].freq); ret = -EINVAL; goto out; } - if (!ssp->params.bclk_rate || ssp->params.bclk_rate > ssp->params.mclk_rate) { - LOG_ERR("BCLK %d Hz = 0 or > MCLK %d Hz", ssp->params.bclk_rate, - ssp->params.mclk_rate); + if (!ssp_plat_data->params.bclk_rate || + ssp_plat_data->params.bclk_rate > ssp_plat_data->params.mclk_rate) { + LOG_ERR("BCLK %d Hz = 0 or > MCLK %d Hz", ssp_plat_data->params.bclk_rate, + ssp_plat_data->params.mclk_rate); ret = -EINVAL; goto out; } /* calc frame width based on BCLK and rate - must be divisible */ - if (ssp->params.bclk_rate % ssp->params.fsync_rate) { - LOG_ERR("BCLK %d is not divisible by rate %d", ssp->params.bclk_rate, - ssp->params.fsync_rate); + if (ssp_plat_data->params.bclk_rate % ssp_plat_data->params.fsync_rate) { + LOG_ERR("BCLK %d is not divisible by rate %d", ssp_plat_data->params.bclk_rate, + ssp_plat_data->params.fsync_rate); ret = -EINVAL; goto out; } /* must be enough BCLKs for data */ - bdiv = ssp->params.bclk_rate / ssp->params.fsync_rate; - if (bdiv < ssp->params.tdm_slot_width * ssp->params.tdm_slots) { + bdiv = ssp_plat_data->params.bclk_rate / ssp_plat_data->params.fsync_rate; + if (bdiv < ssp_plat_data->params.tdm_slot_width * ssp_plat_data->params.tdm_slots) { LOG_ERR("not enough BCLKs need %d", - ssp->params.tdm_slot_width * ssp->params.tdm_slots); + ssp_plat_data->params.tdm_slot_width * ssp_plat_data->params.tdm_slots); ret = -EINVAL; goto out; } /* tdm_slot_width must be <= 38 for SSP */ - if (ssp->params.tdm_slot_width > 38) { - LOG_ERR("tdm_slot_width %d > 38", ssp->params.tdm_slot_width); + if (ssp_plat_data->params.tdm_slot_width > 38) { + LOG_ERR("tdm_slot_width %d > 38", ssp_plat_data->params.tdm_slot_width); ret = -EINVAL; goto out; } - bdiv_min = ssp->params.tdm_slots * - (ssp->params.tdm_per_slot_padding_flag ? - ssp->params.tdm_slot_width : ssp->params.sample_valid_bits); + bdiv_min = ssp_plat_data->params.tdm_slots * + (ssp_plat_data->params.tdm_per_slot_padding_flag ? + ssp_plat_data->params.tdm_slot_width : ssp_plat_data->params.sample_valid_bits); if (bdiv < bdiv_min) { LOG_ERR("bdiv(%d) < bdiv_min(%d)", bdiv, bdiv_min); ret = -EINVAL; @@ -1283,7 +1384,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co start_delay = true; - sscr0 |= SSCR0_FRDC(ssp->params.tdm_slots); + sscr0 |= SSCR0_FRDC(ssp_plat_data->params.tdm_slots); if (bdiv % 2) { LOG_ERR("bdiv %d is not divisible by 2", bdiv); @@ -1331,7 +1432,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co /* default start_delay value is set to false */ - sscr0 |= SSCR0_FRDC(ssp->params.tdm_slots); + sscr0 |= SSCR0_FRDC(ssp_plat_data->params.tdm_slots); /* LJDFD enable */ sscr2 &= ~SSCR2_LJDFD; @@ -1387,19 +1488,19 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co /* default start_delay value is set to false */ - sscr0 |= SSCR0_MOD | SSCR0_FRDC(ssp->params.tdm_slots); + sscr0 |= SSCR0_MOD | SSCR0_FRDC(ssp_plat_data->params.tdm_slots); /* set asserted frame length */ frame_len = 1; /* default */ - if (cfs && ssp->params.frame_pulse_width > 0 && - ssp->params.frame_pulse_width <= + if (cfs && ssp_plat_data->params.frame_pulse_width > 0 && + ssp_plat_data->params.frame_pulse_width <= DAI_INTEL_IPC3_SSP_FRAME_PULSE_WIDTH_MAX) { - frame_len = ssp->params.frame_pulse_width; + frame_len = ssp_plat_data->params.frame_pulse_width; } /* frame_pulse_width must less or equal 38 */ - if (ssp->params.frame_pulse_width > + if (ssp_plat_data->params.frame_pulse_width > DAI_INTEL_IPC3_SSP_FRAME_PULSE_WIDTH_MAX) { LOG_ERR("frame_pulse_width > %d", DAI_INTEL_IPC3_SSP_FRAME_PULSE_WIDTH_MAX); ret = -EINVAL; @@ -1413,20 +1514,20 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co */ sspsp |= SSPSP_SFRMP(!inverted_frame); - active_tx_slots = POPCOUNT(ssp->params.tx_slots); - active_rx_slots = POPCOUNT(ssp->params.rx_slots); + active_tx_slots = POPCOUNT(ssp_plat_data->params.tx_slots); + active_rx_slots = POPCOUNT(ssp_plat_data->params.rx_slots); /* * handle TDM mode, TDM mode has padding at the end of * each slot. The amount of padding is equal to result of * subtracting slot width and valid bits per slot. */ - if (ssp->params.tdm_per_slot_padding_flag) { - frame_end_padding = bdiv - ssp->params.tdm_slots * - ssp->params.tdm_slot_width; + if (ssp_plat_data->params.tdm_per_slot_padding_flag) { + frame_end_padding = bdiv - ssp_plat_data->params.tdm_slots * + ssp_plat_data->params.tdm_slot_width; - slot_end_padding = ssp->params.tdm_slot_width - - ssp->params.sample_valid_bits; + slot_end_padding = ssp_plat_data->params.tdm_slot_width - + ssp_plat_data->params.sample_valid_bits; if (slot_end_padding > DAI_INTEL_IPC3_SSP_SLOT_PADDING_MAX) { @@ -1456,7 +1557,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sspsp |= SSPSP_SFRMWDTH(frame_len); - data_size = ssp->params.sample_valid_bits; + data_size = ssp_plat_data->params.sample_valid_bits; if (data_size > 16) { sscr0 |= (SSCR0_EDSS | SSCR0_DSIZE(data_size - 16)); @@ -1465,7 +1566,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co } /* setting TFT and RFT */ - switch (ssp->params.sample_valid_bits) { + switch (ssp_plat_data->params.sample_valid_bits) { case 16: /* use 2 bytes for each slot */ sample_width = 2; @@ -1476,7 +1577,7 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sample_width = 4; break; default: - LOG_ERR("sample_valid_bits %d", ssp->params.sample_valid_bits); + LOG_ERR("sample_valid_bits %d", ssp_plat_data->params.sample_valid_bits); ret = -EINVAL; goto out; } @@ -1506,27 +1607,28 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co LOG_INF("ssrsa = 0x%08x, sstsa = 0x%08x", ssrsa, sstsa); - ssp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; - ssp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; + dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; + dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; clk: switch (config->options & DAI_INTEL_IPC3_SSP_CONFIG_FLAGS_CMD_MASK) { case DAI_INTEL_IPC3_SSP_CONFIG_FLAGS_HW_PARAMS: - if (ssp->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_MCLK_ES) { + if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_MCLK_ES) { ret = dai_ssp_mclk_prepare_enable(dp); if (ret < 0) { goto out; } - ssp->clk_active |= SSP_CLK_MCLK_ES_REQ; + ssp_plat_data->clk_active |= SSP_CLK_MCLK_ES_REQ; - LOG_INF("hw_params stage: enabled MCLK clocks for SSP%d...", dp->index); + LOG_INF("hw_params stage: enabled MCLK clocks for SSP%d...", + dp->dai_index); } - if (ssp->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_ES) { + if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_ES) { bool enable_sse = false; - if (!(ssp->clk_active & SSP_CLK_BCLK_ACTIVE)) { + if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE)) { enable_sse = true; } @@ -1535,39 +1637,43 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co goto out; } - ssp->clk_active |= SSP_CLK_BCLK_ES_REQ; + ssp_plat_data->clk_active |= SSP_CLK_BCLK_ES_REQ; if (enable_sse) { /* enable port */ dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, SSCR0_SSE); - LOG_INF("SSE set for SSP%d", dp->index); + LOG_INF("SSE set for SSP%d", ssp_plat_data->ssp_index); } - LOG_INF("hw_params stage: enabled BCLK clocks for SSP%d...", dp->index); + LOG_INF("hw_params stage: enabled BCLK clocks for SSP%d...", + ssp_plat_data->ssp_index); } break; case DAI_INTEL_IPC3_SSP_CONFIG_FLAGS_HW_FREE: /* disable SSP port if no users */ - if (ssp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING || - ssp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { - LOG_INF("hw_free stage: ignore since SSP%d still in use", dp->index); + if (dp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING || + dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { + LOG_INF("hw_free stage: ignore since SSP%d still in use", + dp->dai_index); break; } - if (ssp->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_ES) { - LOG_INF("hw_free stage: releasing BCLK clocks for SSP%d...", dp->index); - if (ssp->clk_active & SSP_CLK_BCLK_ACTIVE) { + if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_BCLK_ES) { + LOG_INF("hw_free stage: releasing BCLK clocks for SSP%d...", + dp->dai_index); + if (ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE) { dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, 0); - LOG_INF("SSE clear for SSP%d", dp->index); + LOG_INF("SSE clear for SSP%d", dp->dai_index); } dai_ssp_bclk_disable_unprepare(dp); - ssp->clk_active &= ~SSP_CLK_BCLK_ES_REQ; + ssp_plat_data->clk_active &= ~SSP_CLK_BCLK_ES_REQ; } - if (ssp->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_MCLK_ES) { - LOG_INF("hw_free stage: releasing MCLK clocks for SSP%d...", dp->index); + if (ssp_plat_data->params.clks_control & DAI_INTEL_IPC3_SSP_CLKCTRL_MCLK_ES) { + LOG_INF("hw_free stage: releasing MCLK clocks for SSP%d...", + dp->dai_index); dai_ssp_mclk_disable_unprepare(dp); - ssp->clk_active &= ~SSP_CLK_MCLK_ES_REQ; + ssp_plat_data->clk_active &= ~SSP_CLK_MCLK_ES_REQ; } break; default: @@ -1756,7 +1862,6 @@ static int dai_ssp_set_clock_control_ver_1(struct dai_intel_ssp *dp, static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_config *cfg, const struct dai_intel_ipc4_ssp_config *regs) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); uint32_t ssc0, sstsa, ssrsa, sscr1; ssc0 = regs->ssc0; @@ -1764,7 +1869,7 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co ssrsa = SSRSA_GET(regs->ssrsa); sscr1 = regs->ssc1 & ~(SSCR1_RSRE | SSCR1_TSRE); - LOG_INF("SSP%d configuration:", dp->index); + LOG_INF("SSP%d configuration:", dp->dai_index); if (regs->sstsa & SSTSA_TXEN || regs->ssrsa & SSRSA_RXEN || regs->ssc1 & (SSCR1_RSRE | SSCR1_TSRE)) { LOG_INF(" Ignoring %s%s%s%sfrom blob", @@ -1794,18 +1899,18 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co LOG_INF(" ssioc = 0x%08x, ssrsa = 0x%08x, sstsa = 0x%08x", regs->ssioc, ssrsa, sstsa); - ssp->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); + dp->ssp_plat_data->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); if (ssc0 & SSCR0_EDSS) { - ssp->params.sample_valid_bits += 16; + dp->ssp_plat_data->params.sample_valid_bits += 16; } - ssp->params.tdm_slots = SSCR0_FRDC_GET(ssc0); - ssp->params.tx_slots = SSTSA_GET(sstsa); - ssp->params.rx_slots = SSRSA_GET(ssrsa); - ssp->params.fsync_rate = cfg->rate; + dp->ssp_plat_data->params.tdm_slots = SSCR0_FRDC_GET(ssc0); + dp->ssp_plat_data->params.tx_slots = SSTSA_GET(sstsa); + dp->ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); + dp->ssp_plat_data->params.fsync_rate = cfg->rate; - ssp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; - ssp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; + dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; + dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; } static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_config *cfg, @@ -1813,13 +1918,15 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co { const struct dai_intel_ipc4_ssp_configuration_blob_ver_1_5 *blob15 = spec_config; const struct dai_intel_ipc4_ssp_configuration_blob *blob = spec_config; - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); int err; /* set config only once for playback or capture */ - if (ssp->state[DAI_DIR_PLAYBACK] > DAI_STATE_READY || - ssp->state[DAI_DIR_CAPTURE] > DAI_STATE_READY) + if (ssp_plat_data->is_initialized) { + dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; + dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; return 0; + } if (blob15->version == SSP_BLOB_VER_1_5) { err = dai_ssp_parse_aux_data(dp, spec_config); @@ -1836,11 +1943,12 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co return err; } - ssp->clk_active |= SSP_CLK_MCLK_ES_REQ; + ssp_plat_data->clk_active |= SSP_CLK_MCLK_ES_REQ; /* enable port */ dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, SSCR0_SSE); - ssp->clk_active |= SSP_CLK_BCLK_ES_REQ; + ssp_plat_data->clk_active |= SSP_CLK_BCLK_ES_REQ; + ssp_plat_data->is_initialized = true; return 0; } @@ -1852,14 +1960,14 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co */ static int dai_ssp_pre_start(struct dai_intel_ssp *dp) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); int ret = 0; /* * We will test if mclk/bclk is configured in * ssp_mclk/bclk_prepare_enable/disable functions */ - if (!(ssp->clk_active & SSP_CLK_MCLK_ES_REQ)) { + if (!(ssp_plat_data->clk_active & SSP_CLK_MCLK_ES_REQ)) { /* MCLK config */ ret = dai_ssp_mclk_prepare_enable(dp); if (ret < 0) { @@ -1867,7 +1975,7 @@ static int dai_ssp_pre_start(struct dai_intel_ssp *dp) } } - if (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ)) { + if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)) { ret = dai_ssp_bclk_prepare_enable(dp); } @@ -1881,17 +1989,17 @@ static int dai_ssp_pre_start(struct dai_intel_ssp *dp) */ static void dai_ssp_post_stop(struct dai_intel_ssp *dp) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); /* release clocks if SSP is inactive */ - if (ssp->state[DAI_DIR_PLAYBACK] != DAI_STATE_RUNNING && - ssp->state[DAI_DIR_CAPTURE] != DAI_STATE_RUNNING) { - if (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ)) { - LOG_INF("releasing BCLK clocks for SSP%d...", dp->index); + if (dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_RUNNING && + dp->state[DAI_DIR_CAPTURE] != DAI_STATE_RUNNING) { + if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)) { + LOG_INF("releasing BCLK clocks for SSP%d...", dp->dai_index); dai_ssp_bclk_disable_unprepare(dp); } - if (!(ssp->clk_active & SSP_CLK_MCLK_ES_REQ)) { - LOG_INF("releasing MCLK clocks for SSP%d...", dp->index); + if (!(ssp_plat_data->clk_active & SSP_CLK_MCLK_ES_REQ)) { + LOG_INF("releasing MCLK clocks for SSP%d...", dp->dai_index); dai_ssp_mclk_disable_unprepare(dp); } } @@ -1899,25 +2007,25 @@ static void dai_ssp_post_stop(struct dai_intel_ssp *dp) static void dai_ssp_early_start(struct dai_intel_ssp *dp, int direction) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); k_spinlock_key_t key; key = k_spin_lock(&dp->lock); /* RX fifo must be cleared before start */ if (direction == DAI_DIR_CAPTURE) { - LOG_INF("SSP%d RX", dp->index); + LOG_INF("SSP%d RX", dp->dai_index); ssp_empty_rx_fifo_on_start(dp); } else { - LOG_INF("SSP%d TX", dp->index); + LOG_INF("SSP%d TX", dp->dai_index); } /* request mclk/bclk */ dai_ssp_pre_start(dp); - if (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ)) { + if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)) { /* enable port */ - LOG_INF("SSP%d: set SSE", dp->index); + LOG_INF("SSP%d: set SSE", dp->dai_index); dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, SSCR0_SSE); } @@ -1935,16 +2043,17 @@ static void dai_ssp_start(struct dai_intel_ssp *dp, int direction) /* enable DMA */ if (direction == DAI_DIR_PLAYBACK) { - LOG_INF("SSP%d TX", dp->index); + LOG_INF("SSP%d TX", dp->dai_index); dai_ssp_update_bits(dp, SSCR1, SSCR1_TSRE, SSCR1_TSRE); dai_ssp_update_bits(dp, SSTSA, SSTSA_TXEN, SSTSA_TXEN); } else { - LOG_INF("SSP%d RX", dp->index); + LOG_INF("SSP%d RX", dp->dai_index); dai_ssp_update_bits(dp, SSCR1, SSCR1_RSRE, SSCR1_RSRE); dai_ssp_update_bits(dp, SSRSA, SSRSA_RXEN, SSRSA_RXEN); } - ssp->state[direction] = DAI_STATE_RUNNING; + dp->state[direction] = DAI_STATE_RUNNING; + ssp_acquire_port(dp->ssp_plat_data); /* * Wait to get valid fifo status in clock consumer mode. TODO it's @@ -1968,6 +2077,7 @@ static void dai_ssp_start(struct dai_intel_ssp *dp, int direction) static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) { struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); k_spinlock_key_t key; key = k_spin_lock(&dp->lock); @@ -1988,64 +2098,68 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) /* stop Rx if neeed */ if (direction == DAI_DIR_CAPTURE && - ssp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING) { - LOG_INF("SSP%d RX", dp->index); + dp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING) { + LOG_INF("SSP%d RX", dp->dai_index); dai_ssp_update_bits(dp, SSRSA, SSRSA_RXEN, 0); dai_ssp_update_bits(dp, SSCR1, SSCR1_RSRE, 0); ssp_empty_rx_fifo_on_stop(dp); - ssp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; + dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; + ssp_release_port(ssp_plat_data); } /* stop Tx if needed */ if (direction == DAI_DIR_PLAYBACK && - ssp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { - LOG_INF("SSP%d TX", dp->index); + dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { + LOG_INF("SSP%d TX", dp->dai_index); dai_ssp_update_bits(dp, SSCR1, SSCR1_TSRE, 0); dai_ssp_empty_tx_fifo(dp); dai_ssp_update_bits(dp, SSTSA, SSTSA_TXEN, 0); - ssp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; + dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; + ssp_release_port(ssp_plat_data); } /* disable SSP port if no users */ - if (ssp->state[DAI_DIR_CAPTURE] == DAI_STATE_PRE_RUNNING && - ssp->state[DAI_DIR_PLAYBACK] == DAI_STATE_PRE_RUNNING && + if (dp->state[DAI_DIR_CAPTURE] == DAI_STATE_PRE_RUNNING && + dp->state[DAI_DIR_PLAYBACK] == DAI_STATE_PRE_RUNNING && COND_CODE_1(CONFIG_INTEL_ADSP_CAVS, - (!(ssp->clk_active & SSP_CLK_BCLK_ES_REQ)), (true))) { - LOG_INF("SSP%d: clear SSE", dp->index); - dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, 0); + (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)), (true))) { + + if (!ssp_is_acquired(ssp_plat_data)) { + dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, 0); + LOG_INF("%s SSE clear SSP%d", __func__, ssp_plat_data->ssp_index); + } } - dai_ssp_post_stop(dp); + if (!ssp_is_acquired(ssp_plat_data)) { + dai_ssp_post_stop(dp); + } k_spin_unlock(&dp->lock, key); } static void dai_ssp_pause(struct dai_intel_ssp *dp, int direction) { - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); - if (direction == DAI_DIR_CAPTURE) { - LOG_INF("SSP%d RX", dp->index); + LOG_INF("SSP%d RX", dp->dai_index); } else { - LOG_INF("SSP%d TX", dp->index); + LOG_INF("SSP%d TX", dp->dai_index); } - ssp->state[direction] = DAI_STATE_PAUSED; + dp->state[direction] = DAI_STATE_PAUSED; } static int dai_ssp_trigger(const struct device *dev, enum dai_dir dir, enum dai_trigger_cmd cmd) { struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; - struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); int array_index = SSP_ARRAY_INDEX(dir); - LOG_DBG("SSP%d: cmd %d", dp->index, cmd); + LOG_DBG("SSP%d: cmd %d", dp->dai_index, cmd); switch (cmd) { case DAI_TRIGGER_START: - if (ssp->state[array_index] == DAI_STATE_PAUSED || - ssp->state[array_index] == DAI_STATE_PRE_RUNNING) { + if (dp->state[array_index] == DAI_STATE_PAUSED || + dp->state[array_index] == DAI_STATE_PRE_RUNNING) { dai_ssp_start(dp, array_index); } break; @@ -2070,6 +2184,7 @@ static int dai_ssp_config_get(const struct device *dev, struct dai_config *cfg, struct dai_config *params = (struct dai_config *)dev->config; struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); if (!cfg) { return -EINVAL; @@ -2080,15 +2195,15 @@ static int dai_ssp_config_get(const struct device *dev, struct dai_config *cfg, return 0; } - params->rate = ssp->params.fsync_rate; + params->rate = ssp_plat_data->params.fsync_rate; if (dir == DAI_DIR_PLAYBACK) { - params->channels = POPCOUNT(ssp->params.tx_slots); + params->channels = POPCOUNT(ssp_plat_data->params.tx_slots); } else { - params->channels = POPCOUNT(ssp->params.rx_slots); + params->channels = POPCOUNT(ssp_plat_data->params.rx_slots); } - params->word_size = ssp->params.sample_valid_bits; + params->word_size = ssp_plat_data->params.sample_valid_bits; *cfg = *params; @@ -2106,7 +2221,7 @@ static int dai_ssp_config_set(const struct device *dev, const struct dai_config } else { ret = dai_ssp_set_config_blob(dp, cfg, bespoke_cfg); } - dai_ssp_program_channel_map(dp, cfg, dp->index); + dai_ssp_program_channel_map(dp, cfg, dp->ssp_index); return ret; } @@ -2115,19 +2230,20 @@ static const struct dai_properties *dai_ssp_get_properties(const struct device * { struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; struct dai_intel_ssp_pdata *ssp = dai_get_drvdata(dp); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); struct dai_properties *prop = &ssp->props; int array_index = SSP_ARRAY_INDEX(dir); - prop->fifo_address = dp->plat_data.fifo[array_index].offset; - prop->dma_hs_id = dp->plat_data.fifo[array_index].handshake; + prop->fifo_address = ssp_plat_data->fifo[array_index].offset; + prop->dma_hs_id = ssp_plat_data->fifo[array_index].handshake; - if (ssp->clk_active & SSP_CLK_BCLK_ACTIVE) { + if (ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE) { prop->reg_init_delay = 0; } else { - prop->reg_init_delay = ssp->params.bclk_delay; + prop->reg_init_delay = ssp_plat_data->params.bclk_delay; } - LOG_INF("SSP%u: fifo %u, handshake %u, init delay %u", dp->index, prop->fifo_address, + LOG_INF("SSP%u: fifo %u, handshake %u, init delay %u", dp->dai_index, prop->fifo_address, prop->dma_hs_id, prop->reg_init_delay); return prop; @@ -2135,6 +2251,7 @@ static const struct dai_properties *dai_ssp_get_properties(const struct device * static int dai_ssp_probe(struct dai_intel_ssp *dp) { + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); struct dai_intel_ssp_pdata *ssp; if (dai_get_drvdata(dp)) { @@ -2144,47 +2261,59 @@ static int dai_ssp_probe(struct dai_intel_ssp *dp) /* allocate private data */ ssp = k_calloc(1, sizeof(*ssp)); if (!ssp) { - LOG_ERR("SSP%d: alloc failed", dp->index); + LOG_ERR("SSP%d: alloc failed", ssp_plat_data->ssp_index); return -ENOMEM; } dai_set_drvdata(dp, ssp); - ssp->state[DAI_DIR_PLAYBACK] = DAI_STATE_READY; - ssp->state[DAI_DIR_CAPTURE] = DAI_STATE_READY; + dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_READY; + dp->state[DAI_DIR_CAPTURE] = DAI_STATE_READY; + + if (ssp_plat_data->is_power_en) { + return 0; + } #if CONFIG_INTEL_MN /* Reset M/N, power-gating functions need it */ - dai_ssp_mn_reset_bclk_divider(dp, dp->index); + dai_ssp_mn_reset_bclk_divider(dp, ssp_plat_data->ssp_index); #endif /* Enable SSP power */ - dai_ssp_pm_runtime_en_ssp_power(dp, dp->index); + dai_ssp_pm_runtime_en_ssp_power(dp, ssp_plat_data->ssp_index); /* Disable dynamic clock gating before touching any register */ - dai_ssp_pm_runtime_dis_ssp_clk_gating(dp, dp->index); + dai_ssp_pm_runtime_dis_ssp_clk_gating(dp, ssp_plat_data->ssp_index); + + ssp_plat_data->is_power_en = true; return 0; } static int dai_ssp_remove(struct dai_intel_ssp *dp) { - dai_ssp_pm_runtime_en_ssp_clk_gating(dp, dp->index); + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + + dai_ssp_pm_runtime_en_ssp_clk_gating(dp, ssp_plat_data->ssp_index); dai_ssp_mclk_disable_unprepare(dp); dai_ssp_bclk_disable_unprepare(dp); /* Disable SSP power */ - dai_ssp_pm_runtime_dis_ssp_power(dp, dp->index); + dai_ssp_pm_runtime_dis_ssp_power(dp, ssp_plat_data->ssp_index); k_free(dai_get_drvdata(dp)); dai_set_drvdata(dp, NULL); + ssp_plat_data->is_initialized = false; + ssp_plat_data->is_power_en = false; + return 0; } static int ssp_pm_action(const struct device *dev, enum pm_device_action action) { struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; + switch (action) { case PM_DEVICE_ACTION_SUSPEND: dai_ssp_remove(dp); @@ -2203,8 +2332,19 @@ static int ssp_pm_action(const struct device *dev, enum pm_device_action action) return 0; } +static int dai_intel_ssp_init_device(const struct device *dev) +{ + struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; + + dp->ssp_plat_data = ssp_get_device_instance(dp->ssp_index); + + return 0; +}; + static int ssp_init(const struct device *dev) { + dai_intel_ssp_init_device(dev); + if (pm_device_on_power_domain(dev)) { pm_device_init_off(dev); } else { @@ -2223,60 +2363,20 @@ static struct dai_driver_api dai_intel_ssp_api_funcs = { .get_properties = dai_ssp_get_properties, }; -static struct dai_intel_ssp_freq_table ssp_freq_table[] = { - { DT_PROP(DT_NODELABEL(audioclk), clock_frequency), - DT_PROP(DT_NODELABEL(audioclk), clock_frequency) / 1000}, - { DT_PROP(DT_NODELABEL(sysclk), clock_frequency), - DT_PROP(DT_NODELABEL(sysclk), clock_frequency) / 1000}, - { DT_PROP(DT_NODELABEL(pllclk), clock_frequency), - DT_PROP(DT_NODELABEL(pllclk), clock_frequency) / 1000}, -}; -static uint32_t ssp_freq_sources[] = { - DAI_INTEL_SSP_CLOCK_AUDIO_CARDINAL, - DAI_INTEL_SSP_CLOCK_XTAL_OSCILLATOR, - DAI_INTEL_SSP_CLOCK_PLL_FIXED, -}; - -static struct dai_intel_ssp_mn ssp_mn_divider = { - .base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(ssp0), 1), -}; +#define DT_DRV_COMPAT intel_ssp_dai -static const char irq_name_level5_z[] = "level5"; - -#define DAI_INTEL_SSP_DEVICE_INIT(n) \ - static struct dai_config dai_intel_ssp_config_##n = { \ - .type = DAI_INTEL_SSP, \ - .dai_index = n, \ - }; \ - static struct dai_intel_ssp dai_intel_ssp_data_##n = { \ - .index = n, \ - .plat_data = { \ - .base = DT_INST_REG_ADDR_BY_IDX(n, 0), \ - IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(sspbase)), \ - (.ip_base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(sspbase), 0),))\ - .shim_base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(shim), 0), \ - IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(hdamlssp)), \ - (.hdamlssp_base = DT_REG_ADDR(DT_NODELABEL(hdamlssp)),))\ - IF_ENABLED(DT_INST_PROP_HAS_IDX(n, i2svss, 0), \ - (.i2svss_base = DT_INST_PROP_BY_IDX(n, i2svss, 0),))\ - .irq = n, \ - .irq_name = irq_name_level5_z, \ - .fifo[DAI_DIR_PLAYBACK].offset = \ - DT_INST_REG_ADDR_BY_IDX(n, 0) + SSDR, \ - .fifo[DAI_DIR_PLAYBACK].handshake = \ - DT_INST_DMAS_CELL_BY_NAME(n, tx, channel), \ - .fifo[DAI_DIR_CAPTURE].offset = \ - DT_INST_REG_ADDR_BY_IDX(n, 0) + SSDR, \ - .fifo[DAI_DIR_CAPTURE].handshake = \ - DT_INST_DMAS_CELL_BY_NAME(n, rx, channel), \ - .mn_inst = &ssp_mn_divider, \ - .ftable = ssp_freq_table, \ - .fsources = ssp_freq_sources, \ - }, \ +#define DAI_INTEL_SSP_DEVICE_INIT(n) \ + static struct dai_config dai_intel_ssp_config_##n = { \ + .type = DAI_INTEL_SSP, \ + .dai_index = DT_INST_REG_ADDR(n), \ + }; \ + static struct dai_intel_ssp dai_intel_ssp_data_##n = { \ + .dai_index = DT_INST_REG_ADDR(n), \ + .ssp_index = DT_PROP(DT_INST_PARENT(n), ssp_index), \ }; \ \ - PM_DEVICE_DT_INST_DEFINE(n, ssp_pm_action); \ + PM_DEVICE_DT_INST_DEFINE(n, ssp_pm_action); \ \ DEVICE_DT_INST_DEFINE(n, \ ssp_init, PM_DEVICE_DT_INST_GET(n), \ diff --git a/drivers/dai/intel/ssp/ssp.h b/drivers/dai/intel/ssp/ssp.h index 5a187730dd538b..f35b398b6b78b9 100644 --- a/drivers/dai/intel/ssp/ssp.h +++ b/drivers/dai/intel/ssp/ssp.h @@ -316,6 +316,10 @@ struct dai_intel_ssp_plat_fifo_data { }; struct dai_intel_ssp_plat_data { + uint32_t ssp_index; + int acquire_count; + bool is_initialized; + bool is_power_en; uint32_t base; uint32_t ip_base; uint32_t shim_base; @@ -330,24 +334,25 @@ struct dai_intel_ssp_plat_data { struct dai_intel_ssp_mn *mn_inst; struct dai_intel_ssp_freq_table *ftable; uint32_t *fsources; + uint32_t clk_active; + struct dai_intel_ipc3_ssp_params params; }; struct dai_intel_ssp_pdata { uint32_t sscr0; uint32_t sscr1; uint32_t psp; - uint32_t state[2]; - uint32_t clk_active; struct dai_config config; struct dai_properties props; - struct dai_intel_ipc3_ssp_params params; }; struct dai_intel_ssp { - uint32_t index; /**< index */ + uint32_t dai_index; + uint32_t ssp_index; + uint32_t state[2]; struct k_spinlock lock; /**< locking mechanism */ int sref; /**< simple ref counter, guarded by lock */ - struct dai_intel_ssp_plat_data plat_data; + struct dai_intel_ssp_plat_data *ssp_plat_data; void *priv_data; }; diff --git a/dts/bindings/i2s/intel,ssp-dai.yaml b/dts/bindings/i2s/intel,ssp-dai.yaml index 59a778baa1f580..8fc6f1a2e907bd 100644 --- a/dts/bindings/i2s/intel,ssp-dai.yaml +++ b/dts/bindings/i2s/intel,ssp-dai.yaml @@ -1,8 +1,7 @@ -# Copyright (c) 2022 Intel Corporation -# +# Copyright (c) 2024 Intel Corporation # SPDX-License-Identifier: Apache-2.0 -description: Intel SSP DAI controller +description: Intel SSP DAI node compatible: "intel,ssp-dai" @@ -11,18 +10,3 @@ include: base.yaml properties: reg: required: true - - interrupts: - required: true - - interrupt-parent: - required: true - - dmas: - required: true - - dma-names: - required: true - - i2svss: - type: array diff --git a/dts/bindings/i2s/intel,ssp.yaml b/dts/bindings/i2s/intel,ssp.yaml new file mode 100644 index 00000000000000..76b59e7c2bcf33 --- /dev/null +++ b/dts/bindings/i2s/intel,ssp.yaml @@ -0,0 +1,32 @@ +# Copyright (c) 2024 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Intel SSP DAI controller + +compatible: "intel,ssp" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + interrupt-parent: + required: true + + dmas: + required: true + + dma-names: + required: true + + i2svss: + type: array + + ssp-index: + type: int + required: true diff --git a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi index 1c770ea88267e0..a9a70d64ba923e 100644 --- a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi @@ -243,10 +243,15 @@ status = "okay"; }; + sspbase: ssp_base@28800 { + compatible = "intel,ssp-sspbase"; + reg = <0x28800 0x1000>; + }; + ssp0: ssp@28000 { - compatible = "intel,ssp-dai"; #address-cells = <1>; #size-cells = <0>; + compatible = "intel,ssp"; reg = <0x00028000 0x1000 0x00079C00 0x200>; interrupts = <0x00 0 0>; @@ -255,16 +260,18 @@ &lpgpdma0 3>; dma-names = "tx", "rx"; power-domain = <&io0_domain>; + ssp-index = <0>; status = "okay"; - }; - sspbase: ssp_base@28800 { - compatible = "intel,ssp-sspbase"; - reg = <0x28800 0x1000>; + ssp00: ssp@0 { + compatible = "intel,ssp-dai"; + status = "okay"; + reg = <0x0>; + }; }; ssp1: ssp@29000 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00029000 0x1000 @@ -275,11 +282,18 @@ &lpgpdma0 5>; dma-names = "tx", "rx"; power-domain = <&io0_domain>; + ssp-index = <1>; status = "okay"; + + ssp10: ssp@10 { + compatible = "intel,ssp-dai"; + status = "okay"; + reg = <0x10>; + }; }; ssp2: ssp@2a000 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x0002a000 0x1000 @@ -290,7 +304,14 @@ &lpgpdma0 7>; dma-names = "tx", "rx"; power-domain = <&io0_domain>; + ssp-index = <2>; status = "okay"; + + ssp20: ssp@20 { + compatible = "intel,ssp-dai"; + status = "okay"; + reg = <0x20>; + }; }; mem_window0: mem_window@70200 { diff --git a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi index fef22aec7d0fc3..73e808dc3a961b 100644 --- a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi @@ -178,7 +178,7 @@ }; ssp0: ssp@28100 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00028100 0x1000 @@ -190,11 +190,18 @@ &hda_link_in 1>; dma-names = "tx", "rx"; power-domain = <&io0_domain>; + ssp-index = <0>; status = "okay"; + + ssp00: ssp@0 { + compatible = "intel,ssp-dai"; + status = "okay"; + reg = <0x0>; + }; }; ssp1: ssp@29100 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00029100 0x1000 @@ -206,11 +213,18 @@ &hda_link_in 2>; dma-names = "tx", "rx"; power-domain = <&io0_domain>; + ssp-index = <1>; status = "okay"; + + ssp10: ssp@10 { + compatible = "intel,ssp-dai"; + status = "okay"; + reg = <0x10>; + }; }; ssp2: ssp@2a100 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x0002a100 0x1000 @@ -222,7 +236,14 @@ &hda_link_in 3>; dma-names = "tx", "rx"; power-domain = <&io0_domain>; + ssp-index = <2>; status = "okay"; + + ssp20: ssp@20 { + compatible = "intel,ssp-dai"; + status = "okay"; + reg = <0x20>; + }; }; mem_window0: mem_window@70200 { diff --git a/dts/xtensa/intel/intel_adsp_cavs25.dtsi b/dts/xtensa/intel/intel_adsp_cavs25.dtsi index 36ad7afa218640..03faf222748f5a 100644 --- a/dts/xtensa/intel/intel_adsp_cavs25.dtsi +++ b/dts/xtensa/intel/intel_adsp_cavs25.dtsi @@ -217,7 +217,7 @@ }; ssp0: ssp@77000 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077000 0x200 @@ -227,12 +227,18 @@ dmas = <&lpgpdma0 2 &lpgpdma0 3>; dma-names = "tx", "rx"; - + ssp-index = <0>; status = "okay"; + + ssp00: ssp@0 { + compatible = "intel,ssp-dai"; + reg = <0x0>; + status = "okay"; + }; }; ssp1: ssp@77200 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077200 0x200 @@ -242,12 +248,18 @@ dmas = <&lpgpdma0 4 &lpgpdma0 5>; dma-names = "tx", "rx"; - + ssp-index = <1>; status = "okay"; + + ssp10: ssp@10 { + compatible = "intel,ssp-dai"; + reg = <0x10>; + status = "okay"; + }; }; ssp2: ssp@77400 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077400 0x200 @@ -257,12 +269,18 @@ dmas = <&lpgpdma0 6 &lpgpdma0 7>; dma-names = "tx", "rx"; - + ssp-index = <2>; status = "okay"; + + ssp20: ssp@20 { + compatible = "intel,ssp-dai"; + reg = <0x20>; + status = "okay"; + }; }; ssp3: ssp@77600 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077600 0x200 @@ -272,12 +290,18 @@ dmas = <&lpgpdma0 8 &lpgpdma0 9>; dma-names = "tx", "rx"; - + ssp-index = <3>; status = "okay"; + + ssp30: ssp@30 { + compatible = "intel,ssp-dai"; + reg = <0x30>; + status = "okay"; + }; }; ssp4: ssp@77800 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077800 0x200 @@ -287,12 +311,18 @@ dmas = <&lpgpdma0 10 &lpgpdma0 11>; dma-names = "tx", "rx"; - + ssp-index = <4>; status = "okay"; + + ssp40: ssp@40 { + compatible = "intel,ssp-dai"; + reg = <0x40>; + status = "okay"; + }; }; ssp5: ssp@77a00 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077A00 0x200 @@ -302,8 +332,14 @@ dmas = <&lpgpdma0 12 &lpgpdma0 13>; dma-names = "tx", "rx"; - + ssp-index = <5>; status = "okay"; + + ssp50: ssp@50 { + compatible = "intel,ssp-dai"; + reg = <0x50>; + status = "okay"; + }; }; /* diff --git a/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi b/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi index e5116ef22e1df7..28b982e993f6b2 100644 --- a/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi +++ b/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi @@ -242,7 +242,7 @@ }; ssp0: ssp@77000 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077000 0x200 @@ -252,12 +252,18 @@ dmas = <&lpgpdma0 2 &lpgpdma0 3>; dma-names = "tx", "rx"; - + ssp-index = <0>; status = "okay"; + + ssp00: ssp@0 { + compatible = "intel,ssp-dai"; + reg = <0x0>; + status = "okay"; + }; }; ssp1: ssp@77200 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077200 0x200 @@ -267,12 +273,18 @@ dmas = <&lpgpdma0 4 &lpgpdma0 5>; dma-names = "tx", "rx"; - + ssp-index = <1>; status = "okay"; + + ssp10: ssp@10 { + compatible = "intel,ssp-dai"; + reg = <0x10>; + status = "okay"; + }; }; ssp2: ssp@77400 { - compatible = "intel,ssp-dai"; + compatible = "intel,ssp"; #address-cells = <1>; #size-cells = <0>; reg = <0x00077400 0x200 @@ -282,8 +294,14 @@ dmas = <&lpgpdma0 6 &lpgpdma0 7>; dma-names = "tx", "rx"; - + ssp-index = <2>; status = "okay"; + + ssp20: ssp@20 { + compatible = "intel,ssp-dai"; + reg = <0x20>; + status = "okay"; + }; }; }; diff --git a/tests/boards/intel_adsp/ssp/src/main.c b/tests/boards/intel_adsp/ssp/src/main.c index 7ba608e4bbb4cf..4b0b8f09bd0fbf 100644 --- a/tests/boards/intel_adsp/ssp/src/main.c +++ b/tests/boards/intel_adsp/ssp/src/main.c @@ -44,7 +44,7 @@ struct sof_dai_ssp_params { } __packed; static const struct device *const dev_dai_ssp = - DEVICE_DT_GET(DT_NODELABEL(ssp0)); + DEVICE_DT_GET(DT_NODELABEL(ssp00)); static const struct device *const dev_dma_dw = DEVICE_DT_GET(DT_NODELABEL(lpgpdma0));