blob: 4b76e8467b871dd1a35b01cc30c0f47cc6539493 [file] [log] [blame]
/*
* Copyright (c) 2022 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __INTEL_DAI_DRIVER_SSP_H__
#define __INTEL_DAI_DRIVER_SSP_H__
#include <stdint.h>
#include <zephyr/drivers/dai.h>
#include "dai-params-intel-ipc3.h"
#include "dai-params-intel-ipc4.h"
#define DAI_INTEL_SSP_MASK(b_hi, b_lo) \
(((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo))
#define DAI_INTEL_SSP_SET_BIT(b, x) (((x) & 1) << (b))
#define DAI_INTEL_SSP_SET_BITS(b_hi, b_lo, x) \
(((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo))
#define DAI_INTEL_SSP_GET_BIT(b, x) \
(((x) & (1ULL << (b))) >> (b))
#define DAI_INTEL_SSP_GET_BITS(b_hi, b_lo, x) \
(((x) & MASK(b_hi, b_lo)) >> (b_lo))
/* ssp_freq array constants */
#define DAI_INTEL_SSP_NUM_FREQ 3
#define DAI_INTEL_SSP_MAX_FREQ_INDEX (DAI_INTEL_SSP_NUM_FREQ - 1)
#define DAI_INTEL_SSP_DEFAULT_IDX 1
/* the SSP port fifo depth */
#define DAI_INTEL_SSP_FIFO_DEPTH 16
/* the watermark for the SSP fifo depth setting */
#define DAI_INTEL_SSP_FIFO_WATERMARK 8
/* minimal SSP port delay in cycles */
#define DAI_INTEL_SSP_PLATFORM_DELAY 1600
/* minimal SSP port delay in useconds */
#define DAI_INTEL_SSP_PLATFORM_DELAY_US 42
#define DAI_INTEL_SSP_PLATFORM_DEFAULT_DELAY 12
#define DAI_INTEL_SSP_DEFAULT_TRY_TIMES 8
#if CONFIG_SOC_SERIES_INTEL_CAVS_V15
/** \brief Number of 'base' SSP ports available */
#define DAI_INTEL_SSP_NUM_BASE 4
/** \brief Number of 'extended' SSP ports available */
#define DAI_INTEL_SSP_NUM_EXT 2
#else
/** \brief Number of 'base' SSP ports available */
#define DAI_INTEL_SSP_NUM_BASE 6
/** \brief Number of 'extended' SSP ports available */
#define DAI_INTEL_SSP_NUM_EXT 0
#endif
/** \brief Number of SSP MCLKs available */
#define DAI_INTEL_SSP_NUM_MCLK 2
#define DAI_INTEL_SSP_CLOCK_XTAL_OSCILLATOR 0x0
#define DAI_INTEL_SSP_CLOCK_AUDIO_CARDINAL 0x1
#define DAI_INTEL_SSP_CLOCK_PLL_FIXED 0x2
/* SSP register offsets */
#define SSCR0 0x00
#define SSCR1 0x04
#define SSSR 0x08
#define SSITR 0x0C
#define SSDR 0x10
#define SSTO 0x28
#define SSPSP 0x2C
#define SSTSA 0x30
#define SSRSA 0x34
#define SSTSS 0x38
#define SSCR2 0x40
/* SSCR0 bits */
#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1)
#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1)
#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4)
#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0)
#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1)
#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2)
#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3)
#define SSCR0_ECS BIT(6)
#define SSCR0_SSE BIT(7)
#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8)
#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x)
#define SSCR0_EDSS BIT(20)
#define SSCR0_NCS BIT(21)
#define SSCR0_RIM BIT(22)
#define SSCR0_TIM BIT(23)
#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1)
#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1)
#define SSCR0_ACS BIT(30)
#define SSCR0_MOD BIT(31)
/* SSCR1 bits */
#define SSCR1_RIE BIT(0)
#define SSCR1_TIE BIT(1)
#define SSCR1_LBM BIT(2)
#define SSCR1_SPO BIT(3)
#define SSCR1_SPH BIT(4)
#define SSCR1_MWDS BIT(5)
#define SSCR1_TFT_MASK DAI_INTEL_SSP_MASK(9, 6)
#define SSCR1_TFT(x) DAI_INTEL_SSP_SET_BITS(9, 6, (x) - 1)
#define SSCR1_RFT_MASK DAI_INTEL_SSP_MASK(13, 10)
#define SSCR1_RFT(x) DAI_INTEL_SSP_SET_BITS(13, 10, (x) - 1)
#define SSCR1_EFWR BIT(14)
#define SSCR1_STRF BIT(15)
#define SSCR1_IFS BIT(16)
#define SSCR1_PINTE BIT(18)
#define SSCR1_TINTE BIT(19)
#define SSCR1_RSRE BIT(20)
#define SSCR1_TSRE BIT(21)
#define SSCR1_TRAIL BIT(22)
#define SSCR1_RWOT BIT(23)
#define SSCR1_SFRMDIR BIT(24)
#define SSCR1_SCLKDIR BIT(25)
#define SSCR1_ECRB BIT(26)
#define SSCR1_ECRA BIT(27)
#define SSCR1_SCFR BIT(28)
#define SSCR1_EBCEI BIT(29)
#define SSCR1_TTE BIT(30)
#define SSCR1_TTELP BIT(31)
#define SSCR2_TURM1 BIT(1)
#define SSCR2_PSPSRWFDFD BIT(3)
#define SSCR2_PSPSTWFDFD BIT(4)
#define SSCR2_SDFD BIT(14)
#define SSCR2_SDPM BIT(16)
#define SSCR2_LJDFD BIT(17)
#define SSCR2_MMRATF BIT(18)
#define SSCR2_SMTATF BIT(19)
#define SSCR2_SFRMEN BIT(20)
#define SSCR2_ACIOLBS BIT(21)
/* SSR bits */
#define SSSR_TNF BIT(2)
#define SSSR_RNE BIT(3)
#define SSSR_BSY BIT(4)
#define SSSR_TFS BIT(5)
#define SSSR_RFS BIT(6)
#define SSSR_ROR BIT(7)
#define SSSR_TUR BIT(21)
/* SSPSP bits */
#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x)
#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x)
#define SSPSP_ETDS BIT(3)
#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x)
#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x)
#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x)
#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x)
#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x)
#define SSPSP_DMYSTOP_BITS 2
#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0)
#define SSPSP_FSRT BIT(25)
#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x)
#define SSPSP2 0x44
#define SSPSP2_FEP_MASK 0xff
#define SSCR3 0x48
#define SSIOC 0x4C
#define SSP_REG_MAX SSIOC
/* SSTSA bits */
#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x)
#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0))
#define SSTSA_TXEN BIT(8)
/* SSRSA bits */
#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x)
#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0))
#define SSRSA_RXEN BIT(8)
/* SSCR3 bits */
#define SSCR3_FRM_MST_EN BIT(0)
#define SSCR3_I2S_MODE_EN BIT(1)
#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x)
#define SSCR3_I2S_TX_SS_FIX_EN BIT(3)
#define SSCR3_I2S_RX_SS_FIX_EN BIT(4)
#define SSCR3_I2S_TX_EN BIT(9)
#define SSCR3_I2S_RX_EN BIT(10)
#define SSCR3_CLK_EDGE_SEL BIT(12)
#define SSCR3_STRETCH_TX BIT(14)
#define SSCR3_STRETCH_RX BIT(15)
#define SSCR3_MST_CLK_EN BIT(16)
#define SSCR3_SYN_FIX_EN BIT(17)
/* SSCR4 bits */
#define SSCR4_TOT_FRM_PRD(x) ((x) << 7)
/* SSCR5 bits */
#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1)
#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x)
/* SFIFOTT bits */
#define SFIFOTT_TX(x) ((x) - 1)
#define SFIFOTT_RX(x) (((x) - 1) << 16)
/* SFIFOL bits */
#define SFIFOL_TFL(x) ((x) & 0xFFFF)
#define SFIFOL_RFL(x) ((x) >> 16)
#define SSTSA_TSEN BIT(8)
#define SSRSA_RSEN BIT(8)
#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0)
#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8)
#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0))
#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0))
#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1)
#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1)
#define SSIOC_TXDPDEB BIT(1)
#define SSIOC_SFCR BIT(4)
#define SSIOC_SCOE BIT(5)
/* For 8000 Hz rate one sample is transmitted within 125us */
#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125
/* SSP flush retry counts maximum */
#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16
#define SSP_CLK_MCLK_ES_REQ BIT(0)
#define SSP_CLK_MCLK_ACTIVE BIT(1)
#define SSP_CLK_BCLK_ES_REQ BIT(2)
#define SSP_CLK_BCLK_ACTIVE BIT(3)
#define I2SLCTL_OFFSET 0x04
#define I2SLCTL_SPA(x) BIT(0 + x)
#define I2SLCTL_CPA(x) BIT(8 + x)
#define SHIM_CLKCTL 0x78
#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x)
#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x)
/** \brief Offset of MCLK Divider Control Register. */
#define MN_MDIVCTRL 0x0
/** \brief Enables the output of MCLK Divider. */
#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x)
/** \brief Offset of MCLK Divider x Ratio Register. */
#define MN_MDIVR(x) (0x80 + (x) * 0x4)
/** \brief Bits for setting MCLK source clock. */
#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x)
/** \brief Offset of BCLK x M/N Divider M Value Register. */
#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0)
/** \brief Offset of BCLK x M/N Divider N Value Register. */
#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4)
/** \brief Bits for setting M/N source clock. */
#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x)
/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */
#define MN_SOURCE_CLKS_MASK 0x3
#if CONFIG_INTEL_MN
/** \brief BCLKs can be driven by multiple sources - M/N or XTAL directly.
* Even in the case of M/N, the actual clock source can be XTAL,
* Audio cardinal clock (24.576) or 96 MHz PLL.
* The MN block is not really the source of clocks, but rather
* an intermediate component.
* Input for source is shared by all outputs coming from that source
* and once it's in use, it can be adjusted only with dividers.
* In order to change input, the source should not be in use, that's why
* it's necessary to keep track of BCLKs sources to know when it's safe
* to change shared input clock.
*/
enum bclk_source {
MN_BCLK_SOURCE_NONE = 0, /**< port is not using any clock */
MN_BCLK_SOURCE_MN, /**< port is using clock driven by M/N */
MN_BCLK_SOURCE_XTAL, /**< port is using XTAL directly */
};
#endif
struct dai_intel_ssp_mn {
uint32_t base;
/**< keep track of which MCLKs are in use to know when it's safe to
* change shared clock
*/
int mclk_sources_ref[DAI_INTEL_SSP_NUM_MCLK];
int mclk_rate[DAI_INTEL_SSP_NUM_MCLK];
int mclk_source_clock;
#if CONFIG_INTEL_MN
enum bclk_source bclk_sources[(DAI_INTEL_SSP_NUM_BASE + DAI_INTEL_SSP_NUM_EXT)];
int bclk_source_mn_clock;
#endif
struct k_spinlock lock; /**< lock mechanism */
};
struct dai_intel_ssp_freq_table {
uint32_t freq;
uint32_t ticks_per_msec;
};
struct dai_intel_ssp_plat_fifo_data {
uint32_t offset;
uint32_t width;
uint32_t depth;
uint32_t watermark;
uint32_t handshake;
};
struct dai_intel_ssp_plat_data {
uint32_t base;
uint32_t ip_base;
uint32_t shim_base;
int irq;
const char *irq_name;
uint32_t flags;
struct dai_intel_ssp_plat_fifo_data fifo[2];
struct dai_intel_ssp_mn *mn_inst;
struct dai_intel_ssp_freq_table *ftable;
uint32_t *fsources;
};
struct dai_intel_ssp_pdata {
uint32_t sscr0;
uint32_t sscr1;
uint32_t psp;
uint32_t state[2];
uint32_t clk_active;
struct dai_config config;
struct dai_properties props;
struct dai_intel_ipc3_ssp_params params;
};
struct dai_intel_ssp {
uint32_t index; /**< index */
struct k_spinlock lock; /**< locking mechanism */
int sref; /**< simple ref counter, guarded by lock */
struct dai_intel_ssp_plat_data plat_data;
void *priv_data;
};
#endif