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:
parent
c61e06739c
commit
8c997b35ab
2 changed files with 136 additions and 39 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue