xref: /linux/sound/soc/sdca/sdca_class_function.c (revision 7a5214f769c7c953c58971027a762f2e191057d4)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2025 Cirrus Logic, Inc. and
3 //                    Cirrus Logic International Semiconductor Ltd.
4 
5 /*
6  * The MIPI SDCA specification is available for public downloads at
7  * https://www.mipi.org/mipi-sdca-v1-0-download
8  */
9 
10 #include <linux/auxiliary_bus.h>
11 #include <linux/minmax.h>
12 #include <linux/module.h>
13 #include <linux/pm.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/soundwire/sdw.h>
16 #include <linux/soundwire/sdw_registers.h>
17 #include <sound/pcm.h>
18 #include <sound/sdca_asoc.h>
19 #include <sound/sdca_fdl.h>
20 #include <sound/sdca_function.h>
21 #include <sound/sdca_interrupts.h>
22 #include <sound/sdca_jack.h>
23 #include <sound/sdca_regmap.h>
24 #include <sound/sdw.h>
25 #include <sound/soc-component.h>
26 #include <sound/soc-dai.h>
27 #include <sound/soc.h>
28 #include "sdca_class.h"
29 
30 struct class_function_drv {
31 	struct device *dev;
32 	struct regmap *regmap;
33 	struct sdca_class_drv *core;
34 
35 	struct sdca_function_data *function;
36 	bool suspended;
37 };
38 
39 static void class_function_regmap_lock(void *data)
40 {
41 	struct mutex *lock = data;
42 
43 	mutex_lock(lock);
44 }
45 
46 static void class_function_regmap_unlock(void *data)
47 {
48 	struct mutex *lock = data;
49 
50 	mutex_unlock(lock);
51 }
52 
53 static bool class_function_regmap_writeable(struct device *dev, unsigned int reg)
54 {
55 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
56 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
57 
58 	return sdca_regmap_writeable(drv->function, reg);
59 }
60 
61 static bool class_function_regmap_readable(struct device *dev, unsigned int reg)
62 {
63 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
64 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
65 
66 	return sdca_regmap_readable(drv->function, reg);
67 }
68 
69 static bool class_function_regmap_volatile(struct device *dev, unsigned int reg)
70 {
71 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
72 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
73 
74 	return sdca_regmap_volatile(drv->function, reg);
75 }
76 
77 static const struct regmap_config class_function_regmap_config = {
78 	.name			= "sdca",
79 	.reg_bits		= 32,
80 	.val_bits		= 32,
81 	.reg_format_endian	= REGMAP_ENDIAN_LITTLE,
82 	.val_format_endian	= REGMAP_ENDIAN_LITTLE,
83 
84 	.max_register		= SDW_SDCA_MAX_REGISTER,
85 	.readable_reg		= class_function_regmap_readable,
86 	.writeable_reg		= class_function_regmap_writeable,
87 	.volatile_reg		= class_function_regmap_volatile,
88 
89 	.cache_type		= REGCACHE_MAPLE,
90 
91 	.lock			= class_function_regmap_lock,
92 	.unlock			= class_function_regmap_unlock,
93 };
94 
95 static int class_function_regmap_mbq_size(struct device *dev, unsigned int reg)
96 {
97 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
98 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
99 
100 	return sdca_regmap_mbq_size(drv->function, reg);
101 }
102 
103 static bool class_function_regmap_deferrable(struct device *dev, unsigned int reg)
104 {
105 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
106 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
107 
108 	return sdca_regmap_deferrable(drv->function, reg);
109 }
110 
111 static const struct regmap_sdw_mbq_cfg class_function_mbq_config = {
112 	.mbq_size		= class_function_regmap_mbq_size,
113 	.deferrable		= class_function_regmap_deferrable,
114 	.retry_us		= 1000,
115 	.timeout_us		= 10000,
116 };
117 
118 static int class_function_startup(struct snd_pcm_substream *substream,
119 				  struct snd_soc_dai *dai)
120 {
121 	struct class_function_drv *drv = snd_soc_component_get_drvdata(dai->component);
122 
123 	return sdca_asoc_set_constraints(drv->dev, drv->regmap, drv->function,
124 					 substream, dai);
125 }
126 
127 static int class_function_sdw_add_peripheral(struct snd_pcm_substream *substream,
128 					     struct snd_pcm_hw_params *params,
129 					     struct snd_soc_dai *dai)
130 {
131 	struct class_function_drv *drv = snd_soc_component_get_drvdata(dai->component);
132 	struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
133 	struct sdw_slave *sdw = dev_to_sdw_dev(drv->dev->parent);
134 	struct sdw_stream_config sconfig = {0};
135 	struct sdw_port_config pconfig = {0};
136 	int ret;
137 
138 	if (!sdw_stream)
139 		return -EINVAL;
140 
141 	snd_sdw_params_to_config(substream, params, &sconfig, &pconfig);
142 
143 	/*
144 	 * FIXME: As also noted in sdca_asoc_get_port(), currently only
145 	 * a single unshared port is supported for each DAI.
146 	 */
147 	ret = sdca_asoc_get_port(drv->dev, drv->regmap, drv->function, dai);
148 	if (ret < 0)
149 		return ret;
150 
151 	pconfig.num = ret;
152 
153 	ret = sdw_stream_add_slave(sdw, &sconfig, &pconfig, 1, sdw_stream);
154 	if (ret) {
155 		dev_err(drv->dev, "failed to add sdw stream: %d\n", ret);
156 		return ret;
157 	}
158 
159 	return sdca_asoc_hw_params(drv->dev, drv->regmap, drv->function,
160 				   substream, params, dai);
161 }
162 
163 static int class_function_sdw_remove_peripheral(struct snd_pcm_substream *substream,
164 						struct snd_soc_dai *dai)
165 {
166 	struct class_function_drv *drv = snd_soc_component_get_drvdata(dai->component);
167 	struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
168 	struct sdw_slave *sdw = dev_to_sdw_dev(drv->dev->parent);
169 
170 	if (!sdw_stream)
171 		return -EINVAL;
172 
173 	return sdw_stream_remove_slave(sdw, sdw_stream);
174 }
175 
176 static int class_function_sdw_set_stream(struct snd_soc_dai *dai, void *sdw_stream,
177 					 int direction)
178 {
179 	snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
180 
181 	return 0;
182 }
183 
184 static const struct snd_soc_dai_ops class_function_sdw_ops = {
185 	.startup	= class_function_startup,
186 	.shutdown	= sdca_asoc_free_constraints,
187 	.set_stream	= class_function_sdw_set_stream,
188 	.hw_params	= class_function_sdw_add_peripheral,
189 	.hw_free	= class_function_sdw_remove_peripheral,
190 };
191 
192 static int class_function_component_probe(struct snd_soc_component *component)
193 {
194 	struct class_function_drv *drv = snd_soc_component_get_drvdata(component);
195 	struct sdca_class_drv *core = drv->core;
196 
197 	return sdca_irq_populate(drv->function, component, core->irq_info);
198 }
199 
200 static int class_function_set_jack(struct snd_soc_component *component,
201 				   struct snd_soc_jack *jack, void *d)
202 {
203 	struct class_function_drv *drv = snd_soc_component_get_drvdata(component);
204 	struct sdca_class_drv *core = drv->core;
205 
206 	return sdca_jack_set_jack(core->irq_info, jack);
207 }
208 
209 static const struct snd_soc_component_driver class_function_component_drv = {
210 	.probe			= class_function_component_probe,
211 	.endianness		= 1,
212 };
213 
214 static int class_function_boot(struct class_function_drv *drv)
215 {
216 	unsigned int reg = SDW_SDCA_CTL(drv->function->desc->adr,
217 					SDCA_ENTITY_TYPE_ENTITY_0,
218 					SDCA_CTL_ENTITY_0_FUNCTION_STATUS, 0);
219 	unsigned int val;
220 	int ret;
221 
222 	ret = regmap_read(drv->regmap, reg, &val);
223 	if (ret < 0) {
224 		dev_err(drv->dev, "failed to read function status: %d\n", ret);
225 		return ret;
226 	}
227 
228 	if (!(val & SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET)) {
229 		dev_dbg(drv->dev, "reset function device\n");
230 
231 		ret = sdca_reset_function(drv->dev, drv->function, drv->regmap);
232 		if (ret)
233 			return ret;
234 	}
235 
236 	if (val & SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION) {
237 		dev_dbg(drv->dev, "write initialisation\n");
238 
239 		ret = sdca_regmap_write_init(drv->dev, drv->core->dev_regmap,
240 					     drv->function);
241 		if (ret)
242 			return ret;
243 
244 		ret = regmap_write(drv->regmap, reg,
245 				   SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION);
246 		if (ret < 0) {
247 			dev_err(drv->dev,
248 				"failed to clear function init status: %d\n",
249 				ret);
250 			return ret;
251 		}
252 	}
253 
254 	/* Start FDL process */
255 	ret = sdca_irq_populate_early(drv->dev, drv->regmap, drv->function,
256 				      drv->core->irq_info);
257 	if (ret)
258 		return ret;
259 
260 	ret = sdca_fdl_sync(drv->dev, drv->function, drv->core->irq_info);
261 	if (ret)
262 		return ret;
263 
264 	ret = sdca_regmap_write_defaults(drv->dev, drv->regmap, drv->function);
265 	if (ret)
266 		return ret;
267 
268 	ret = regmap_write(drv->regmap, reg, 0xFF);
269 	if (ret < 0) {
270 		dev_err(drv->dev, "failed to clear function status: %d\n", ret);
271 		return ret;
272 	}
273 
274 	return 0;
275 }
276 
277 static int class_function_probe(struct auxiliary_device *auxdev,
278 				const struct auxiliary_device_id *aux_dev_id)
279 {
280 	struct device *dev = &auxdev->dev;
281 	struct sdca_class_drv *core = dev_get_drvdata(dev->parent);
282 	struct sdca_device_data *data = &core->sdw->sdca_data;
283 	struct sdca_function_desc *desc;
284 	struct snd_soc_component_driver *cmp_drv;
285 	struct snd_soc_dai_driver *dais;
286 	struct class_function_drv *drv;
287 	struct regmap_sdw_mbq_cfg *mbq_config;
288 	struct regmap_config *config;
289 	struct reg_default *defaults;
290 	int ndefaults;
291 	int num_dais;
292 	int ret;
293 	int i;
294 
295 	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
296 	if (!drv)
297 		return -ENOMEM;
298 
299 	cmp_drv = devm_kmemdup(dev, &class_function_component_drv, sizeof(*cmp_drv),
300 			       GFP_KERNEL);
301 	if (!cmp_drv)
302 		return -ENOMEM;
303 
304 	config = devm_kmemdup(dev, &class_function_regmap_config, sizeof(*config),
305 			      GFP_KERNEL);
306 	if (!config)
307 		return -ENOMEM;
308 
309 	mbq_config = devm_kmemdup(dev, &class_function_mbq_config, sizeof(*mbq_config),
310 				  GFP_KERNEL);
311 	if (!mbq_config)
312 		return -ENOMEM;
313 
314 	drv->dev = dev;
315 	drv->core = core;
316 
317 	for (i = 0; i < data->num_functions; i++) {
318 		desc = &data->function[i];
319 
320 		if (desc->type == aux_dev_id->driver_data)
321 			break;
322 	}
323 	if (i == core->sdw->sdca_data.num_functions) {
324 		dev_err(dev, "failed to locate function\n");
325 		return -EINVAL;
326 	}
327 
328 	drv->function = &core->functions[i];
329 
330 	ret = sdca_parse_function(dev, core->sdw, desc, drv->function);
331 	if (ret)
332 		return ret;
333 
334 	ndefaults = sdca_regmap_count_constants(dev, drv->function);
335 	if (ndefaults < 0)
336 		return ndefaults;
337 
338 	defaults = devm_kcalloc(dev, ndefaults, sizeof(*defaults), GFP_KERNEL);
339 	if (!defaults)
340 		return -ENOMEM;
341 
342 	ret = sdca_regmap_populate_constants(dev, drv->function, defaults);
343 	if (ret < 0)
344 		return ret;
345 
346 	regcache_sort_defaults(defaults, ndefaults);
347 
348 	auxiliary_set_drvdata(auxdev, drv);
349 
350 	config->reg_defaults = defaults;
351 	config->num_reg_defaults = ndefaults;
352 	config->lock_arg = &core->regmap_lock;
353 
354 	if (drv->function->busy_max_delay) {
355 		mbq_config->timeout_us = drv->function->busy_max_delay;
356 		mbq_config->retry_us = umax(drv->function->busy_max_delay / 10,
357 					    mbq_config->retry_us);
358 	}
359 
360 	drv->regmap = devm_regmap_init_sdw_mbq_cfg(dev, core->sdw, config, mbq_config);
361 	if (IS_ERR(drv->regmap))
362 		return dev_err_probe(dev, PTR_ERR(drv->regmap),
363 				     "failed to create regmap");
364 
365 	if (desc->type == SDCA_FUNCTION_TYPE_UAJ)
366 		cmp_drv->set_jack = class_function_set_jack;
367 
368 	ret = sdca_asoc_populate_component(dev, drv->function, cmp_drv,
369 					   &dais, &num_dais,
370 					   &class_function_sdw_ops);
371 	if (ret)
372 		return ret;
373 
374 	pm_runtime_set_autosuspend_delay(dev, 200);
375 	pm_runtime_use_autosuspend(dev);
376 	pm_runtime_set_active(dev);
377 	pm_runtime_get_noresume(dev);
378 
379 	ret = devm_pm_runtime_enable(dev);
380 	if (ret)
381 		return ret;
382 
383 	ret = class_function_boot(drv);
384 	if (ret)
385 		return ret;
386 
387 	ret = devm_snd_soc_register_component(dev, cmp_drv, dais, num_dais);
388 	if (ret)
389 		return dev_err_probe(dev, ret, "failed to register component\n");
390 
391 	pm_runtime_mark_last_busy(dev);
392 	pm_runtime_put_autosuspend(dev);
393 
394 	return 0;
395 }
396 
397 static int class_function_runtime_suspend(struct device *dev)
398 {
399 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
400 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
401 
402 	/*
403 	 * Whilst the driver doesn't power the chip down here, going into
404 	 * runtime suspend means the driver can't be sure the bus won't
405 	 * power down which would prevent communication with the device.
406 	 */
407 	regcache_cache_only(drv->regmap, true);
408 
409 	return 0;
410 }
411 
412 static int class_function_runtime_resume(struct device *dev)
413 {
414 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
415 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
416 	int ret;
417 
418 	regcache_mark_dirty(drv->regmap);
419 	regcache_cache_only(drv->regmap, false);
420 
421 	if (drv->suspended) {
422 		sdca_irq_enable_early(drv->function, drv->core->irq_info);
423 		/* TODO: Add FDL process between early and late IRQs */
424 		sdca_irq_enable(drv->function, drv->core->irq_info);
425 
426 		drv->suspended = false;
427 	}
428 
429 	ret = regcache_sync(drv->regmap);
430 	if (ret) {
431 		dev_err(drv->dev, "failed to restore register cache: %d\n", ret);
432 		goto err;
433 	}
434 
435 	return 0;
436 
437 err:
438 	regcache_cache_only(drv->regmap, true);
439 
440 	return ret;
441 }
442 
443 static int class_function_suspend(struct device *dev)
444 {
445 	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
446 	struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
447 	int ret;
448 
449 	drv->suspended = true;
450 
451 	/* Ensure runtime resume runs on resume */
452 	ret = pm_runtime_resume_and_get(dev);
453 	if (ret) {
454 		dev_err(dev, "failed to resume for suspend: %d\n", ret);
455 		return ret;
456 	}
457 
458 	sdca_irq_disable(drv->function, drv->core->irq_info);
459 
460 	ret = pm_runtime_force_suspend(dev);
461 	if (ret) {
462 		dev_err(dev, "failed to force suspend: %d\n", ret);
463 		return ret;
464 	}
465 
466 	pm_runtime_put_noidle(dev);
467 
468 	return 0;
469 }
470 
471 static int class_function_resume(struct device *dev)
472 {
473 	int ret;
474 
475 	ret = pm_runtime_force_resume(dev);
476 	if (ret) {
477 		dev_err(dev, "failed to force resume: %d\n", ret);
478 		return ret;
479 	}
480 
481 	return 0;
482 }
483 
484 static const struct dev_pm_ops class_function_pm_ops = {
485 	SYSTEM_SLEEP_PM_OPS(class_function_suspend, class_function_resume)
486 	RUNTIME_PM_OPS(class_function_runtime_suspend,
487 		       class_function_runtime_resume, NULL)
488 };
489 
490 static const struct auxiliary_device_id class_function_id_table[] = {
491 	{
492 		.name = "snd_soc_sdca." SDCA_FUNCTION_TYPE_SMART_AMP_NAME,
493 		.driver_data = SDCA_FUNCTION_TYPE_SMART_AMP,
494 	},
495 	{
496 		.name = "snd_soc_sdca." SDCA_FUNCTION_TYPE_SMART_MIC_NAME,
497 		.driver_data = SDCA_FUNCTION_TYPE_SMART_MIC,
498 	},
499 	{
500 		.name = "snd_soc_sdca." SDCA_FUNCTION_TYPE_UAJ_NAME,
501 		.driver_data = SDCA_FUNCTION_TYPE_UAJ,
502 	},
503 	{
504 		.name = "snd_soc_sdca." SDCA_FUNCTION_TYPE_HID_NAME,
505 		.driver_data = SDCA_FUNCTION_TYPE_HID,
506 	},
507 	{},
508 };
509 MODULE_DEVICE_TABLE(auxiliary, class_function_id_table);
510 
511 static struct auxiliary_driver class_function_drv = {
512 	.driver = {
513 		.name		= "sdca_function",
514 		.pm		= pm_ptr(&class_function_pm_ops),
515 	},
516 
517 	.probe		= class_function_probe,
518 	.id_table	= class_function_id_table
519 };
520 module_auxiliary_driver(class_function_drv);
521 
522 MODULE_LICENSE("GPL");
523 MODULE_DESCRIPTION("SDCA Class Function Driver");
524 MODULE_IMPORT_NS("SND_SOC_SDCA");
525