xref: /linux/sound/soc/sdca/sdca_class.c (revision d34a818a331f7e270fa9dc3db3d96f6a0d4fa7ab)
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/device.h>
11 #include <linux/err.h>
12 #include <linux/module.h>
13 #include <linux/pm.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/regmap.h>
16 #include <linux/soundwire/sdw.h>
17 #include <linux/soundwire/sdw_registers.h>
18 #include <linux/soundwire/sdw_type.h>
19 #include <sound/sdca.h>
20 #include <sound/sdca_function.h>
21 #include <sound/sdca_interrupts.h>
22 #include <sound/sdca_regmap.h>
23 #include <sound/sdca_class.h>
24 
25 #define CLASS_SDW_ATTACH_TIMEOUT_MS	5000
26 
27 static int class_read_prop(struct sdw_slave *sdw)
28 {
29 	struct sdw_slave_prop *prop = &sdw->prop;
30 	int ret;
31 
32 	ret = sdw_slave_read_prop(sdw);
33 	if (ret)
34 		return ret;
35 
36 	prop->use_domain_irq = true;
37 	prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY |
38 			      SDW_SCP_INT1_IMPL_DEF;
39 
40 	return 0;
41 }
42 
43 static const struct sdw_slave_ops class_sdw_ops = {
44 	.read_prop	= class_read_prop,
45 };
46 
47 static void class_regmap_lock(void *data)
48 {
49 	struct mutex *lock = data;
50 
51 	mutex_lock(lock);
52 }
53 
54 static void class_regmap_unlock(void *data)
55 {
56 	struct mutex *lock = data;
57 
58 	mutex_unlock(lock);
59 }
60 
61 static bool class_dev_regmap_volatile(struct device *dev, unsigned int reg)
62 {
63 	switch (reg) {
64 	case SDW_SCP_SDCA_INTMASK1 ... SDW_SCP_SDCA_INTMASK4:
65 		return false;
66 	default:
67 		return true;
68 	}
69 }
70 
71 static bool class_dev_regmap_precious(struct device *dev, unsigned int reg)
72 {
73 	switch (reg) {
74 	case SDW_SCP_SDCA_INT1 ... SDW_SCP_SDCA_INT4:
75 	case SDW_SCP_SDCA_INTMASK1 ... SDW_SCP_SDCA_INTMASK4:
76 		return false;
77 	default:
78 		return true;
79 	}
80 }
81 
82 static const struct regmap_config class_dev_regmap_config = {
83 	.name			= "sdca-device",
84 	.reg_bits		= 32,
85 	.val_bits		= 8,
86 
87 	.max_register		= SDW_SDCA_MAX_REGISTER,
88 	.volatile_reg		= class_dev_regmap_volatile,
89 	.precious_reg		= class_dev_regmap_precious,
90 
91 	.cache_type		= REGCACHE_MAPLE,
92 
93 	.lock			= class_regmap_lock,
94 	.unlock			= class_regmap_unlock,
95 };
96 
97 static void class_remove_functions(void *data)
98 {
99 	struct sdca_class_drv *drv = data;
100 
101 	sdca_dev_unregister_functions(drv->sdw);
102 }
103 
104 static void class_boot_work(struct work_struct *work)
105 {
106 	struct sdca_class_drv *drv = container_of(work,
107 						  struct sdca_class_drv,
108 						  boot_work);
109 	int ret;
110 
111 	ret = sdw_slave_wait_for_init(drv->sdw, CLASS_SDW_ATTACH_TIMEOUT_MS);
112 	if (ret)
113 		goto err;
114 
115 	regcache_cache_only(drv->dev_regmap, false);
116 
117 	drv->irq_info = devm_sdca_irq_allocate(drv->dev, drv->dev_regmap,
118 					       drv->sdw->irq);
119 	if (IS_ERR(drv->irq_info))
120 		goto err;
121 
122 	ret = sdca_dev_register_functions(drv->sdw);
123 	if (ret)
124 		goto err;
125 
126 	/* Ensure function drivers are removed before the IRQ is destroyed */
127 	ret = devm_add_action_or_reset(drv->dev, class_remove_functions, drv);
128 	if (ret)
129 		goto err;
130 
131 	dev_dbg(drv->dev, "boot work complete\n");
132 
133 	pm_runtime_mark_last_busy(drv->dev);
134 	pm_runtime_put_autosuspend(drv->dev);
135 
136 	return;
137 
138 err:
139 	pm_runtime_put_sync(drv->dev);
140 }
141 
142 /**
143  * sdca_class_probe - SDCA class SoundWire slave probe helper
144  * @sdw: SoundWire slave
145  * @drv: caller-allocated sdca_class_drv storage.  The caller (a codec
146  *       driver, or the built-in class_sdw_driver in this file) owns the
147  *       allocation and sets its own dev_set_drvdata() -- the framework
148  *       does not touch drvdata.  Typically embedded in the codec's own
149  *       priv struct so codec drivers can keep per-slave state.
150  * @ops: optional codec-provided class callbacks (may be NULL for
151  *       pure-generic SDCA parts that need no quirks)
152  *
153  * Codec-specific SoundWire drivers call this from their .probe after
154  * allocating a struct sdca_class_drv (usually embedded in their own
155  * priv) and setting drvdata to their priv.  The framework fills in the
156  * sdca_class_drv fields, sets up the class regmap, and queues the
157  * deferred boot work.
158  */
159 int sdca_class_probe(struct sdw_slave *sdw,
160 		     struct sdca_class_drv *drv,
161 		     const struct sdca_class_ops *ops)
162 {
163 	struct device *dev = &sdw->dev;
164 	struct regmap_config *dev_config;
165 	int ret;
166 
167 	sdca_lookup_swft(sdw);
168 
169 	if (!drv)
170 		return -EINVAL;
171 
172 	dev_config = devm_kmemdup(dev, &class_dev_regmap_config,
173 				  sizeof(*dev_config), GFP_KERNEL);
174 	if (!dev_config)
175 		return -ENOMEM;
176 
177 	drv->dev = dev;
178 	drv->sdw = sdw;
179 	drv->ops = ops;
180 	mutex_init(&drv->regmap_lock);
181 	mutex_init(&drv->init_lock);
182 
183 	INIT_WORK(&drv->boot_work, class_boot_work);
184 
185 	dev_config->lock_arg = &drv->regmap_lock;
186 
187 	drv->dev_regmap = devm_regmap_init_sdw(sdw, dev_config);
188 	if (IS_ERR(drv->dev_regmap))
189 		return dev_err_probe(drv->dev, PTR_ERR(drv->dev_regmap),
190 				     "failed to create device regmap\n");
191 
192 	regcache_cache_only(drv->dev_regmap, true);
193 
194 	pm_runtime_set_autosuspend_delay(dev, 250);
195 	pm_runtime_use_autosuspend(dev);
196 	pm_runtime_set_active(dev);
197 	pm_runtime_get_noresume(dev);
198 
199 	ret = devm_pm_runtime_enable(dev);
200 	if (ret) {
201 		pm_runtime_put_sync(dev);
202 		return ret;
203 	}
204 
205 	queue_work(system_long_wq, &drv->boot_work);
206 
207 	return 0;
208 }
209 EXPORT_SYMBOL_NS_GPL(sdca_class_probe, "SND_SOC_SDCA_CLASS");
210 
211 static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id)
212 {
213 	struct sdca_class_drv *drv;
214 
215 	/*
216 	 * Pure-generic SDCA parts: no codec priv to embed, so allocate a
217 	 * bare sdca_class_drv here and stash it in drvdata for the
218 	 * built-in PM ops to fetch.
219 	 */
220 	drv = devm_kzalloc(&sdw->dev, sizeof(*drv), GFP_KERNEL);
221 	if (!drv)
222 		return -ENOMEM;
223 
224 	dev_set_drvdata(&sdw->dev, drv);
225 
226 	return sdca_class_probe(sdw, drv, NULL);
227 }
228 
229 /**
230  * sdca_class_remove - SDCA class SoundWire slave remove helper
231  * @drv: caller-owned sdca_class_drv (the one handed to sdca_class_probe()).
232  *
233  * Cancels the deferred boot work so devres can safely free @drv and the
234  * embedding codec priv without racing class_boot_work.  Codec-specific
235  * SoundWire drivers that call sdca_class_probe() must call this from
236  * their .remove with the same drv pointer they passed to probe.
237  */
238 void sdca_class_remove(struct sdca_class_drv *drv)
239 {
240 	cancel_work_sync(&drv->boot_work);
241 }
242 EXPORT_SYMBOL_NS_GPL(sdca_class_remove, "SND_SOC_SDCA_CLASS");
243 
244 static void class_sdw_remove(struct sdw_slave *sdw)
245 {
246 	struct sdca_class_drv *drv = dev_get_drvdata(&sdw->dev);
247 
248 	sdca_class_remove(drv);
249 }
250 
251 /**
252  * sdca_class_system_suspend - SDCA class system suspend helper
253  * @drv: caller-owned sdca_class_drv.
254  *
255  * Codec drivers compose this into their own dev_pm_ops.  Disables the
256  * SoundWire interrupt and forces runtime suspend of the underlying
257  * class regmap.
258  */
259 int sdca_class_system_suspend(struct sdca_class_drv *drv)
260 {
261 	int ret;
262 
263 	disable_irq(drv->sdw->irq);
264 
265 	ret = pm_runtime_force_suspend(drv->dev);
266 	if (ret) {
267 		dev_err(drv->dev, "failed to force suspend: %d\n", ret);
268 		enable_irq(drv->sdw->irq);
269 		return ret;
270 	}
271 
272 	return 0;
273 }
274 EXPORT_SYMBOL_NS_GPL(sdca_class_system_suspend, "SND_SOC_SDCA_CLASS");
275 
276 /**
277  * sdca_class_system_resume - SDCA class system resume helper
278  * @drv: caller-owned sdca_class_drv.
279  */
280 int sdca_class_system_resume(struct sdca_class_drv *drv)
281 {
282 	int ret;
283 
284 	ret = pm_runtime_force_resume(drv->dev);
285 	if (ret) {
286 		dev_err(drv->dev, "failed to force resume: %d\n", ret);
287 		return ret;
288 	}
289 
290 	enable_irq(drv->sdw->irq);
291 
292 	return 0;
293 }
294 EXPORT_SYMBOL_NS_GPL(sdca_class_system_resume, "SND_SOC_SDCA_CLASS");
295 
296 /**
297  * sdca_class_runtime_suspend - SDCA class runtime suspend helper
298  * @drv: caller-owned sdca_class_drv.
299  */
300 int sdca_class_runtime_suspend(struct sdca_class_drv *drv)
301 {
302 	/*
303 	 * Whilst the driver doesn't power the chip down here, going into runtime
304 	 * suspend lets the SoundWire bus power down, which means the driver
305 	 * can't communicate with the device any more.
306 	 */
307 	regcache_cache_only(drv->dev_regmap, true);
308 
309 	return 0;
310 }
311 EXPORT_SYMBOL_NS_GPL(sdca_class_runtime_suspend, "SND_SOC_SDCA_CLASS");
312 
313 /**
314  * sdca_class_runtime_resume - SDCA class runtime resume helper
315  * @drv: caller-owned sdca_class_drv.
316  */
317 int sdca_class_runtime_resume(struct sdca_class_drv *drv)
318 {
319 	int ret;
320 
321 	ret = sdw_slave_wait_for_init(drv->sdw, CLASS_SDW_ATTACH_TIMEOUT_MS);
322 	if (ret)
323 		goto err;
324 
325 	regcache_cache_only(drv->dev_regmap, false);
326 	regcache_mark_dirty(drv->dev_regmap);
327 
328 	ret = regcache_sync(drv->dev_regmap);
329 	if (ret) {
330 		dev_err(drv->dev, "failed to restore cache: %d\n", ret);
331 		goto err;
332 	}
333 
334 	return 0;
335 
336 err:
337 	regcache_cache_only(drv->dev_regmap, true);
338 
339 	return ret;
340 }
341 EXPORT_SYMBOL_NS_GPL(sdca_class_runtime_resume, "SND_SOC_SDCA_CLASS");
342 
343 /*
344  * Convenience dev_pm_ops used by the built-in class_sdw_driver, which
345  * stashes its sdca_class_drv in drvdata directly.  Codec drivers that
346  * embed sdca_class_drv in their own priv compose their own dev_pm_ops
347  * using the sdca_class_*_suspend/resume helpers above.
348  */
349 static int class_pm_system_suspend(struct device *dev)
350 {
351 	return sdca_class_system_suspend(dev_get_drvdata(dev));
352 }
353 
354 static int class_pm_system_resume(struct device *dev)
355 {
356 	return sdca_class_system_resume(dev_get_drvdata(dev));
357 }
358 
359 static int class_pm_runtime_suspend(struct device *dev)
360 {
361 	return sdca_class_runtime_suspend(dev_get_drvdata(dev));
362 }
363 
364 static int class_pm_runtime_resume(struct device *dev)
365 {
366 	return sdca_class_runtime_resume(dev_get_drvdata(dev));
367 }
368 
369 static const struct dev_pm_ops sdca_class_pm_ops = {
370 	SYSTEM_SLEEP_PM_OPS(class_pm_system_suspend, class_pm_system_resume)
371 	RUNTIME_PM_OPS(class_pm_runtime_suspend, class_pm_runtime_resume, NULL)
372 };
373 
374 static const struct sdw_device_id class_sdw_id[] = {
375 	SDW_SLAVE_ENTRY(0x01FA, 0x4245, 0),
376 	SDW_SLAVE_ENTRY(0x01FA, 0x4249, 0),
377 	SDW_SLAVE_ENTRY(0x01FA, 0x4747, 0),
378 	{}
379 };
380 MODULE_DEVICE_TABLE(sdw, class_sdw_id);
381 
382 static struct sdw_driver class_sdw_driver = {
383 	.driver = {
384 		.name		= "sdca_class",
385 		.pm		= pm_ptr(&sdca_class_pm_ops),
386 	},
387 
388 	.probe		= class_sdw_probe,
389 	.remove		= class_sdw_remove,
390 	.id_table	= class_sdw_id,
391 	.ops		= &class_sdw_ops,
392 };
393 module_sdw_driver(class_sdw_driver);
394 
395 MODULE_LICENSE("GPL");
396 MODULE_DESCRIPTION("SDCA Class Driver");
397 MODULE_IMPORT_NS("SND_SOC_SDCA");
398