intel_adsp: ace20_lnl: ssp: Program new HW registers

In LNL platform GPDMA and ALH is no longer used. SSP uses LINK HDA
as a DMA engine. Therefore new shim, new register definitions and new
programming flows were defined.

This patch implements new SSP programming requirements for LNL.
Since HDA is shared between Host and DSP, link_config field was added to
dai_config structure. This one is provided by Host in new IPC4 fields
during interface configuration.

Signed-off-by: Jaroslaw Stelter <Jaroslaw.Stelter@intel.com>
This commit is contained in:
Jaroslaw Stelter 2022-11-08 12:49:44 +01:00 committed by Anas Nashif
commit 1e5550d262
2 changed files with 63 additions and 3 deletions

View file

@ -29,6 +29,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
#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_shim2_base(dai) dai->plat_data.shim2_base
#define DAI_DIR_PLAYBACK 0
#define DAI_DIR_CAPTURE 1
@ -715,7 +716,7 @@ static void dai_ssp_pm_runtime_en_ssp_power(struct dai_intel_ssp *dp, uint32_t i
int ret;
LOG_INF("%s en_ssp_power index %d", __func__, 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),
dai_ip_base(dp) + I2SLCTL_OFFSET);
@ -723,7 +724,17 @@ static void dai_ssp_pm_runtime_en_ssp_power(struct dai_intel_ssp *dp, uint32_t i
ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET,
I2SLCTL_CPA(index), 0,
DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE);
#elif CONFIG_SOC_INTEL_ACE20_LNL
sys_write32(sys_read32(dai_shim2_base(dp) + I2SLCTL_OFFSET) |
I2SLCTL_SPA(index) | I2SLCTL_OFLEN,
dai_shim2_base(dp) + I2SLCTL_OFFSET);
/* Check if powered on. */
ret = dai_ssp_poll_for_register_delay(dai_shim2_base(dp) + I2SLCTL_OFFSET,
I2SLCTL_CPA(index), 0,
DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE);
#else
#error need to define SOC
#endif
if (ret) {
LOG_WRN("%s warning: timeout", __func__);
}
@ -741,7 +752,7 @@ static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t
int ret;
LOG_INF("%s index %d", __func__, 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)),
dai_ip_base(dp) + I2SLCTL_OFFSET);
@ -749,7 +760,17 @@ static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t
ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET,
I2SLCTL_CPA(index), I2SLCTL_CPA(index),
DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE);
#elif CONFIG_SOC_INTEL_ACE20_LNL
sys_write32(sys_read32(dai_shim2_base(dp) + I2SLCTL_OFFSET) & (~I2SLCTL_SPA(index)) &
(~I2SLCTL_OFLEN), dai_shim2_base(dp) + I2SLCTL_OFFSET);
/* Check if powered off. */
ret = dai_ssp_poll_for_register_delay(dai_shim2_base(dp) + I2SLCTL_OFFSET,
I2SLCTL_CPA(index), I2SLCTL_CPA(index),
DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE);
#else
#error need to define SOC
#endif
if (ret) {
LOG_WRN("%s warning: timeout", __func__);
}
@ -761,6 +782,28 @@ static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t
#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)
{
#ifdef CONFIG_SOC_INTEL_ACE20_LNL
uint16_t pcmsycm = cfg->link_config;
if (DAI_INTEL_SSP_IS_BIT_SET(pcmsycm, 15)) {
uint32_t reg_add = dai_ip_base(dp) + 0x1000 * 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;
/* Program HDA input stream parameters */
sys_write16((pcmsycm & 0xffff), reg_add);
}
#else
ARG_UNUSED(dp);
ARG_UNUSED(cfg);
ARG_UNUSED(index);
#endif /* CONFIG_SOC_INTEL_ACE20_LNL */
}
/* empty SSP transmit FIFO */
static void dai_ssp_empty_tx_fifo(struct dai_intel_ssp *dp)
{
@ -2041,8 +2084,10 @@ static int dai_ssp_config_set(const struct device *dev, const struct dai_config
struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data;
if (cfg->type == DAI_INTEL_SSP) {
dai_ssp_program_channel_map(dp, cfg, dp->index);
return dai_ssp_set_config_tplg(dp, cfg, bespoke_cfg);
} else {
dai_ssp_program_channel_map(dp, cfg, dp->index);
return dai_ssp_set_config_blob(dp, cfg, bespoke_cfg);
}
}
@ -2197,6 +2242,8 @@ static const char irq_name_level5_z[] = "level5";
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(CONFIG_SOC_INTEL_ACE20_LNL, \
(.shim2_base = DT_INST_PROP_BY_IDX(n, shim2, 0),))\
.irq = n, \
.irq_name = irq_name_level5_z, \
.fifo[DAI_DIR_PLAYBACK].offset = \