1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // Copyright (c) 2022, Analog Devices Inc. |
3 | |
4 | #include <linux/module.h> |
5 | #include <linux/pm_runtime.h> |
6 | #include <linux/regmap.h> |
7 | #include <linux/soundwire/sdw.h> |
8 | #include <linux/soundwire/sdw_registers.h> |
9 | #include <linux/soundwire/sdw_type.h> |
10 | #include <sound/pcm.h> |
11 | #include <sound/pcm_params.h> |
12 | #include <sound/soc.h> |
13 | #include <sound/tlv.h> |
14 | |
15 | #include "max98363.h" |
16 | |
17 | static struct reg_default max98363_reg[] = { |
18 | {MAX98363_R2021_ERR_MON_CTRL, 0x0}, |
19 | {MAX98363_R2022_SPK_MON_THRESH, 0x0}, |
20 | {MAX98363_R2023_SPK_MON_DURATION, 0x0}, |
21 | {MAX98363_R2030_TONE_GEN_CFG, 0x0}, |
22 | {MAX98363_R203F_TONE_GEN_EN, 0x0}, |
23 | {MAX98363_R2040_AMP_VOL, 0x0}, |
24 | {MAX98363_R2041_AMP_GAIN, 0x5}, |
25 | {MAX98363_R2042_DSP_CFG, 0x0}, |
26 | }; |
27 | |
28 | static bool max98363_readable_register(struct device *dev, unsigned int reg) |
29 | { |
30 | switch (reg) { |
31 | case MAX98363_R2001_INTR_RAW: |
32 | case MAX98363_R2003_INTR_STATE: |
33 | case MAX98363_R2005_INTR_FALG: |
34 | case MAX98363_R2007_INTR_EN: |
35 | case MAX98363_R2009_INTR_CLR: |
36 | case MAX98363_R2021_ERR_MON_CTRL ... MAX98363_R2023_SPK_MON_DURATION: |
37 | case MAX98363_R2030_TONE_GEN_CFG: |
38 | case MAX98363_R203F_TONE_GEN_EN: |
39 | case MAX98363_R2040_AMP_VOL: |
40 | case MAX98363_R2041_AMP_GAIN: |
41 | case MAX98363_R2042_DSP_CFG: |
42 | case MAX98363_R21FF_REV_ID: |
43 | return true; |
44 | default: |
45 | return false; |
46 | } |
47 | }; |
48 | |
49 | static bool max98363_volatile_reg(struct device *dev, unsigned int reg) |
50 | { |
51 | switch (reg) { |
52 | case MAX98363_R2001_INTR_RAW: |
53 | case MAX98363_R2003_INTR_STATE: |
54 | case MAX98363_R2005_INTR_FALG: |
55 | case MAX98363_R2007_INTR_EN: |
56 | case MAX98363_R2009_INTR_CLR: |
57 | case MAX98363_R21FF_REV_ID: |
58 | return true; |
59 | default: |
60 | return false; |
61 | } |
62 | } |
63 | |
64 | static const struct regmap_config max98363_sdw_regmap = { |
65 | .reg_bits = 32, |
66 | .val_bits = 8, |
67 | .max_register = MAX98363_R21FF_REV_ID, |
68 | .reg_defaults = max98363_reg, |
69 | .num_reg_defaults = ARRAY_SIZE(max98363_reg), |
70 | .readable_reg = max98363_readable_register, |
71 | .volatile_reg = max98363_volatile_reg, |
72 | .cache_type = REGCACHE_RBTREE, |
73 | .use_single_read = true, |
74 | .use_single_write = true, |
75 | }; |
76 | |
77 | static int max98363_suspend(struct device *dev) |
78 | { |
79 | struct max98363_priv *max98363 = dev_get_drvdata(dev); |
80 | |
81 | regcache_cache_only(map: max98363->regmap, enable: true); |
82 | regcache_mark_dirty(map: max98363->regmap); |
83 | |
84 | return 0; |
85 | } |
86 | |
87 | #define MAX98363_PROBE_TIMEOUT 5000 |
88 | |
89 | static int max98363_resume(struct device *dev) |
90 | { |
91 | struct sdw_slave *slave = dev_to_sdw_dev(dev); |
92 | struct max98363_priv *max98363 = dev_get_drvdata(dev); |
93 | unsigned long time; |
94 | |
95 | if (!max98363->first_hw_init) |
96 | return 0; |
97 | |
98 | if (!slave->unattach_request) |
99 | goto regmap_sync; |
100 | |
101 | time = wait_for_completion_timeout(x: &slave->initialization_complete, |
102 | timeout: msecs_to_jiffies(MAX98363_PROBE_TIMEOUT)); |
103 | if (!time) { |
104 | dev_err(dev, "Initialization not complete, timed out\n" ); |
105 | return -ETIMEDOUT; |
106 | } |
107 | |
108 | regmap_sync: |
109 | |
110 | slave->unattach_request = 0; |
111 | regcache_cache_only(map: max98363->regmap, enable: false); |
112 | regcache_sync(map: max98363->regmap); |
113 | |
114 | return 0; |
115 | } |
116 | |
117 | static DEFINE_RUNTIME_DEV_PM_OPS(max98363_pm, max98363_suspend, max98363_resume, NULL); |
118 | |
119 | static int max98363_read_prop(struct sdw_slave *slave) |
120 | { |
121 | struct sdw_slave_prop *prop = &slave->prop; |
122 | int nval, i; |
123 | u32 bit; |
124 | unsigned long addr; |
125 | struct sdw_dpn_prop *dpn; |
126 | |
127 | prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; |
128 | |
129 | /* BITMAP: 00000010 Dataport 1 is active */ |
130 | prop->sink_ports = BIT(1); |
131 | prop->paging_support = true; |
132 | prop->clk_stop_timeout = 20; |
133 | prop->simple_clk_stop_capable = true; |
134 | prop->clock_reg_supported = true; |
135 | |
136 | nval = hweight32(prop->sink_ports); |
137 | prop->sink_dpn_prop = devm_kcalloc(dev: &slave->dev, n: nval, |
138 | size: sizeof(*prop->sink_dpn_prop), |
139 | GFP_KERNEL); |
140 | if (!prop->sink_dpn_prop) |
141 | return -ENOMEM; |
142 | |
143 | i = 0; |
144 | dpn = prop->sink_dpn_prop; |
145 | addr = prop->sink_ports; |
146 | for_each_set_bit(bit, &addr, 32) { |
147 | dpn[i].num = bit; |
148 | dpn[i].type = SDW_DPN_FULL; |
149 | dpn[i].simple_ch_prep_sm = true; |
150 | dpn[i].ch_prep_timeout = 10; |
151 | i++; |
152 | } |
153 | |
154 | return 0; |
155 | } |
156 | |
157 | static int max98363_io_init(struct sdw_slave *slave) |
158 | { |
159 | struct device *dev = &slave->dev; |
160 | struct max98363_priv *max98363 = dev_get_drvdata(dev); |
161 | int ret, reg; |
162 | |
163 | regcache_cache_only(map: max98363->regmap, enable: false); |
164 | if (max98363->first_hw_init) |
165 | regcache_cache_bypass(map: max98363->regmap, enable: true); |
166 | |
167 | /* |
168 | * PM runtime status is marked as 'active' only when a Slave reports as Attached |
169 | */ |
170 | if (!max98363->first_hw_init) |
171 | /* update count of parent 'active' children */ |
172 | pm_runtime_set_active(dev); |
173 | |
174 | pm_runtime_get_noresume(dev); |
175 | |
176 | ret = regmap_read(map: max98363->regmap, MAX98363_R21FF_REV_ID, val: ®); |
177 | if (!ret) |
178 | dev_info(dev, "Revision ID: %X\n" , reg); |
179 | else |
180 | goto out; |
181 | |
182 | if (max98363->first_hw_init) { |
183 | regcache_cache_bypass(map: max98363->regmap, enable: false); |
184 | regcache_mark_dirty(map: max98363->regmap); |
185 | } |
186 | |
187 | max98363->first_hw_init = true; |
188 | max98363->hw_init = true; |
189 | |
190 | out: |
191 | pm_runtime_mark_last_busy(dev); |
192 | pm_runtime_put_autosuspend(dev); |
193 | |
194 | return ret; |
195 | } |
196 | |
197 | #define MAX98363_RATES SNDRV_PCM_RATE_8000_192000 |
198 | #define MAX98363_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) |
199 | |
200 | static int max98363_sdw_dai_hw_params(struct snd_pcm_substream *substream, |
201 | struct snd_pcm_hw_params *params, |
202 | struct snd_soc_dai *dai) |
203 | { |
204 | struct snd_soc_component *component = dai->component; |
205 | struct max98363_priv *max98363 = |
206 | snd_soc_component_get_drvdata(c: component); |
207 | |
208 | struct sdw_stream_config stream_config; |
209 | struct sdw_port_config port_config; |
210 | enum sdw_data_direction direction; |
211 | struct sdw_stream_runtime *stream; |
212 | struct snd_pcm_runtime *runtime = substream->runtime; |
213 | |
214 | int ret; |
215 | |
216 | stream = snd_soc_dai_get_dma_data(dai, substream); |
217 | |
218 | if (!stream) |
219 | return -EINVAL; |
220 | |
221 | if (!max98363->slave) |
222 | return -EINVAL; |
223 | |
224 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) |
225 | return -EINVAL; |
226 | |
227 | direction = SDW_DATA_DIR_RX; |
228 | port_config.num = 1; |
229 | |
230 | stream_config.frame_rate = params_rate(p: params); |
231 | stream_config.bps = snd_pcm_format_width(format: params_format(p: params)); |
232 | stream_config.direction = direction; |
233 | stream_config.ch_count = 1; |
234 | |
235 | if (stream_config.ch_count > runtime->hw.channels_max) { |
236 | stream_config.ch_count = runtime->hw.channels_max; |
237 | dev_info(dai->dev, "Number of channels: %d (requested: %d)\n" , |
238 | stream_config.ch_count, params_channels(params)); |
239 | } |
240 | port_config.ch_mask = GENMASK((int)stream_config.ch_count - 1, 0); |
241 | |
242 | ret = sdw_stream_add_slave(slave: max98363->slave, stream_config: &stream_config, |
243 | port_config: &port_config, num_ports: 1, stream); |
244 | if (ret) { |
245 | dev_err(dai->dev, "Unable to configure port\n" ); |
246 | return ret; |
247 | } |
248 | |
249 | dev_dbg(component->dev, "Format supported %d" , params_format(params)); |
250 | |
251 | return 0; |
252 | } |
253 | |
254 | static int max98363_pcm_hw_free(struct snd_pcm_substream *substream, |
255 | struct snd_soc_dai *dai) |
256 | { |
257 | struct snd_soc_component *component = dai->component; |
258 | struct max98363_priv *max98363 = |
259 | snd_soc_component_get_drvdata(c: component); |
260 | struct sdw_stream_runtime *stream = |
261 | snd_soc_dai_get_dma_data(dai, substream); |
262 | |
263 | if (!max98363->slave) |
264 | return -EINVAL; |
265 | |
266 | sdw_stream_remove_slave(slave: max98363->slave, stream); |
267 | |
268 | return 0; |
269 | } |
270 | |
271 | static int max98363_set_sdw_stream(struct snd_soc_dai *dai, |
272 | void *sdw_stream, int direction) |
273 | { |
274 | snd_soc_dai_dma_data_set(dai, stream: direction, data: sdw_stream); |
275 | |
276 | return 0; |
277 | } |
278 | |
279 | static const struct snd_soc_dai_ops max98363_dai_sdw_ops = { |
280 | .hw_params = max98363_sdw_dai_hw_params, |
281 | .hw_free = max98363_pcm_hw_free, |
282 | .set_stream = max98363_set_sdw_stream, |
283 | }; |
284 | |
285 | static struct snd_soc_dai_driver max98363_dai[] = { |
286 | { |
287 | .name = "max98363-aif1" , |
288 | .playback = { |
289 | .stream_name = "HiFi Playback" , |
290 | .channels_min = 1, |
291 | .channels_max = 1, |
292 | .rates = MAX98363_RATES, |
293 | .formats = MAX98363_FORMATS, |
294 | }, |
295 | .ops = &max98363_dai_sdw_ops, |
296 | } |
297 | }; |
298 | |
299 | static int max98363_update_status(struct sdw_slave *slave, |
300 | enum sdw_slave_status status) |
301 | { |
302 | struct max98363_priv *max98363 = dev_get_drvdata(dev: &slave->dev); |
303 | |
304 | if (status == SDW_SLAVE_UNATTACHED) |
305 | max98363->hw_init = false; |
306 | |
307 | /* |
308 | * Perform initialization only if slave status is SDW_SLAVE_ATTACHED |
309 | */ |
310 | if (max98363->hw_init || status != SDW_SLAVE_ATTACHED) |
311 | return 0; |
312 | |
313 | /* perform I/O transfers required for Slave initialization */ |
314 | return max98363_io_init(slave); |
315 | } |
316 | |
317 | static const struct sdw_slave_ops max98363_slave_ops = { |
318 | .read_prop = max98363_read_prop, |
319 | .update_status = max98363_update_status, |
320 | }; |
321 | |
322 | static DECLARE_TLV_DB_SCALE(max98363_digital_tlv, -6350, 50, 1); |
323 | static const DECLARE_TLV_DB_RANGE(max98363_spk_tlv, |
324 | 0, 5, TLV_DB_SCALE_ITEM(-300, 300, 0), |
325 | ); |
326 | |
327 | static const char * const max98363_tone_cfg_text[] = { |
328 | "Reserved" , "0" , "+FS/2" , "-FS/2" , "1KHz" , |
329 | "12KHz" , "8KHz" , "6KHz" , "4KHz" , "3KHz" , |
330 | "2KHz" , "1.5KHz" , "Reserved" , "500Hz" , "250Hz" |
331 | }; |
332 | |
333 | static SOC_ENUM_SINGLE_DECL(max98363_tone_cfg_enum, |
334 | MAX98363_R2030_TONE_GEN_CFG, 0, |
335 | max98363_tone_cfg_text); |
336 | |
337 | static const char * const max98363_spkmon_duration_text[] = { |
338 | "8ms" , "20ms" , "40ms" , "60ms" , |
339 | "80ms" , "160ms" , "240ms" , "320ms" , |
340 | "400ms" , "480ms" , "560ms" , "640ms" , |
341 | "720ms" , "800ms" , "880ms" , "960ms" |
342 | }; |
343 | |
344 | static SOC_ENUM_SINGLE_DECL(max98363_spkmon_duration_enum, |
345 | MAX98363_R2023_SPK_MON_DURATION, 0, |
346 | max98363_spkmon_duration_text); |
347 | |
348 | static const struct snd_kcontrol_new max98363_snd_controls[] = { |
349 | SOC_SINGLE_TLV("Digital Volume" , MAX98363_R2040_AMP_VOL, |
350 | 0, 0x7F, 1, max98363_digital_tlv), |
351 | SOC_SINGLE_TLV("Speaker Volume" , MAX98363_R2041_AMP_GAIN, |
352 | 0, 10, 0, max98363_spk_tlv), |
353 | SOC_SINGLE("Tone Generator Switch" , MAX98363_R203F_TONE_GEN_EN, |
354 | 0, 1, 0), |
355 | SOC_ENUM("Tone Config" , max98363_tone_cfg_enum), |
356 | SOC_SINGLE("Ramp Switch" , MAX98363_R2042_DSP_CFG, |
357 | MAX98363_AMP_DSP_CFG_RMP_SHIFT, 1, 0), |
358 | SOC_SINGLE("CLK Monitor Switch" , MAX98363_R2021_ERR_MON_CTRL, |
359 | MAX98363_CLOCK_MON_SHIFT, 1, 0), |
360 | SOC_SINGLE("SPKMON Monitor Switch" , MAX98363_R2021_ERR_MON_CTRL, |
361 | MAX98363_SPKMON_SHIFT, 1, 0), |
362 | SOC_SINGLE("SPKMON Thresh" , MAX98363_R2022_SPK_MON_THRESH, 0, 0xFF, 0), |
363 | SOC_ENUM("SPKMON Duration" , max98363_spkmon_duration_enum), |
364 | }; |
365 | |
366 | static const struct snd_soc_dapm_widget max98363_dapm_widgets[] = { |
367 | SND_SOC_DAPM_AIF_IN("AIFIN" , "HiFi Playback" , 0, SND_SOC_NOPM, 0, 0), |
368 | SND_SOC_DAPM_OUTPUT("BE_OUT" ), |
369 | }; |
370 | |
371 | static const struct snd_soc_dapm_route max98363_audio_map[] = { |
372 | /* Plabyack */ |
373 | {"BE_OUT" , NULL, "AIFIN" }, |
374 | }; |
375 | |
376 | static const struct snd_soc_component_driver soc_codec_dev_max98363 = { |
377 | .controls = max98363_snd_controls, |
378 | .num_controls = ARRAY_SIZE(max98363_snd_controls), |
379 | .dapm_widgets = max98363_dapm_widgets, |
380 | .num_dapm_widgets = ARRAY_SIZE(max98363_dapm_widgets), |
381 | .dapm_routes = max98363_audio_map, |
382 | .num_dapm_routes = ARRAY_SIZE(max98363_audio_map), |
383 | .use_pmdown_time = 1, |
384 | .endianness = 1, |
385 | }; |
386 | |
387 | static int max98363_init(struct sdw_slave *slave, struct regmap *regmap) |
388 | { |
389 | struct max98363_priv *max98363; |
390 | int ret; |
391 | struct device *dev = &slave->dev; |
392 | |
393 | /* Allocate and assign private driver data structure */ |
394 | max98363 = devm_kzalloc(dev, size: sizeof(*max98363), GFP_KERNEL); |
395 | if (!max98363) |
396 | return -ENOMEM; |
397 | |
398 | dev_set_drvdata(dev, data: max98363); |
399 | max98363->regmap = regmap; |
400 | max98363->slave = slave; |
401 | |
402 | regcache_cache_only(map: max98363->regmap, enable: true); |
403 | |
404 | max98363->hw_init = false; |
405 | max98363->first_hw_init = false; |
406 | |
407 | /* codec registration */ |
408 | ret = devm_snd_soc_register_component(dev, component_driver: &soc_codec_dev_max98363, |
409 | dai_drv: max98363_dai, |
410 | ARRAY_SIZE(max98363_dai)); |
411 | if (ret < 0) { |
412 | dev_err(dev, "Failed to register codec: %d\n" , ret); |
413 | return ret; |
414 | } |
415 | |
416 | /* set autosuspend parameters */ |
417 | pm_runtime_set_autosuspend_delay(dev, delay: 3000); |
418 | pm_runtime_use_autosuspend(dev); |
419 | |
420 | /* make sure the device does not suspend immediately */ |
421 | pm_runtime_mark_last_busy(dev); |
422 | |
423 | pm_runtime_enable(dev); |
424 | |
425 | /* important note: the device is NOT tagged as 'active' and will remain |
426 | * 'suspended' until the hardware is enumerated/initialized. This is required |
427 | * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently |
428 | * fail with -EACCESS because of race conditions between card creation and enumeration |
429 | */ |
430 | return 0; |
431 | } |
432 | |
433 | static int max98363_sdw_probe(struct sdw_slave *slave, |
434 | const struct sdw_device_id *id) |
435 | { |
436 | struct regmap *regmap; |
437 | |
438 | /* Regmap Initialization */ |
439 | regmap = devm_regmap_init_sdw(slave, &max98363_sdw_regmap); |
440 | if (IS_ERR(ptr: regmap)) |
441 | return PTR_ERR(ptr: regmap); |
442 | |
443 | return max98363_init(slave, regmap); |
444 | } |
445 | |
446 | static const struct sdw_device_id max98363_id[] = { |
447 | SDW_SLAVE_ENTRY(0x019F, 0x8363, 0), |
448 | {}, |
449 | }; |
450 | MODULE_DEVICE_TABLE(sdw, max98363_id); |
451 | |
452 | static struct sdw_driver max98363_sdw_driver = { |
453 | .driver = { |
454 | .name = "max98363" , |
455 | .pm = pm_ptr(&max98363_pm), |
456 | }, |
457 | .probe = max98363_sdw_probe, |
458 | .ops = &max98363_slave_ops, |
459 | .id_table = max98363_id, |
460 | }; |
461 | |
462 | module_sdw_driver(max98363_sdw_driver); |
463 | |
464 | MODULE_DESCRIPTION("ASoC MAX98363 driver SDW" ); |
465 | MODULE_AUTHOR("Ryan Lee <ryans.lee@analog.com>" ); |
466 | MODULE_LICENSE("GPL" ); |
467 | |