driver: ssp: add support for blob30 on PTL

Adding support for SSP blob handling in version 3_0 for PTL.

Signed-off-by: Damian Nikodem <damian.nikodem@intel.com>
This commit is contained in:
Damian Nikodem 2024-08-30 07:12:47 +02:00 committed by Carles Cufí
parent c61e06739c
commit 8c997b35ab
2 changed files with 136 additions and 39 deletions

View file

@ -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

View file

@ -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)) {
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 +
@ -890,9 +896,14 @@ static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp,
/* Program HDA output stream parameters */
sys_write16((pcmsycm & 0xffff), reg_add);
} else {
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);
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 *)blob + 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;