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