1 /* 2 * Copyright (c) 2022 Intel Corporation. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef __INTEL_DAI_DRIVER_SSP_H__ 8 #define __INTEL_DAI_DRIVER_SSP_H__ 9 10 #define SSP_IP_VER_1_0 0x10000 /* cAVS */ 11 #define SSP_IP_VER_1_5 0x10500 /* ACE15 */ 12 #define SSP_IP_VER_2_0 0x20000 /* ACE20 */ 13 #define SSP_IP_VER_3_0 0x30000 /* ACE30 */ 14 15 /* SSP IP version defined by CONFIG_SOC*/ 16 #if defined(CONFIG_SOC_SERIES_INTEL_ADSP_CAVS) 17 #define SSP_IP_VER SSP_IP_VER_1_0 18 #elif defined(CONFIG_SOC_INTEL_ACE15_MTPM) 19 #define SSP_IP_VER SSP_IP_VER_1_5 20 #elif defined(CONFIG_SOC_INTEL_ACE20_LNL) 21 #define SSP_IP_VER SSP_IP_VER_2_0 22 #elif defined(CONFIG_SOC_INTEL_ACE30) 23 #define SSP_IP_VER SSP_IP_VER_3_0 24 #else 25 #error "Unknown SSP IP" 26 #endif 27 28 #include <stdint.h> 29 #include <zephyr/drivers/dai.h> 30 #include "dai-params-intel-ipc3.h" 31 #include "dai-params-intel-ipc4.h" 32 33 #define DAI_INTEL_SSP_MASK(b_hi, b_lo) \ 34 (((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo)) 35 #define DAI_INTEL_SSP_SET_BIT(b, x) (((x) & 1) << (b)) 36 #define DAI_INTEL_SSP_SET_BITS(b_hi, b_lo, x) \ 37 (((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo)) 38 #define DAI_INTEL_SSP_GET_BIT(b, x) \ 39 (((x) & (1ULL << (b))) >> (b)) 40 #define DAI_INTEL_SSP_GET_BITS(b_hi, b_lo, x) \ 41 (((x) & MASK(b_hi, b_lo)) >> (b_lo)) 42 #define DAI_INTEL_SSP_IS_BIT_SET(reg, bit) (((reg >> bit) & (0x1)) != 0) 43 44 /* ssp_freq array constants */ 45 #define DAI_INTEL_SSP_NUM_FREQ 3 46 #define DAI_INTEL_SSP_MAX_FREQ_INDEX (DAI_INTEL_SSP_NUM_FREQ - 1) 47 #define DAI_INTEL_SSP_DEFAULT_IDX 1 48 49 /* the SSP port fifo depth */ 50 #define DAI_INTEL_SSP_FIFO_DEPTH 32 51 52 /* the watermark for the SSP fifo depth setting */ 53 #define DAI_INTEL_SSP_FIFO_WATERMARK 8 54 55 /* minimal SSP port delay in cycles */ 56 #define DAI_INTEL_SSP_PLATFORM_DELAY 1600 57 /* minimal SSP port delay in useconds */ 58 #define DAI_INTEL_SSP_PLATFORM_DELAY_US 42 59 #define DAI_INTEL_SSP_PLATFORM_DEFAULT_DELAY 12 60 #define DAI_INTEL_SSP_DEFAULT_TRY_TIMES 8 61 62 /** \brief Number of SSP MCLKs available */ 63 #define DAI_INTEL_SSP_NUM_MCLK 2 64 65 #define DAI_INTEL_SSP_CLOCK_XTAL_OSCILLATOR 0x0 66 #define DAI_INTEL_SSP_CLOCK_AUDIO_CARDINAL 0x1 67 #define DAI_INTEL_SSP_CLOCK_PLL_FIXED 0x2 68 69 #if defined(CONFIG_SOC_INTEL_ACE15_MTPM) || defined(CONFIG_SOC_SERIES_INTEL_ADSP_CAVS) 70 #include "ssp_regs_v1.h" 71 #elif defined(CONFIG_SOC_INTEL_ACE20_LNL) 72 #include "ssp_regs_v2.h" 73 #elif defined(CONFIG_SOC_INTEL_ACE30) 74 #include "ssp_regs_v3.h" 75 #else 76 #error "Missing ssp definitions" 77 #endif 78 79 #if SSP_IP_VER == SSP_IP_VER_1_0 80 /** \brief BCLKs can be driven by multiple sources - M/N or XTAL directly. 81 * Even in the case of M/N, the actual clock source can be XTAL, 82 * Audio cardinal clock (24.576) or 96 MHz PLL. 83 * The MN block is not really the source of clocks, but rather 84 * an intermediate component. 85 * Input for source is shared by all outputs coming from that source 86 * and once it's in use, it can be adjusted only with dividers. 87 * In order to change input, the source should not be in use, that's why 88 * it's necessary to keep track of BCLKs sources to know when it's safe 89 * to change shared input clock. 90 */ 91 enum bclk_source { 92 MN_BCLK_SOURCE_NONE = 0, /**< port is not using any clock */ 93 MN_BCLK_SOURCE_MN, /**< port is using clock driven by M/N */ 94 MN_BCLK_SOURCE_XTAL, /**< port is using XTAL directly */ 95 }; 96 #endif 97 98 struct dai_intel_ssp_mn { 99 uint32_t base; 100 /**< keep track of which MCLKs are in use to know when it's safe to 101 * change shared clock 102 */ 103 int mclk_sources_ref[DAI_INTEL_SSP_NUM_MCLK]; 104 int mclk_rate[DAI_INTEL_SSP_NUM_MCLK]; 105 int mclk_source_clock; 106 107 #if SSP_IP_VER == SSP_IP_VER_1_0 108 enum bclk_source bclk_sources[(CONFIG_DAI_INTEL_SSP_NUM_BASE + 109 CONFIG_DAI_INTEL_SSP_NUM_EXT)]; 110 int bclk_source_mn_clock; 111 #endif 112 113 struct k_spinlock lock; /**< lock mechanism */ 114 }; 115 116 struct dai_intel_ssp_freq_table { 117 uint32_t freq; 118 uint32_t ticks_per_msec; 119 }; 120 121 struct dai_intel_ssp_plat_fifo_data { 122 uint32_t offset; 123 uint32_t width; 124 uint32_t depth; 125 uint32_t watermark; 126 uint32_t handshake; 127 }; 128 129 struct dai_intel_ssp_plat_data { 130 uint32_t ssp_index; 131 int acquire_count; 132 bool is_initialized; 133 bool is_power_en; 134 uint32_t base; 135 uint32_t ip_base; 136 uint32_t shim_base; 137 #if SSP_IP_VER > SSP_IP_VER_1_5 138 uint32_t hdamlssp_base; 139 uint32_t i2svss_base; 140 uint32_t link_clock; 141 #endif 142 int irq; 143 const char *irq_name; 144 uint32_t flags; 145 struct dai_intel_ssp_plat_fifo_data fifo[2]; 146 struct dai_intel_ssp_mn *mn_inst; 147 struct dai_intel_ssp_freq_table *ftable; 148 uint32_t *fsources; 149 uint32_t clk_active; 150 struct dai_intel_ipc3_ssp_params params; 151 }; 152 153 struct dai_intel_ssp_pdata { 154 uint32_t sscr0; 155 uint32_t sscr1; 156 uint32_t psp; 157 struct dai_config config; 158 struct dai_properties props; 159 }; 160 161 struct dai_intel_ssp { 162 uint32_t dai_index; 163 uint32_t ssp_index; 164 uint32_t tdm_slot_group; 165 uint32_t state[2]; 166 struct k_spinlock lock; /**< locking mechanism */ 167 int sref; /**< simple ref counter, guarded by lock */ 168 struct dai_intel_ssp_plat_data *ssp_plat_data; 169 void *priv_data; 170 }; 171 172 #endif 173