1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // |
3 | // rt1318-sdw.c -- rt1318 SDCA ALSA SoC amplifier audio driver |
4 | // |
5 | // Copyright(c) 2022 Realtek Semiconductor Corp. |
6 | // |
7 | // |
8 | #include <linux/delay.h> |
9 | #include <linux/device.h> |
10 | #include <linux/pm_runtime.h> |
11 | #include <linux/mod_devicetable.h> |
12 | #include <linux/module.h> |
13 | #include <linux/regmap.h> |
14 | #include <linux/dmi.h> |
15 | #include <linux/firmware.h> |
16 | #include <sound/core.h> |
17 | #include <sound/pcm.h> |
18 | #include <sound/pcm_params.h> |
19 | #include <sound/soc-dapm.h> |
20 | #include <sound/initval.h> |
21 | #include "rt1318-sdw.h" |
22 | |
23 | static const struct reg_sequence rt1318_blind_write[] = { |
24 | { 0xc001, 0x43 }, |
25 | { 0xc003, 0xa2 }, |
26 | { 0xc004, 0x44 }, |
27 | { 0xc005, 0x44 }, |
28 | { 0xc006, 0x33 }, |
29 | { 0xc007, 0x64 }, |
30 | { 0xc320, 0x20 }, |
31 | { 0xf203, 0x18 }, |
32 | { 0xf211, 0x00 }, |
33 | { 0xf212, 0x26 }, |
34 | { 0xf20d, 0x17 }, |
35 | { 0xf214, 0x06 }, |
36 | { 0xf20e, 0x00 }, |
37 | { 0xf223, 0x7f }, |
38 | { 0xf224, 0xdb }, |
39 | { 0xf225, 0xee }, |
40 | { 0xf226, 0x3f }, |
41 | { 0xf227, 0x0f }, |
42 | { 0xf21a, 0x78 }, |
43 | { 0xf242, 0x3c }, |
44 | { 0xc321, 0x0b }, |
45 | { 0xc200, 0xd8 }, |
46 | { 0xc201, 0x27 }, |
47 | { 0xc202, 0x0f }, |
48 | { 0xf800, 0x20 }, |
49 | { 0xdf00, 0x10 }, |
50 | { 0xdf5f, 0x01 }, |
51 | { 0xdf60, 0xa7 }, |
52 | { 0xc400, 0x0e }, |
53 | { 0xc401, 0x43 }, |
54 | { 0xc402, 0xe0 }, |
55 | { 0xc403, 0x00 }, |
56 | { 0xc404, 0x4c }, |
57 | { 0xc407, 0x02 }, |
58 | { 0xc408, 0x3f }, |
59 | { 0xc300, 0x01 }, |
60 | { 0xc206, 0x78 }, |
61 | { 0xc203, 0x84 }, |
62 | { 0xc120, 0xc0 }, |
63 | { 0xc121, 0x03 }, |
64 | { 0xe000, 0x88 }, |
65 | { 0xc321, 0x09 }, |
66 | { 0xc322, 0x01 }, |
67 | { 0xe706, 0x0f }, |
68 | { 0xe707, 0x30 }, |
69 | { 0xe806, 0x0f }, |
70 | { 0xe807, 0x30 }, |
71 | { 0xed00, 0xb0 }, |
72 | { 0xce04, 0x02 }, |
73 | { 0xce05, 0x63 }, |
74 | { 0xce06, 0x68 }, |
75 | { 0xce07, 0x07 }, |
76 | { 0xcf04, 0x02 }, |
77 | { 0xcf05, 0x63 }, |
78 | { 0xcf06, 0x68 }, |
79 | { 0xcf07, 0x07 }, |
80 | { 0xce60, 0xe3 }, |
81 | { 0xc130, 0x51 }, |
82 | { 0xf102, 0x00 }, |
83 | { 0xf103, 0x00 }, |
84 | { 0xf104, 0xf5 }, |
85 | { 0xf105, 0x06 }, |
86 | { 0xf109, 0x9b }, |
87 | { 0xf10a, 0x0b }, |
88 | { 0xf10b, 0x4c }, |
89 | { 0xf10b, 0x5c }, |
90 | { 0xf102, 0x00 }, |
91 | { 0xf103, 0x00 }, |
92 | { 0xf104, 0xf5 }, |
93 | { 0xf105, 0x0b }, |
94 | { 0xf109, 0x03 }, |
95 | { 0xf10a, 0x0b }, |
96 | { 0xf10b, 0x4c }, |
97 | { 0xf10b, 0x5c }, |
98 | { 0xf102, 0x00 }, |
99 | { 0xf103, 0x00 }, |
100 | { 0xf104, 0xf5 }, |
101 | { 0xf105, 0x0c }, |
102 | { 0xf109, 0x7f }, |
103 | { 0xf10a, 0x0b }, |
104 | { 0xf10b, 0x4c }, |
105 | { 0xf10b, 0x5c }, |
106 | |
107 | { 0xe604, 0x00 }, |
108 | { 0xdb00, 0x0c }, |
109 | { 0xdd00, 0x0c }, |
110 | { 0xdc19, 0x00 }, |
111 | { 0xdc1a, 0xff }, |
112 | { 0xdc1b, 0xff }, |
113 | { 0xdc1c, 0xff }, |
114 | { 0xdc1d, 0x00 }, |
115 | { 0xdc1e, 0x00 }, |
116 | { 0xdc1f, 0x00 }, |
117 | { 0xdc20, 0xff }, |
118 | { 0xde19, 0x00 }, |
119 | { 0xde1a, 0xff }, |
120 | { 0xde1b, 0xff }, |
121 | { 0xde1c, 0xff }, |
122 | { 0xde1d, 0x00 }, |
123 | { 0xde1e, 0x00 }, |
124 | { 0xde1f, 0x00 }, |
125 | { 0xde20, 0xff }, |
126 | { 0xdb32, 0x00 }, |
127 | { 0xdd32, 0x00 }, |
128 | { 0xdb33, 0x0a }, |
129 | { 0xdd33, 0x0a }, |
130 | { 0xdb34, 0x1a }, |
131 | { 0xdd34, 0x1a }, |
132 | { 0xdb17, 0xef }, |
133 | { 0xdd17, 0xef }, |
134 | { 0xdba7, 0x00 }, |
135 | { 0xdba8, 0x64 }, |
136 | { 0xdda7, 0x00 }, |
137 | { 0xdda8, 0x64 }, |
138 | { 0xdb19, 0x40 }, |
139 | { 0xdd19, 0x40 }, |
140 | { 0xdb00, 0x4c }, |
141 | { 0xdb01, 0x79 }, |
142 | { 0xdd01, 0x79 }, |
143 | { 0xdb04, 0x05 }, |
144 | { 0xdb05, 0x03 }, |
145 | { 0xdd04, 0x05 }, |
146 | { 0xdd05, 0x03 }, |
147 | { 0xdbbb, 0x09 }, |
148 | { 0xdbbc, 0x30 }, |
149 | { 0xdbbd, 0xf0 }, |
150 | { 0xdbbe, 0xf1 }, |
151 | { 0xddbb, 0x09 }, |
152 | { 0xddbc, 0x30 }, |
153 | { 0xddbd, 0xf0 }, |
154 | { 0xddbe, 0xf1 }, |
155 | { 0xdb01, 0x79 }, |
156 | { 0xdd01, 0x79 }, |
157 | { 0xdc52, 0xef }, |
158 | { 0xde52, 0xef }, |
159 | { 0x2f55, 0x22 }, |
160 | }; |
161 | |
162 | static const struct reg_default rt1318_reg_defaults[] = { |
163 | { 0x3000, 0x00 }, |
164 | { 0x3004, 0x01 }, |
165 | { 0x3005, 0x23 }, |
166 | { 0x3202, 0x00 }, |
167 | { 0x3203, 0x01 }, |
168 | { 0x3206, 0x00 }, |
169 | { 0xc000, 0x00 }, |
170 | { 0xc001, 0x43 }, |
171 | { 0xc003, 0x22 }, |
172 | { 0xc004, 0x44 }, |
173 | { 0xc005, 0x44 }, |
174 | { 0xc006, 0x33 }, |
175 | { 0xc007, 0x64 }, |
176 | { 0xc008, 0x05 }, |
177 | { 0xc00a, 0xfc }, |
178 | { 0xc00b, 0x0f }, |
179 | { 0xc00c, 0x0e }, |
180 | { 0xc00d, 0xef }, |
181 | { 0xc00e, 0xe5 }, |
182 | { 0xc00f, 0xff }, |
183 | { 0xc120, 0xc0 }, |
184 | { 0xc121, 0x00 }, |
185 | { 0xc122, 0x00 }, |
186 | { 0xc123, 0x14 }, |
187 | { 0xc125, 0x00 }, |
188 | { 0xc200, 0x00 }, |
189 | { 0xc201, 0x00 }, |
190 | { 0xc202, 0x00 }, |
191 | { 0xc203, 0x04 }, |
192 | { 0xc204, 0x00 }, |
193 | { 0xc205, 0x00 }, |
194 | { 0xc206, 0x68 }, |
195 | { 0xc207, 0x70 }, |
196 | { 0xc208, 0x00 }, |
197 | { 0xc20a, 0x00 }, |
198 | { 0xc20b, 0x01 }, |
199 | { 0xc20c, 0x7f }, |
200 | { 0xc20d, 0x01 }, |
201 | { 0xc20e, 0x7f }, |
202 | { 0xc300, 0x00 }, |
203 | { 0xc301, 0x00 }, |
204 | { 0xc303, 0x80 }, |
205 | { 0xc320, 0x00 }, |
206 | { 0xc321, 0x09 }, |
207 | { 0xc322, 0x02 }, |
208 | { 0xc410, 0x04 }, |
209 | { 0xc430, 0x00 }, |
210 | { 0xc431, 0x00 }, |
211 | { 0xca00, 0x10 }, |
212 | { 0xca01, 0x00 }, |
213 | { 0xca02, 0x0b }, |
214 | { 0xca10, 0x10 }, |
215 | { 0xca11, 0x00 }, |
216 | { 0xca12, 0x0b }, |
217 | { 0xdd93, 0x00 }, |
218 | { 0xdd94, 0x64 }, |
219 | { 0xe300, 0xa0 }, |
220 | { 0xed00, 0x80 }, |
221 | { 0xed01, 0x0f }, |
222 | { 0xed02, 0xff }, |
223 | { 0xed03, 0x00 }, |
224 | { 0xed04, 0x00 }, |
225 | { 0xed05, 0x0f }, |
226 | { 0xed06, 0xff }, |
227 | { 0xf010, 0x10 }, |
228 | { 0xf011, 0xec }, |
229 | { 0xf012, 0x68 }, |
230 | { 0xf013, 0x21 }, |
231 | { 0xf800, 0x00 }, |
232 | { 0xf801, 0x12 }, |
233 | { 0xf802, 0xe0 }, |
234 | { 0xf803, 0x2f }, |
235 | { 0xf804, 0x00 }, |
236 | { 0xf805, 0x00 }, |
237 | { 0xf806, 0x07 }, |
238 | { 0xf807, 0xff }, |
239 | { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_UDMPU21, RT1318_SDCA_CTL_UDMPU_CLUSTER, 0), 0x00 }, |
240 | { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, |
241 | { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, |
242 | { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_PDE23, RT1318_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, |
243 | { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_CS21, RT1318_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, |
244 | }; |
245 | |
246 | static bool rt1318_readable_register(struct device *dev, unsigned int reg) |
247 | { |
248 | switch (reg) { |
249 | case 0x2f55: |
250 | case 0x3000: |
251 | case 0x3004 ... 0x3005: |
252 | case 0x3202 ... 0x3203: |
253 | case 0x3206: |
254 | case 0xc000 ... 0xc00f: |
255 | case 0xc120 ... 0xc125: |
256 | case 0xc200 ... 0xc20e: |
257 | case 0xc300 ... 0xc303: |
258 | case 0xc320 ... 0xc322: |
259 | case 0xc410: |
260 | case 0xc430 ... 0xc431: |
261 | case 0xca00 ... 0xca02: |
262 | case 0xca10 ... 0xca12: |
263 | case 0xcb00 ... 0xcb0b: |
264 | case 0xcc00 ... 0xcce5: |
265 | case 0xcd00 ... 0xcde5: |
266 | case 0xce00 ... 0xce6a: |
267 | case 0xcf00 ... 0xcf53: |
268 | case 0xd000 ... 0xd0cc: |
269 | case 0xd100 ... 0xd1b9: |
270 | case 0xdb00 ... 0xdc53: |
271 | case 0xdd00 ... 0xde53: |
272 | case 0xdf00 ... 0xdf6b: |
273 | case 0xe300: |
274 | case 0xeb00 ... 0xebcc: |
275 | case 0xec00 ... 0xecb9: |
276 | case 0xed00 ... 0xed06: |
277 | case 0xf010 ... 0xf014: |
278 | case 0xf800 ... 0xf807: |
279 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_UDMPU21, RT1318_SDCA_CTL_UDMPU_CLUSTER, 0): |
280 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_L): |
281 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_R): |
282 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_PDE23, RT1318_SDCA_CTL_REQ_POWER_STATE, 0): |
283 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_CS21, RT1318_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): |
284 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_SAPU, RT1318_SDCA_CTL_SAPU_PROTECTION_MODE, 0): |
285 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_SAPU, RT1318_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): |
286 | return true; |
287 | default: |
288 | return false; |
289 | } |
290 | } |
291 | |
292 | static bool rt1318_volatile_register(struct device *dev, unsigned int reg) |
293 | { |
294 | switch (reg) { |
295 | case 0x2f55: |
296 | case 0x3000 ... 0x3001: |
297 | case 0xc000: |
298 | case 0xc301: |
299 | case 0xc410: |
300 | case 0xc430 ... 0xc431: |
301 | case 0xdb06: |
302 | case 0xdb12: |
303 | case 0xdb1d ... 0xdb1f: |
304 | case 0xdb35: |
305 | case 0xdb37: |
306 | case 0xdb8a ... 0xdb92: |
307 | case 0xdbc5 ... 0xdbc8: |
308 | case 0xdc2b ... 0xdc49: |
309 | case 0xdd0b: |
310 | case 0xdd12: |
311 | case 0xdd1d ... 0xdd1f: |
312 | case 0xdd35: |
313 | case 0xdd8a ... 0xdd92: |
314 | case 0xddc5 ... 0xddc8: |
315 | case 0xde2b ... 0xde44: |
316 | case 0xdf4a ... 0xdf55: |
317 | case 0xe224 ... 0xe23b: |
318 | case 0xea01: |
319 | case 0xebc5: |
320 | case 0xebc8: |
321 | case 0xebcb ... 0xebcc: |
322 | case 0xed03 ... 0xed06: |
323 | case 0xf010 ... 0xf014: |
324 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_SAPU, RT1318_SDCA_CTL_SAPU_PROTECTION_MODE, 0): |
325 | case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_SAPU, RT1318_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): |
326 | return true; |
327 | default: |
328 | return false; |
329 | } |
330 | } |
331 | |
332 | static const struct regmap_config rt1318_sdw_regmap = { |
333 | .reg_bits = 32, |
334 | .val_bits = 8, |
335 | .readable_reg = rt1318_readable_register, |
336 | .volatile_reg = rt1318_volatile_register, |
337 | .max_register = 0x41081488, |
338 | .reg_defaults = rt1318_reg_defaults, |
339 | .num_reg_defaults = ARRAY_SIZE(rt1318_reg_defaults), |
340 | .cache_type = REGCACHE_MAPLE, |
341 | .use_single_read = true, |
342 | .use_single_write = true, |
343 | }; |
344 | |
345 | static int rt1318_read_prop(struct sdw_slave *slave) |
346 | { |
347 | struct sdw_slave_prop *prop = &slave->prop; |
348 | int nval; |
349 | int i, j; |
350 | u32 bit; |
351 | unsigned long addr; |
352 | struct sdw_dpn_prop *dpn; |
353 | |
354 | prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; |
355 | prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; |
356 | |
357 | prop->paging_support = true; |
358 | |
359 | /* first we need to allocate memory for set bits in port lists */ |
360 | prop->source_ports = BIT(2); |
361 | prop->sink_ports = BIT(1); |
362 | |
363 | nval = hweight32(prop->source_ports); |
364 | prop->src_dpn_prop = devm_kcalloc(dev: &slave->dev, n: nval, |
365 | size: sizeof(*prop->src_dpn_prop), GFP_KERNEL); |
366 | if (!prop->src_dpn_prop) |
367 | return -ENOMEM; |
368 | |
369 | i = 0; |
370 | dpn = prop->src_dpn_prop; |
371 | addr = prop->source_ports; |
372 | for_each_set_bit(bit, &addr, 32) { |
373 | dpn[i].num = bit; |
374 | dpn[i].type = SDW_DPN_FULL; |
375 | dpn[i].simple_ch_prep_sm = true; |
376 | dpn[i].ch_prep_timeout = 10; |
377 | i++; |
378 | } |
379 | |
380 | /* do this again for sink now */ |
381 | nval = hweight32(prop->sink_ports); |
382 | prop->sink_dpn_prop = devm_kcalloc(dev: &slave->dev, n: nval, |
383 | size: sizeof(*prop->sink_dpn_prop), GFP_KERNEL); |
384 | if (!prop->sink_dpn_prop) |
385 | return -ENOMEM; |
386 | |
387 | j = 0; |
388 | dpn = prop->sink_dpn_prop; |
389 | addr = prop->sink_ports; |
390 | for_each_set_bit(bit, &addr, 32) { |
391 | dpn[j].num = bit; |
392 | dpn[j].type = SDW_DPN_FULL; |
393 | dpn[j].simple_ch_prep_sm = true; |
394 | dpn[j].ch_prep_timeout = 10; |
395 | j++; |
396 | } |
397 | |
398 | /* set the timeout values */ |
399 | prop->clk_stop_timeout = 20; |
400 | |
401 | return 0; |
402 | } |
403 | |
404 | static int rt1318_io_init(struct device *dev, struct sdw_slave *slave) |
405 | { |
406 | struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); |
407 | |
408 | if (rt1318->hw_init) |
409 | return 0; |
410 | |
411 | regcache_cache_only(map: rt1318->regmap, enable: false); |
412 | if (rt1318->first_hw_init) { |
413 | regcache_cache_bypass(map: rt1318->regmap, enable: true); |
414 | } else { |
415 | /* |
416 | * PM runtime status is marked as 'active' only when a Slave reports as Attached |
417 | */ |
418 | /* update count of parent 'active' children */ |
419 | pm_runtime_set_active(dev: &slave->dev); |
420 | } |
421 | |
422 | pm_runtime_get_noresume(dev: &slave->dev); |
423 | |
424 | /* blind write */ |
425 | regmap_multi_reg_write(map: rt1318->regmap, regs: rt1318_blind_write, |
426 | ARRAY_SIZE(rt1318_blind_write)); |
427 | |
428 | if (rt1318->first_hw_init) { |
429 | regcache_cache_bypass(map: rt1318->regmap, enable: false); |
430 | regcache_mark_dirty(map: rt1318->regmap); |
431 | } |
432 | |
433 | /* Mark Slave initialization complete */ |
434 | rt1318->first_hw_init = true; |
435 | rt1318->hw_init = true; |
436 | |
437 | pm_runtime_mark_last_busy(dev: &slave->dev); |
438 | pm_runtime_put_autosuspend(dev: &slave->dev); |
439 | |
440 | dev_dbg(&slave->dev, "%s hw_init complete\n" , __func__); |
441 | return 0; |
442 | } |
443 | |
444 | static int rt1318_update_status(struct sdw_slave *slave, |
445 | enum sdw_slave_status status) |
446 | { |
447 | struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev: &slave->dev); |
448 | |
449 | if (status == SDW_SLAVE_UNATTACHED) |
450 | rt1318->hw_init = false; |
451 | |
452 | /* |
453 | * Perform initialization only if slave status is present and |
454 | * hw_init flag is false |
455 | */ |
456 | if (rt1318->hw_init || status != SDW_SLAVE_ATTACHED) |
457 | return 0; |
458 | |
459 | /* perform I/O transfers required for Slave initialization */ |
460 | return rt1318_io_init(dev: &slave->dev, slave); |
461 | } |
462 | |
463 | static int rt1318_classd_event(struct snd_soc_dapm_widget *w, |
464 | struct snd_kcontrol *kcontrol, int event) |
465 | { |
466 | struct snd_soc_component *component = |
467 | snd_soc_dapm_to_component(dapm: w->dapm); |
468 | struct rt1318_sdw_priv *rt1318 = snd_soc_component_get_drvdata(c: component); |
469 | unsigned char ps0 = 0x0, ps3 = 0x3; |
470 | |
471 | switch (event) { |
472 | case SND_SOC_DAPM_POST_PMU: |
473 | regmap_write(map: rt1318->regmap, |
474 | SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_PDE23, |
475 | RT1318_SDCA_CTL_REQ_POWER_STATE, 0), |
476 | val: ps0); |
477 | break; |
478 | case SND_SOC_DAPM_PRE_PMD: |
479 | regmap_write(map: rt1318->regmap, |
480 | SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_PDE23, |
481 | RT1318_SDCA_CTL_REQ_POWER_STATE, 0), |
482 | val: ps3); |
483 | break; |
484 | |
485 | default: |
486 | break; |
487 | } |
488 | |
489 | return 0; |
490 | } |
491 | |
492 | static const char * const rt1318_rx_data_ch_select[] = { |
493 | "L,R" , |
494 | "L,L" , |
495 | "L,R" , |
496 | "L,L+R" , |
497 | "R,L" , |
498 | "R,R" , |
499 | "R,L+R" , |
500 | "L+R,L" , |
501 | "L+R,R" , |
502 | "L+R,L+R" , |
503 | }; |
504 | |
505 | static SOC_ENUM_SINGLE_DECL(rt1318_rx_data_ch_enum, |
506 | SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_UDMPU21, RT1318_SDCA_CTL_UDMPU_CLUSTER, 0), 0, |
507 | rt1318_rx_data_ch_select); |
508 | |
509 | static const struct snd_kcontrol_new rt1318_snd_controls[] = { |
510 | |
511 | /* UDMPU Cluster Selection */ |
512 | SOC_ENUM("RX Channel Select" , rt1318_rx_data_ch_enum), |
513 | }; |
514 | |
515 | static const struct snd_kcontrol_new rt1318_sto_dac = |
516 | SOC_DAPM_DOUBLE_R("Switch" , |
517 | SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_L), |
518 | SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_R), |
519 | 0, 1, 1); |
520 | |
521 | static const struct snd_soc_dapm_widget rt1318_dapm_widgets[] = { |
522 | /* Audio Interface */ |
523 | SND_SOC_DAPM_AIF_IN("DP1RX" , "DP1 Playback" , 0, SND_SOC_NOPM, 0, 0), |
524 | SND_SOC_DAPM_AIF_OUT("DP2TX" , "DP2 Capture" , 0, SND_SOC_NOPM, 0, 0), |
525 | |
526 | /* Digital Interface */ |
527 | SND_SOC_DAPM_SWITCH("DAC" , SND_SOC_NOPM, 0, 0, &rt1318_sto_dac), |
528 | |
529 | /* Output */ |
530 | SND_SOC_DAPM_PGA_E("CLASS D" , SND_SOC_NOPM, 0, 0, NULL, 0, |
531 | rt1318_classd_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
532 | SND_SOC_DAPM_OUTPUT("SPOL" ), |
533 | SND_SOC_DAPM_OUTPUT("SPOR" ), |
534 | /* Input */ |
535 | SND_SOC_DAPM_PGA("FB Data" , SND_SOC_NOPM, 0, 0, NULL, 0), |
536 | SND_SOC_DAPM_SIGGEN("FB Gen" ), |
537 | }; |
538 | |
539 | static const struct snd_soc_dapm_route rt1318_dapm_routes[] = { |
540 | { "DAC" , "Switch" , "DP1RX" }, |
541 | { "CLASS D" , NULL, "DAC" }, |
542 | { "SPOL" , NULL, "CLASS D" }, |
543 | { "SPOR" , NULL, "CLASS D" }, |
544 | |
545 | { "FB Data" , NULL, "FB Gen" }, |
546 | { "DP2TX" , NULL, "FB Data" }, |
547 | }; |
548 | |
549 | static int rt1318_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, |
550 | int direction) |
551 | { |
552 | snd_soc_dai_dma_data_set(dai, stream: direction, data: sdw_stream); |
553 | |
554 | return 0; |
555 | } |
556 | |
557 | static void rt1318_sdw_shutdown(struct snd_pcm_substream *substream, |
558 | struct snd_soc_dai *dai) |
559 | { |
560 | snd_soc_dai_set_dma_data(dai, substream, NULL); |
561 | } |
562 | |
563 | static int rt1318_sdw_hw_params(struct snd_pcm_substream *substream, |
564 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
565 | { |
566 | struct snd_soc_component *component = dai->component; |
567 | struct rt1318_sdw_priv *rt1318 = |
568 | snd_soc_component_get_drvdata(c: component); |
569 | struct sdw_stream_config stream_config; |
570 | struct sdw_port_config port_config; |
571 | enum sdw_data_direction direction; |
572 | struct sdw_stream_runtime *sdw_stream; |
573 | int retval, port, num_channels, ch_mask; |
574 | unsigned int sampling_rate; |
575 | |
576 | dev_dbg(dai->dev, "%s %s" , __func__, dai->name); |
577 | sdw_stream = snd_soc_dai_get_dma_data(dai, substream); |
578 | |
579 | if (!sdw_stream) |
580 | return -EINVAL; |
581 | |
582 | if (!rt1318->sdw_slave) |
583 | return -EINVAL; |
584 | |
585 | /* SoundWire specific configuration */ |
586 | /* port 1 for playback */ |
587 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
588 | direction = SDW_DATA_DIR_RX; |
589 | port = 1; |
590 | } else { |
591 | direction = SDW_DATA_DIR_TX; |
592 | port = 2; |
593 | } |
594 | |
595 | num_channels = params_channels(p: params); |
596 | ch_mask = (1 << num_channels) - 1; |
597 | |
598 | stream_config.frame_rate = params_rate(p: params); |
599 | stream_config.ch_count = num_channels; |
600 | stream_config.bps = snd_pcm_format_width(format: params_format(p: params)); |
601 | stream_config.direction = direction; |
602 | |
603 | port_config.ch_mask = ch_mask; |
604 | port_config.num = port; |
605 | |
606 | retval = sdw_stream_add_slave(slave: rt1318->sdw_slave, stream_config: &stream_config, |
607 | port_config: &port_config, num_ports: 1, stream: sdw_stream); |
608 | if (retval) { |
609 | dev_err(dai->dev, "%s: Unable to configure port\n" , __func__); |
610 | return retval; |
611 | } |
612 | |
613 | /* sampling rate configuration */ |
614 | switch (params_rate(p: params)) { |
615 | case 16000: |
616 | sampling_rate = RT1318_SDCA_RATE_16000HZ; |
617 | break; |
618 | case 32000: |
619 | sampling_rate = RT1318_SDCA_RATE_32000HZ; |
620 | break; |
621 | case 44100: |
622 | sampling_rate = RT1318_SDCA_RATE_44100HZ; |
623 | break; |
624 | case 48000: |
625 | sampling_rate = RT1318_SDCA_RATE_48000HZ; |
626 | break; |
627 | case 96000: |
628 | sampling_rate = RT1318_SDCA_RATE_96000HZ; |
629 | break; |
630 | case 192000: |
631 | sampling_rate = RT1318_SDCA_RATE_192000HZ; |
632 | break; |
633 | default: |
634 | dev_err(component->dev, "%s: Rate %d is not supported\n" , |
635 | __func__, params_rate(params)); |
636 | return -EINVAL; |
637 | } |
638 | |
639 | /* set sampling frequency */ |
640 | regmap_write(map: rt1318->regmap, |
641 | SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_CS21, RT1318_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), |
642 | val: sampling_rate); |
643 | |
644 | return 0; |
645 | } |
646 | |
647 | static int rt1318_sdw_pcm_hw_free(struct snd_pcm_substream *substream, |
648 | struct snd_soc_dai *dai) |
649 | { |
650 | struct snd_soc_component *component = dai->component; |
651 | struct rt1318_sdw_priv *rt1318 = |
652 | snd_soc_component_get_drvdata(c: component); |
653 | struct sdw_stream_runtime *sdw_stream = |
654 | snd_soc_dai_get_dma_data(dai, substream); |
655 | |
656 | if (!rt1318->sdw_slave) |
657 | return -EINVAL; |
658 | |
659 | sdw_stream_remove_slave(slave: rt1318->sdw_slave, stream: sdw_stream); |
660 | return 0; |
661 | } |
662 | |
663 | /* |
664 | * slave_ops: callbacks for get_clock_stop_mode, clock_stop and |
665 | * port_prep are not defined for now |
666 | */ |
667 | static const struct sdw_slave_ops rt1318_slave_ops = { |
668 | .read_prop = rt1318_read_prop, |
669 | .update_status = rt1318_update_status, |
670 | }; |
671 | |
672 | static int rt1318_sdw_component_probe(struct snd_soc_component *component) |
673 | { |
674 | int ret; |
675 | struct rt1318_sdw_priv *rt1318 = snd_soc_component_get_drvdata(c: component); |
676 | |
677 | rt1318->component = component; |
678 | |
679 | if (!rt1318->first_hw_init) |
680 | return 0; |
681 | |
682 | ret = pm_runtime_resume(dev: component->dev); |
683 | dev_dbg(&rt1318->sdw_slave->dev, "%s pm_runtime_resume, ret=%d" , __func__, ret); |
684 | if (ret < 0 && ret != -EACCES) |
685 | return ret; |
686 | |
687 | return 0; |
688 | } |
689 | |
690 | static const struct snd_soc_component_driver soc_component_sdw_rt1318 = { |
691 | .probe = rt1318_sdw_component_probe, |
692 | .controls = rt1318_snd_controls, |
693 | .num_controls = ARRAY_SIZE(rt1318_snd_controls), |
694 | .dapm_widgets = rt1318_dapm_widgets, |
695 | .num_dapm_widgets = ARRAY_SIZE(rt1318_dapm_widgets), |
696 | .dapm_routes = rt1318_dapm_routes, |
697 | .num_dapm_routes = ARRAY_SIZE(rt1318_dapm_routes), |
698 | .endianness = 1, |
699 | }; |
700 | |
701 | static const struct snd_soc_dai_ops rt1318_aif_dai_ops = { |
702 | .hw_params = rt1318_sdw_hw_params, |
703 | .hw_free = rt1318_sdw_pcm_hw_free, |
704 | .set_stream = rt1318_set_sdw_stream, |
705 | .shutdown = rt1318_sdw_shutdown, |
706 | }; |
707 | |
708 | #define RT1318_STEREO_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ |
709 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) |
710 | #define RT1318_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ |
711 | SNDRV_PCM_FMTBIT_S32_LE) |
712 | |
713 | static struct snd_soc_dai_driver rt1318_sdw_dai[] = { |
714 | { |
715 | .name = "rt1318-aif" , |
716 | .playback = { |
717 | .stream_name = "DP1 Playback" , |
718 | .channels_min = 1, |
719 | .channels_max = 2, |
720 | .rates = RT1318_STEREO_RATES, |
721 | .formats = RT1318_FORMATS, |
722 | }, |
723 | .capture = { |
724 | .stream_name = "DP2 Capture" , |
725 | .channels_min = 1, |
726 | .channels_max = 2, |
727 | .rates = RT1318_STEREO_RATES, |
728 | .formats = RT1318_FORMATS, |
729 | }, |
730 | .ops = &rt1318_aif_dai_ops, |
731 | }, |
732 | }; |
733 | |
734 | static int rt1318_sdw_init(struct device *dev, struct regmap *regmap, |
735 | struct sdw_slave *slave) |
736 | { |
737 | struct rt1318_sdw_priv *rt1318; |
738 | int ret; |
739 | |
740 | rt1318 = devm_kzalloc(dev, size: sizeof(*rt1318), GFP_KERNEL); |
741 | if (!rt1318) |
742 | return -ENOMEM; |
743 | |
744 | dev_set_drvdata(dev, data: rt1318); |
745 | rt1318->sdw_slave = slave; |
746 | rt1318->regmap = regmap; |
747 | |
748 | regcache_cache_only(map: rt1318->regmap, enable: true); |
749 | |
750 | /* |
751 | * Mark hw_init to false |
752 | * HW init will be performed when device reports present |
753 | */ |
754 | rt1318->hw_init = false; |
755 | rt1318->first_hw_init = false; |
756 | |
757 | ret = devm_snd_soc_register_component(dev, |
758 | component_driver: &soc_component_sdw_rt1318, |
759 | dai_drv: rt1318_sdw_dai, |
760 | ARRAY_SIZE(rt1318_sdw_dai)); |
761 | if (ret < 0) |
762 | return ret; |
763 | |
764 | /* set autosuspend parameters */ |
765 | pm_runtime_set_autosuspend_delay(dev, delay: 3000); |
766 | pm_runtime_use_autosuspend(dev); |
767 | |
768 | /* make sure the device does not suspend immediately */ |
769 | pm_runtime_mark_last_busy(dev); |
770 | |
771 | pm_runtime_enable(dev); |
772 | |
773 | /* important note: the device is NOT tagged as 'active' and will remain |
774 | * 'suspended' until the hardware is enumerated/initialized. This is required |
775 | * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently |
776 | * fail with -EACCESS because of race conditions between card creation and enumeration |
777 | */ |
778 | |
779 | dev_dbg(dev, "%s\n" , __func__); |
780 | |
781 | return ret; |
782 | } |
783 | |
784 | static int rt1318_sdw_probe(struct sdw_slave *slave, |
785 | const struct sdw_device_id *id) |
786 | { |
787 | struct regmap *regmap; |
788 | |
789 | /* Regmap Initialization */ |
790 | regmap = devm_regmap_init_sdw(slave, &rt1318_sdw_regmap); |
791 | if (IS_ERR(ptr: regmap)) |
792 | return PTR_ERR(ptr: regmap); |
793 | |
794 | return rt1318_sdw_init(dev: &slave->dev, regmap, slave); |
795 | } |
796 | |
797 | static int rt1318_sdw_remove(struct sdw_slave *slave) |
798 | { |
799 | pm_runtime_disable(dev: &slave->dev); |
800 | |
801 | return 0; |
802 | } |
803 | |
804 | static const struct sdw_device_id rt1318_id[] = { |
805 | SDW_SLAVE_ENTRY_EXT(0x025d, 0x1318, 0x3, 0x1, 0), |
806 | {}, |
807 | }; |
808 | MODULE_DEVICE_TABLE(sdw, rt1318_id); |
809 | |
810 | static int __maybe_unused rt1318_dev_suspend(struct device *dev) |
811 | { |
812 | struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); |
813 | |
814 | if (!rt1318->hw_init) |
815 | return 0; |
816 | |
817 | regcache_cache_only(map: rt1318->regmap, enable: true); |
818 | return 0; |
819 | } |
820 | |
821 | #define RT1318_PROBE_TIMEOUT 5000 |
822 | |
823 | static int __maybe_unused rt1318_dev_resume(struct device *dev) |
824 | { |
825 | struct sdw_slave *slave = dev_to_sdw_dev(dev); |
826 | struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); |
827 | unsigned long time; |
828 | |
829 | if (!rt1318->first_hw_init) |
830 | return 0; |
831 | |
832 | if (!slave->unattach_request) |
833 | goto regmap_sync; |
834 | |
835 | time = wait_for_completion_timeout(x: &slave->initialization_complete, |
836 | timeout: msecs_to_jiffies(RT1318_PROBE_TIMEOUT)); |
837 | if (!time) { |
838 | dev_err(&slave->dev, "%s: Initialization not complete, timed out\n" , __func__); |
839 | return -ETIMEDOUT; |
840 | } |
841 | |
842 | regmap_sync: |
843 | slave->unattach_request = 0; |
844 | regcache_cache_only(map: rt1318->regmap, enable: false); |
845 | regcache_sync(map: rt1318->regmap); |
846 | |
847 | return 0; |
848 | } |
849 | |
850 | static const struct dev_pm_ops rt1318_pm = { |
851 | SET_SYSTEM_SLEEP_PM_OPS(rt1318_dev_suspend, rt1318_dev_resume) |
852 | SET_RUNTIME_PM_OPS(rt1318_dev_suspend, rt1318_dev_resume, NULL) |
853 | }; |
854 | |
855 | static struct sdw_driver rt1318_sdw_driver = { |
856 | .driver = { |
857 | .name = "rt1318-sdca" , |
858 | .owner = THIS_MODULE, |
859 | .pm = &rt1318_pm, |
860 | }, |
861 | .probe = rt1318_sdw_probe, |
862 | .remove = rt1318_sdw_remove, |
863 | .ops = &rt1318_slave_ops, |
864 | .id_table = rt1318_id, |
865 | }; |
866 | module_sdw_driver(rt1318_sdw_driver); |
867 | |
868 | MODULE_DESCRIPTION("ASoC RT1318 driver SDCA SDW" ); |
869 | MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>" ); |
870 | MODULE_LICENSE("GPL" ); |
871 | |