diff --git a/drivers/dai/intel/ssp/dai-params-intel-ipc4.h b/drivers/dai/intel/ssp/dai-params-intel-ipc4.h index 5d4782869ff..6d078cd0941 100644 --- a/drivers/dai/intel/ssp/dai-params-intel-ipc4.h +++ b/drivers/dai/intel/ssp/dai-params-intel-ipc4.h @@ -231,18 +231,27 @@ struct dai_intel_ipc4_ssp_config { uint32_t ssc1; uint32_t sscto; uint32_t sspsp; -#ifndef CONFIG_SOC_INTEL_ACE30_PTL uint32_t sstsa; uint32_t ssrsa; -#endif uint32_t ssc2; uint32_t sspsp2; uint32_t ssc3; uint32_t ssioc; -#ifdef CONFIG_SOC_INTEL_ACE30_PTL +} __packed; + +struct dai_intel_ipc4_ssp_config_ver_3_0 { + uint32_t ssc0; + uint32_t ssc1; + uint32_t sscto; + uint32_t sspsp; + uint32_t ssc2; + uint32_t sspsp2; + uint32_t ssc3; + uint32_t ssioc; + /* Specifies which time slots the DMA FIFO will receive from the SSP Interface*/ uint64_t ssmidytsa[I2SIPCMC]; + /* Specifies which time slots the DMA FIFO will transmit to the SSP Interface */ uint64_t ssmodytsa[I2SOPCMC]; -#endif } __packed; struct dai_intel_ipc4_ssp_mclk_config { @@ -260,7 +269,11 @@ struct dai_intel_ipc4_ssp_mclk_config_2 { } __packed; struct dai_intel_ipc4_ssp_driver_config { +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + struct dai_intel_ipc4_ssp_config_ver_3_0 i2s_config; +#else struct dai_intel_ipc4_ssp_config i2s_config; +#endif struct dai_intel_ipc4_ssp_mclk_config mclk_config; } __packed; @@ -340,4 +353,21 @@ struct dai_intel_ipc4_ssp_configuration_blob_ver_1_5 { struct dai_intel_ipc4_ssp_mclk_config_2 i2s_mclk_control; } __packed; +#define SSP_BLOB_VER_3_0 0xee000300 + +struct dai_intel_ipc4_ssp_configuration_blob_ver_3_0 { + union dai_intel_ipc4_gateway_attributes gw_attr; + + uint32_t version; + uint32_t size; + + /* TDM time slot mappings */ + uint32_t tdm_ts_group[DAI_INTEL_I2S_TDM_MAX_SLOT_MAP_COUNT]; + + /* i2s port configuration */ + struct dai_intel_ipc4_ssp_config_ver_3_0 i2s_ssp_config; + /* clock configuration parameters */ + struct dai_intel_ipc4_ssp_mclk_config_2 i2s_mclk_control; +} __packed; + #endif diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index a11f03ce4db..58ab0c10170 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -874,14 +874,20 @@ static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp, sys_write16((pcmsycm & 0xffff), reg_add); } #elif defined(CONFIG_SOC_INTEL_ACE30_PTL) + const struct dai_intel_ipc4_ssp_configuration_blob_ver_3_0 *blob30 = spec_config; const struct dai_intel_ipc4_ssp_configuration_blob *blob = spec_config; uint64_t time_slot_map = 0; uint16_t pcmsycm = cfg->link_config; uint8_t slot_count = 0; if (DAI_INTEL_SSP_IS_BIT_SET(cfg->link_config, 15)) { - time_slot_map = - blob->i2s_driver_config.i2s_config.ssmidytsa[cfg->tdm_slot_group]; + if (blob30->version == SSP_BLOB_VER_3_0) { + time_slot_map = + blob30->i2s_ssp_config.ssmidytsa[cfg->tdm_slot_group]; + } else { + time_slot_map = + blob->i2s_driver_config.i2s_config.ssmidytsa[cfg->tdm_slot_group]; + } slot_count = POPCOUNT(time_slot_map >> 32) + POPCOUNT(time_slot_map & 0xFFFFFFFF); pcmsycm = cfg->link_config | (slot_count - 1) << 4; uint32_t reg_add = dai_ip_base(dp) + 0x1000 * ssp_index + @@ -891,8 +897,13 @@ static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp, sys_write16((pcmsycm & 0xffff), reg_add); } else { - time_slot_map = - blob->i2s_driver_config.i2s_config.ssmodytsa[cfg->tdm_slot_group]; + if (blob30->version == SSP_BLOB_VER_3_0) { + time_slot_map = + blob30->i2s_ssp_config.ssmodytsa[cfg->tdm_slot_group]; + } else { + time_slot_map = + blob->i2s_driver_config.i2s_config.ssmodytsa[cfg->tdm_slot_group]; + } slot_count = POPCOUNT(time_slot_map >> 32) + POPCOUNT(time_slot_map & 0xFFFFFFFF); pcmsycm = cfg->link_config | (slot_count - 1) << 4; uint32_t reg_add = dai_ip_base(dp) + 0x1000 * ssp_index + @@ -1997,14 +2008,27 @@ static int dai_ssp_parse_tlv(struct dai_intel_ssp *dp, const uint8_t *aux_ptr, s static int dai_ssp_parse_aux_data(struct dai_intel_ssp *dp, const void *spec_config) { - const struct dai_intel_ipc4_ssp_configuration_blob_ver_1_5 *blob = spec_config; + const struct dai_intel_ipc4_ssp_configuration_blob_ver_1_5 *blob15 = spec_config; + const struct dai_intel_ipc4_ssp_configuration_blob_ver_3_0 *blob30 = spec_config; int cfg_len, pre_aux_len, aux_len; uint8_t *aux_ptr; - cfg_len = blob->size; - pre_aux_len = sizeof(*blob) + blob->i2s_mclk_control.mdivrcnt * sizeof(uint32_t); - aux_len = cfg_len - pre_aux_len; - aux_ptr = (uint8_t *)blob + pre_aux_len; + if (blob15->version == SSP_BLOB_VER_1_5) { + cfg_len = blob15->size; + pre_aux_len = sizeof(*blob15) + + blob15->i2s_mclk_control.mdivrcnt * sizeof(uint32_t); + aux_len = cfg_len - pre_aux_len; + aux_ptr = (uint8_t *)blob15 + pre_aux_len; + } else if (blob30->version == SSP_BLOB_VER_3_0) { + cfg_len = blob30->size; + pre_aux_len = sizeof(*blob30) + + blob30->i2s_mclk_control.mdivrcnt * sizeof(uint32_t); + aux_len = cfg_len - pre_aux_len; + aux_ptr = (uint8_t *)blob30 + pre_aux_len; + } else { + LOG_ERR("unsupported blob version"); + return -EINVAL; + } if (aux_len <= 0) { return 0; @@ -2041,25 +2065,73 @@ static int dai_ssp_set_clock_control_ver_1(struct dai_intel_ssp *dp, return 0; } +#ifdef CONFIG_SOC_INTEL_ACE30_PTL 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) + const void *spec_config) { struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + const struct dai_intel_ipc4_ssp_config_ver_3_0 *regs = spec_config; + uint32_t sscr1 = 0; + uint32_t sstsa = 0; + uint32_t ssrsa = 0; + uint32_t ssc0 = regs->ssc0; + sscr1 = regs->ssc1 & ~(SSCR1_RSVD21); + + LOG_INF("SSP%d configuration:", dp->dai_index); + + sys_write32(ssc0, dai_base(dp) + SSCR0); + sys_write32(regs->ssc2 & ~SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ + sys_write32(sscr1, dai_base(dp) + SSCR1); + sys_write32(regs->ssc2 | SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ + sys_write32(regs->ssc2, dai_base(dp) + SSCR2); + sys_write32(regs->sspsp, dai_base(dp) + SSPSP); + sys_write32(regs->sspsp2, dai_base(dp) + SSPSP2); + sys_write32(regs->ssioc, dai_base(dp) + SSIOC); + sys_write32(regs->sscto, dai_base(dp) + SSTO); + + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + sys_write64(regs->ssmidytsa[idx], dai_base(dp) + SSMIDyTSA(idx)); + } + + for (uint32_t idx = 0; idx < I2SOPCMC; ++idx) { + sys_write64(regs->ssmodytsa[idx], dai_base(dp) + SSMODyTSA(idx)); + } + + LOG_INF(" sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x", + ssc0, sscr1, regs->sscto, regs->sspsp); + LOG_INF(" sscr2 = 0x%08x, sspsp2 = 0x%08x, sscr3 = 0x%08x", + regs->ssc2, regs->sspsp2, regs->ssc3); + LOG_INF(" ssioc = 0x%08x", regs->ssioc); + + ssp_plat_data->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); + if (ssc0 & SSCR0_EDSS) { + ssp_plat_data->params.sample_valid_bits += 16; + } + + ssp_plat_data->params.tx_slots = regs->ssmodytsa[dp->tdm_slot_group]; + ssp_plat_data->params.rx_slots = regs->ssmidytsa[dp->tdm_slot_group]; + + ssp_plat_data->params.fsync_rate = cfg->rate; + dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; + dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; +} +#else +static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_config *cfg, + const void *spec_config) +{ + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + const struct dai_intel_ipc4_ssp_config *regs = spec_config; uint32_t sscr1 = 0; uint32_t sstsa = 0; uint32_t ssrsa = 0; uint32_t ssc0 = regs->ssc0; -#ifdef CONFIG_SOC_INTEL_ACE30_PTL - sscr1 = regs->ssc1 & ~(SSCR1_RSVD21); -#else sscr1 = regs->ssc1 & ~(SSCR1_RSRE | SSCR1_TSRE); sstsa = SSTSA_GET(regs->sstsa); ssrsa = SSRSA_GET(regs->ssrsa); -#endif LOG_INF("SSP%d configuration:", dp->dai_index); -#ifndef CONFIG_SOC_INTEL_ACE30_PTL + if (regs->sstsa & SSTSA_TXEN || regs->ssrsa & SSRSA_RXEN || regs->ssc1 & (SSCR1_RSRE | SSCR1_TSRE)) { LOG_INF(" Ignoring %s%s%s%sfrom blob", @@ -2068,32 +2140,19 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co regs->ssc1 & SSCR1_TSRE ? "SSCR1:TSRE " : "", regs->ssc1 & SSCR1_RSRE ? "SSCR1:RSRE " : ""); } -#endif sys_write32(ssc0, dai_base(dp) + SSCR0); sys_write32(regs->ssc2 & ~SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ sys_write32(sscr1, dai_base(dp) + SSCR1); sys_write32(regs->ssc2 | SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ sys_write32(regs->ssc2, dai_base(dp) + SSCR2); -#ifndef CONFIG_SOC_INTEL_ACE30_PTL sys_write32(regs->ssc3, dai_base(dp) + SSCR3); -#endif sys_write32(regs->sspsp, dai_base(dp) + SSPSP); sys_write32(regs->sspsp2, dai_base(dp) + SSPSP2); sys_write32(regs->ssioc, dai_base(dp) + SSIOC); sys_write32(regs->sscto, dai_base(dp) + SSTO); -#ifdef CONFIG_SOC_INTEL_ACE30_PTL - for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { - sys_write64(regs->ssmidytsa[idx], dai_base(dp) + SSMIDyTSA(idx)); - } - - for (uint32_t idx = 0; idx < I2SOPCMC; ++idx) { - sys_write64(regs->ssmodytsa[idx], dai_base(dp) + SSMODyTSA(idx)); - } -#else sys_write32(sstsa, dai_base(dp) + SSTSA); sys_write32(ssrsa, dai_base(dp) + SSRSA); -#endif LOG_INF(" sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x", ssc0, sscr1, regs->sscto, regs->sspsp); @@ -2106,23 +2165,21 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co if (ssc0 & SSCR0_EDSS) { ssp_plat_data->params.sample_valid_bits += 16; } -#ifdef CONFIG_SOC_INTEL_ACE30_PTL - ssp_plat_data->params.tx_slots = regs->ssmodytsa[dp->tdm_slot_group]; - ssp_plat_data->params.rx_slots = regs->ssmidytsa[dp->tdm_slot_group]; -#else + ssp_plat_data->params.tdm_slots = SSCR0_FRDC_GET(ssc0); ssp_plat_data->params.tx_slots = SSTSA_GET(sstsa); ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); -#endif ssp_plat_data->params.fsync_rate = cfg->rate; dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; } +#endif static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_config *cfg, const void *spec_config) { const struct dai_intel_ipc4_ssp_configuration_blob_ver_1_5 *blob15 = spec_config; + const struct dai_intel_ipc4_ssp_configuration_blob_ver_3_0 *blob30 = spec_config; const struct dai_intel_ipc4_ssp_configuration_blob *blob = spec_config; struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); int err; @@ -2143,13 +2200,23 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co if (err) { return err; } - dai_ssp_set_reg_config(dp, cfg, &blob15->i2s_ssp_config); + dai_ssp_set_reg_config(dp, cfg, (void *)&blob15->i2s_ssp_config); err = dai_ssp_set_clock_control_ver_1_5(dp, &blob15->i2s_mclk_control); if (err) { return err; } + } else if (blob30->version == SSP_BLOB_VER_3_0) { + err = dai_ssp_parse_aux_data(dp, spec_config); + if (err) { + return err; + } + dai_ssp_set_reg_config(dp, cfg, (void *)&blob30->i2s_ssp_config); + err = dai_ssp_set_clock_control_ver_1_5(dp, &blob30->i2s_mclk_control); + if (err) { + return err; + } } else { - dai_ssp_set_reg_config(dp, cfg, &blob->i2s_driver_config.i2s_config); + dai_ssp_set_reg_config(dp, cfg, (void *)&blob->i2s_driver_config.i2s_config); err = dai_ssp_set_clock_control_ver_1(dp, &blob->i2s_driver_config.mclk_config); if (err) { return err;