1 | /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ |
2 | /* Copyright(c) 2015-17 Intel Corporation. */ |
3 | #include <sound/soc.h> |
4 | |
5 | #ifndef __SDW_CADENCE_H |
6 | #define __SDW_CADENCE_H |
7 | |
8 | #define SDW_CADENCE_GSYNC_KHZ 4 /* 4 kHz */ |
9 | #define SDW_CADENCE_GSYNC_HZ (SDW_CADENCE_GSYNC_KHZ * 1000) |
10 | |
11 | /* |
12 | * The Cadence IP supports up to 32 entries in the FIFO, though implementations |
13 | * can configure the IP to have a smaller FIFO. |
14 | */ |
15 | #define CDNS_MCP_IP_MAX_CMD_LEN 32 |
16 | |
17 | #define SDW_CADENCE_MCP_IP_OFFSET 0x4000 |
18 | |
19 | /** |
20 | * struct sdw_cdns_pdi: PDI (Physical Data Interface) instance |
21 | * |
22 | * @num: pdi number |
23 | * @intel_alh_id: link identifier |
24 | * @l_ch_num: low channel for PDI |
25 | * @h_ch_num: high channel for PDI |
26 | * @ch_count: total channel count for PDI |
27 | * @dir: data direction |
28 | * @type: stream type, (only PCM supported) |
29 | */ |
30 | struct sdw_cdns_pdi { |
31 | int num; |
32 | int intel_alh_id; |
33 | int l_ch_num; |
34 | int h_ch_num; |
35 | int ch_count; |
36 | enum sdw_data_direction dir; |
37 | enum sdw_stream_type type; |
38 | }; |
39 | |
40 | /** |
41 | * struct sdw_cdns_streams: Cadence stream data structure |
42 | * |
43 | * @num_bd: number of bidirectional streams |
44 | * @num_in: number of input streams |
45 | * @num_out: number of output streams |
46 | * @num_ch_bd: number of bidirectional stream channels |
47 | * @num_ch_bd: number of input stream channels |
48 | * @num_ch_bd: number of output stream channels |
49 | * @num_pdi: total number of PDIs |
50 | * @bd: bidirectional streams |
51 | * @in: input streams |
52 | * @out: output streams |
53 | */ |
54 | struct sdw_cdns_streams { |
55 | unsigned int num_bd; |
56 | unsigned int num_in; |
57 | unsigned int num_out; |
58 | unsigned int num_ch_bd; |
59 | unsigned int num_ch_in; |
60 | unsigned int num_ch_out; |
61 | unsigned int num_pdi; |
62 | struct sdw_cdns_pdi *bd; |
63 | struct sdw_cdns_pdi *in; |
64 | struct sdw_cdns_pdi *out; |
65 | }; |
66 | |
67 | /** |
68 | * struct sdw_cdns_stream_config: stream configuration |
69 | * |
70 | * @pcm_bd: number of bidirectional PCM streams supported |
71 | * @pcm_in: number of input PCM streams supported |
72 | * @pcm_out: number of output PCM streams supported |
73 | */ |
74 | struct sdw_cdns_stream_config { |
75 | unsigned int pcm_bd; |
76 | unsigned int pcm_in; |
77 | unsigned int pcm_out; |
78 | }; |
79 | |
80 | /** |
81 | * struct sdw_cdns_dai_runtime: Cadence DAI runtime data |
82 | * |
83 | * @name: SoundWire stream name |
84 | * @stream: stream runtime |
85 | * @pdi: PDI used for this dai |
86 | * @bus: Bus handle |
87 | * @stream_type: Stream type |
88 | * @link_id: Master link id |
89 | * @suspended: status set when suspended, to be used in .prepare |
90 | * @paused: status set in .trigger, to be used in suspend |
91 | * @direction: stream direction |
92 | */ |
93 | struct sdw_cdns_dai_runtime { |
94 | char *name; |
95 | struct sdw_stream_runtime *stream; |
96 | struct sdw_cdns_pdi *pdi; |
97 | struct sdw_bus *bus; |
98 | enum sdw_stream_type stream_type; |
99 | int link_id; |
100 | bool suspended; |
101 | bool paused; |
102 | int direction; |
103 | }; |
104 | |
105 | /** |
106 | * struct sdw_cdns - Cadence driver context |
107 | * @dev: Linux device |
108 | * @bus: Bus handle |
109 | * @instance: instance number |
110 | * @ip_offset: version-dependent offset to access IP_MCP registers and fields |
111 | * @response_buf: SoundWire response buffer |
112 | * @tx_complete: Tx completion |
113 | * @ports: Data ports |
114 | * @num_ports: Total number of data ports |
115 | * @pcm: PCM streams |
116 | * @registers: Cadence registers |
117 | * @link_up: Link status |
118 | * @msg_count: Messages sent on bus |
119 | * @dai_runtime_array: runtime context for each allocated DAI. |
120 | */ |
121 | struct sdw_cdns { |
122 | struct device *dev; |
123 | struct sdw_bus bus; |
124 | unsigned int instance; |
125 | |
126 | u32 ip_offset; |
127 | |
128 | /* |
129 | * The datasheet says the RX FIFO AVAIL can be 2 entries more |
130 | * than the FIFO capacity, so allow for this. |
131 | */ |
132 | u32 response_buf[CDNS_MCP_IP_MAX_CMD_LEN + 2]; |
133 | |
134 | struct completion tx_complete; |
135 | |
136 | struct sdw_cdns_port *ports; |
137 | int num_ports; |
138 | |
139 | struct sdw_cdns_streams pcm; |
140 | |
141 | int pdi_loopback_source; |
142 | int pdi_loopback_target; |
143 | |
144 | void __iomem *registers; |
145 | |
146 | bool link_up; |
147 | unsigned int msg_count; |
148 | bool interrupt_enabled; |
149 | |
150 | struct work_struct work; |
151 | |
152 | struct list_head list; |
153 | |
154 | struct sdw_cdns_dai_runtime **dai_runtime_array; |
155 | }; |
156 | |
157 | #define bus_to_cdns(_bus) container_of(_bus, struct sdw_cdns, bus) |
158 | |
159 | /* Exported symbols */ |
160 | |
161 | int sdw_cdns_probe(struct sdw_cdns *cdns); |
162 | |
163 | irqreturn_t sdw_cdns_irq(int irq, void *dev_id); |
164 | irqreturn_t sdw_cdns_thread(int irq, void *dev_id); |
165 | |
166 | int sdw_cdns_init(struct sdw_cdns *cdns); |
167 | int sdw_cdns_pdi_init(struct sdw_cdns *cdns, |
168 | struct sdw_cdns_stream_config config); |
169 | int sdw_cdns_exit_reset(struct sdw_cdns *cdns); |
170 | int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state); |
171 | |
172 | bool sdw_cdns_is_clock_stop(struct sdw_cdns *cdns); |
173 | int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake); |
174 | int sdw_cdns_clock_restart(struct sdw_cdns *cdns, bool bus_reset); |
175 | |
176 | #ifdef CONFIG_DEBUG_FS |
177 | void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root); |
178 | #endif |
179 | |
180 | struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns, |
181 | struct sdw_cdns_streams *stream, |
182 | u32 ch, u32 dir, int dai_id); |
183 | void sdw_cdns_config_stream(struct sdw_cdns *cdns, |
184 | u32 ch, u32 dir, struct sdw_cdns_pdi *pdi); |
185 | |
186 | enum sdw_command_response |
187 | cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg); |
188 | |
189 | enum sdw_command_response |
190 | cdns_xfer_msg_defer(struct sdw_bus *bus); |
191 | |
192 | u32 cdns_read_ping_status(struct sdw_bus *bus); |
193 | |
194 | int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params); |
195 | |
196 | int cdns_set_sdw_stream(struct snd_soc_dai *dai, |
197 | void *stream, int direction); |
198 | |
199 | void sdw_cdns_check_self_clearing_bits(struct sdw_cdns *cdns, const char *string, |
200 | bool initial_delay, int reset_iterations); |
201 | |
202 | void sdw_cdns_config_update(struct sdw_cdns *cdns); |
203 | int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns); |
204 | |
205 | #endif /* __SDW_CADENCE_H */ |
206 | |