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:
parent
5bffe933e6
commit
1e5550d262
2 changed files with 63 additions and 3 deletions
|
@ -29,6 +29,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
|
||||||
#define dai_base(dai) dai->plat_data.base
|
#define dai_base(dai) dai->plat_data.base
|
||||||
#define dai_ip_base(dai) dai->plat_data.ip_base
|
#define dai_ip_base(dai) dai->plat_data.ip_base
|
||||||
#define dai_shim_base(dai) dai->plat_data.shim_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_PLAYBACK 0
|
||||||
#define DAI_DIR_CAPTURE 1
|
#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;
|
int ret;
|
||||||
|
|
||||||
LOG_INF("%s en_ssp_power index %d", __func__, index);
|
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),
|
sys_write32(sys_read32(dai_ip_base(dp) + I2SLCTL_OFFSET) | I2SLCTL_SPA(index),
|
||||||
dai_ip_base(dp) + I2SLCTL_OFFSET);
|
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,
|
ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET,
|
||||||
I2SLCTL_CPA(index), 0,
|
I2SLCTL_CPA(index), 0,
|
||||||
DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE);
|
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) {
|
if (ret) {
|
||||||
LOG_WRN("%s warning: timeout", __func__);
|
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;
|
int ret;
|
||||||
|
|
||||||
LOG_INF("%s index %d", __func__, index);
|
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)),
|
sys_write32(sys_read32(dai_ip_base(dp) + I2SLCTL_OFFSET) & (~I2SLCTL_SPA(index)),
|
||||||
dai_ip_base(dp) + I2SLCTL_OFFSET);
|
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,
|
ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET,
|
||||||
I2SLCTL_CPA(index), I2SLCTL_CPA(index),
|
I2SLCTL_CPA(index), I2SLCTL_CPA(index),
|
||||||
DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE);
|
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) {
|
if (ret) {
|
||||||
LOG_WRN("%s warning: timeout", __func__);
|
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 */
|
#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 */
|
/* empty SSP transmit FIFO */
|
||||||
static void dai_ssp_empty_tx_fifo(struct dai_intel_ssp *dp)
|
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;
|
struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data;
|
||||||
|
|
||||||
if (cfg->type == DAI_INTEL_SSP) {
|
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);
|
return dai_ssp_set_config_tplg(dp, cfg, bespoke_cfg);
|
||||||
} else {
|
} else {
|
||||||
|
dai_ssp_program_channel_map(dp, cfg, dp->index);
|
||||||
return dai_ssp_set_config_blob(dp, cfg, bespoke_cfg);
|
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)), \
|
IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(sspbase)), \
|
||||||
(.ip_base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(sspbase), 0),)) \
|
(.ip_base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(sspbase), 0),)) \
|
||||||
.shim_base = DT_REG_ADDR_BY_IDX(DT_NODELABEL(shim), 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 = n, \
|
||||||
.irq_name = irq_name_level5_z, \
|
.irq_name = irq_name_level5_z, \
|
||||||
.fifo[DAI_DIR_PLAYBACK].offset = \
|
.fifo[DAI_DIR_PLAYBACK].offset = \
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
(((x) & (1ULL << (b))) >> (b))
|
(((x) & (1ULL << (b))) >> (b))
|
||||||
#define DAI_INTEL_SSP_GET_BITS(b_hi, b_lo, x) \
|
#define DAI_INTEL_SSP_GET_BITS(b_hi, b_lo, x) \
|
||||||
(((x) & MASK(b_hi, b_lo)) >> (b_lo))
|
(((x) & MASK(b_hi, b_lo)) >> (b_lo))
|
||||||
|
#define DAI_INTEL_SSP_IS_BIT_SET(reg, bit) (((reg >> bit) & (0x1)) != 0)
|
||||||
|
|
||||||
/* ssp_freq array constants */
|
/* ssp_freq array constants */
|
||||||
#define DAI_INTEL_SSP_NUM_FREQ 3
|
#define DAI_INTEL_SSP_NUM_FREQ 3
|
||||||
|
@ -216,9 +217,18 @@
|
||||||
#define SSP_CLK_BCLK_ACTIVE BIT(3)
|
#define SSP_CLK_BCLK_ACTIVE BIT(3)
|
||||||
|
|
||||||
#define I2SLCTL_OFFSET 0x04
|
#define I2SLCTL_OFFSET 0x04
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOC_INTEL_ACE15_MTPM
|
||||||
#define I2SLCTL_SPA(x) BIT(0 + x)
|
#define I2SLCTL_SPA(x) BIT(0 + x)
|
||||||
#define I2SLCTL_CPA(x) BIT(8 + x)
|
#define I2SLCTL_CPA(x) BIT(8 + x)
|
||||||
#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x)
|
#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x)
|
||||||
|
#else /* CONFIG_SOC_INTEL_ACE20_LNL */
|
||||||
|
#define I2SLCTL_OFLEN BIT(4)
|
||||||
|
#define I2SLCTL_SPA(x) BIT(16 + x)
|
||||||
|
#define I2SLCTL_CPA(x) BIT(23 + x)
|
||||||
|
#define PCMS0CM_OFFSET 0x16
|
||||||
|
#define PCMS1CM_OFFSET 0x1A
|
||||||
|
#endif /* CONFIG_SOC_INTEL_ACE15_MTPM */
|
||||||
|
|
||||||
#define SHIM_CLKCTL 0x78
|
#define SHIM_CLKCTL 0x78
|
||||||
#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x)
|
#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x)
|
||||||
|
@ -307,6 +317,9 @@ struct dai_intel_ssp_plat_data {
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
uint32_t ip_base;
|
uint32_t ip_base;
|
||||||
uint32_t shim_base;
|
uint32_t shim_base;
|
||||||
|
#ifdef CONFIG_SOC_INTEL_ACE20_LNL
|
||||||
|
uint32_t shim2_base;
|
||||||
|
#endif
|
||||||
int irq;
|
int irq;
|
||||||
const char *irq_name;
|
const char *irq_name;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue