xref: /linux/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c (revision 307797159ac25fe5a2048bf5c6a5718298edca57)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2011 Broadcom Corporation.  All rights reserved. */
3 
4 #include <linux/platform_device.h>
5 
6 #include <linux/init.h>
7 #include <linux/slab.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 
11 #include "bcm2835.h"
12 
13 static bool enable_hdmi;
14 static bool enable_headphones;
15 static bool enable_compat_alsa = true;
16 
17 module_param(enable_hdmi, bool, 0444);
18 MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device");
19 module_param(enable_headphones, bool, 0444);
20 MODULE_PARM_DESC(enable_headphones, "Enables Headphones virtual audio device");
21 module_param(enable_compat_alsa, bool, 0444);
22 MODULE_PARM_DESC(enable_compat_alsa,
23 		 "Enables ALSA compatibility virtual audio device");
24 
25 static void snd_devm_unregister_child(struct device *dev, void *res)
26 {
27 	struct device *childdev = *(struct device **)res;
28 	struct bcm2835_chip *chip = dev_get_drvdata(childdev);
29 	struct snd_card *card = chip->card;
30 
31 	snd_card_free(card);
32 
33 	device_unregister(childdev);
34 }
35 
36 static int snd_devm_add_child(struct device *dev, struct device *child)
37 {
38 	struct device **dr;
39 	int ret;
40 
41 	dr = devres_alloc(snd_devm_unregister_child, sizeof(*dr), GFP_KERNEL);
42 	if (!dr)
43 		return -ENOMEM;
44 
45 	ret = device_add(child);
46 	if (ret) {
47 		devres_free(dr);
48 		return ret;
49 	}
50 
51 	*dr = child;
52 	devres_add(dev, dr);
53 
54 	return 0;
55 }
56 
57 static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
58 {
59 	struct bcm2835_vchi_ctx *vchi_ctx = res;
60 
61 	bcm2835_free_vchi_ctx(vchi_ctx);
62 }
63 
64 static int bcm2835_devm_add_vchi_ctx(struct device *dev)
65 {
66 	struct bcm2835_vchi_ctx *vchi_ctx;
67 	int ret;
68 
69 	vchi_ctx = devres_alloc(bcm2835_devm_free_vchi_ctx, sizeof(*vchi_ctx),
70 				GFP_KERNEL);
71 	if (!vchi_ctx)
72 		return -ENOMEM;
73 
74 	memset(vchi_ctx, 0, sizeof(*vchi_ctx));
75 
76 	ret = bcm2835_new_vchi_ctx(vchi_ctx);
77 	if (ret) {
78 		devres_free(vchi_ctx);
79 		return ret;
80 	}
81 
82 	devres_add(dev, vchi_ctx);
83 
84 	return 0;
85 }
86 
87 static void snd_bcm2835_release(struct device *dev)
88 {
89 	struct bcm2835_chip *chip = dev_get_drvdata(dev);
90 
91 	kfree(chip);
92 }
93 
94 static struct device *
95 snd_create_device(struct device *parent,
96 		  struct device_driver *driver,
97 		  const char *name)
98 {
99 	struct device *device;
100 	int ret;
101 
102 	device = devm_kzalloc(parent, sizeof(*device), GFP_KERNEL);
103 	if (!device)
104 		return ERR_PTR(-ENOMEM);
105 
106 	device_initialize(device);
107 	device->parent = parent;
108 	device->driver = driver;
109 	device->release = snd_bcm2835_release;
110 
111 	dev_set_name(device, "%s", name);
112 
113 	ret = snd_devm_add_child(parent, device);
114 	if (ret)
115 		return ERR_PTR(ret);
116 
117 	return device;
118 }
119 
120 /* component-destructor
121  * (see "Management of Cards and Components")
122  */
123 static int snd_bcm2835_dev_free(struct snd_device *device)
124 {
125 	struct bcm2835_chip *chip = device->device_data;
126 	struct snd_card *card = chip->card;
127 
128 	snd_device_free(card, chip);
129 
130 	return 0;
131 }
132 
133 /* chip-specific constructor
134  * (see "Management of Cards and Components")
135  */
136 static int snd_bcm2835_create(struct snd_card *card,
137 			      struct bcm2835_chip **rchip)
138 {
139 	struct bcm2835_chip *chip;
140 	int err;
141 	static struct snd_device_ops ops = {
142 		.dev_free = snd_bcm2835_dev_free,
143 	};
144 
145 	*rchip = NULL;
146 
147 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
148 	if (!chip)
149 		return -ENOMEM;
150 
151 	chip->card = card;
152 
153 	chip->vchi_ctx = devres_find(card->dev->parent,
154 				     bcm2835_devm_free_vchi_ctx, NULL, NULL);
155 	if (!chip->vchi_ctx) {
156 		kfree(chip);
157 		return -ENODEV;
158 	}
159 
160 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
161 	if (err) {
162 		kfree(chip);
163 		return err;
164 	}
165 
166 	*rchip = chip;
167 	return 0;
168 }
169 
170 static struct snd_card *snd_bcm2835_card_new(struct device *dev)
171 {
172 	struct snd_card *card;
173 	int ret;
174 
175 	ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
176 	if (ret)
177 		return ERR_PTR(ret);
178 
179 	return card;
180 }
181 
182 typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
183 					 const char *name,
184 					 enum snd_bcm2835_route route,
185 					 u32 numchannels);
186 
187 typedef int (*bcm2835_audio_newctl_func)(struct bcm2835_chip *chip);
188 
189 struct bcm2835_audio_driver {
190 	struct device_driver driver;
191 	const char *shortname;
192 	const char *longname;
193 	int minchannels;
194 	bcm2835_audio_newpcm_func newpcm;
195 	bcm2835_audio_newctl_func newctl;
196 	enum snd_bcm2835_route route;
197 };
198 
199 static int bcm2835_audio_alsa_newpcm(struct bcm2835_chip *chip,
200 				     const char *name,
201 				     enum snd_bcm2835_route route,
202 				     u32 numchannels)
203 {
204 	int err;
205 
206 	err = snd_bcm2835_new_pcm(chip, numchannels - 1);
207 	if (err)
208 		return err;
209 
210 	err = snd_bcm2835_new_spdif_pcm(chip);
211 	if (err)
212 		return err;
213 
214 	return 0;
215 }
216 
217 static struct bcm2835_audio_driver bcm2835_audio_alsa = {
218 	.driver = {
219 		.name = "bcm2835_alsa",
220 		.owner = THIS_MODULE,
221 	},
222 	.shortname = "bcm2835 ALSA",
223 	.longname  = "bcm2835 ALSA",
224 	.minchannels = 2,
225 	.newpcm = bcm2835_audio_alsa_newpcm,
226 	.newctl = snd_bcm2835_new_ctl,
227 };
228 
229 static struct bcm2835_audio_driver bcm2835_audio_hdmi = {
230 	.driver = {
231 		.name = "bcm2835_hdmi",
232 		.owner = THIS_MODULE,
233 	},
234 	.shortname = "bcm2835 HDMI",
235 	.longname  = "bcm2835 HDMI",
236 	.minchannels = 1,
237 	.newpcm = snd_bcm2835_new_simple_pcm,
238 	.newctl = snd_bcm2835_new_hdmi_ctl,
239 	.route = AUDIO_DEST_HDMI
240 };
241 
242 static struct bcm2835_audio_driver bcm2835_audio_headphones = {
243 	.driver = {
244 		.name = "bcm2835_headphones",
245 		.owner = THIS_MODULE,
246 	},
247 	.shortname = "bcm2835 Headphones",
248 	.longname  = "bcm2835 Headphones",
249 	.minchannels = 1,
250 	.newpcm = snd_bcm2835_new_simple_pcm,
251 	.newctl = snd_bcm2835_new_headphones_ctl,
252 	.route = AUDIO_DEST_HEADPHONES
253 };
254 
255 struct bcm2835_audio_drivers {
256 	struct bcm2835_audio_driver *audio_driver;
257 	const bool *is_enabled;
258 };
259 
260 static struct bcm2835_audio_drivers children_devices[] = {
261 	{
262 		.audio_driver = &bcm2835_audio_alsa,
263 		.is_enabled = &enable_compat_alsa,
264 	},
265 	{
266 		.audio_driver = &bcm2835_audio_hdmi,
267 		.is_enabled = &enable_hdmi,
268 	},
269 	{
270 		.audio_driver = &bcm2835_audio_headphones,
271 		.is_enabled = &enable_headphones,
272 	},
273 };
274 
275 static int snd_add_child_device(struct device *device,
276 				struct bcm2835_audio_driver *audio_driver,
277 				u32 numchans)
278 {
279 	struct snd_card *card;
280 	struct device *child;
281 	struct bcm2835_chip *chip;
282 	int err, i;
283 
284 	child = snd_create_device(device, &audio_driver->driver,
285 				  audio_driver->driver.name);
286 	if (IS_ERR(child)) {
287 		dev_err(device,
288 			"Unable to create child device %p, error %ld",
289 			audio_driver->driver.name,
290 			PTR_ERR(child));
291 		return PTR_ERR(child);
292 	}
293 
294 	card = snd_bcm2835_card_new(child);
295 	if (IS_ERR(card)) {
296 		dev_err(child, "Failed to create card");
297 		return PTR_ERR(card);
298 	}
299 
300 	snd_card_set_dev(card, child);
301 	strcpy(card->driver, audio_driver->driver.name);
302 	strcpy(card->shortname, audio_driver->shortname);
303 	strcpy(card->longname, audio_driver->longname);
304 
305 	err = snd_bcm2835_create(card, &chip);
306 	if (err) {
307 		dev_err(child, "Failed to create chip, error %d\n", err);
308 		return err;
309 	}
310 
311 	chip->dev = child;
312 
313 	err = audio_driver->newpcm(chip, audio_driver->shortname,
314 		audio_driver->route,
315 		numchans);
316 	if (err) {
317 		dev_err(child, "Failed to create pcm, error %d\n", err);
318 		return err;
319 	}
320 
321 	err = audio_driver->newctl(chip);
322 	if (err) {
323 		dev_err(child, "Failed to create controls, error %d\n", err);
324 		return err;
325 	}
326 
327 	for (i = 0; i < numchans; i++)
328 		chip->avail_substreams |= (1 << i);
329 
330 	err = snd_card_register(card);
331 	if (err) {
332 		dev_err(child, "Failed to register card, error %d\n", err);
333 		return err;
334 	}
335 
336 	dev_set_drvdata(child, chip);
337 	dev_info(child, "card created with %d channels\n", numchans);
338 
339 	return 0;
340 }
341 
342 static int snd_add_child_devices(struct device *device, u32 numchans)
343 {
344 	int i;
345 	int count_devices = 0;
346 	int minchannels = 0;
347 	int extrachannels = 0;
348 	int extrachannels_per_driver = 0;
349 	int extrachannels_remainder = 0;
350 
351 	for (i = 0; i < ARRAY_SIZE(children_devices); i++)
352 		if (*children_devices[i].is_enabled)
353 			count_devices++;
354 
355 	if (!count_devices)
356 		return 0;
357 
358 	for (i = 0; i < ARRAY_SIZE(children_devices); i++)
359 		if (*children_devices[i].is_enabled)
360 			minchannels +=
361 				children_devices[i].audio_driver->minchannels;
362 
363 	if (minchannels < numchans) {
364 		extrachannels = numchans - minchannels;
365 		extrachannels_per_driver = extrachannels / count_devices;
366 		extrachannels_remainder = extrachannels % count_devices;
367 	}
368 
369 	dev_dbg(device, "minchannels %d\n", minchannels);
370 	dev_dbg(device, "extrachannels %d\n", extrachannels);
371 	dev_dbg(device, "extrachannels_per_driver %d\n",
372 		extrachannels_per_driver);
373 	dev_dbg(device, "extrachannels_remainder %d\n",
374 		extrachannels_remainder);
375 
376 	for (i = 0; i < ARRAY_SIZE(children_devices); i++) {
377 		int err;
378 		int numchannels_this_device;
379 		struct bcm2835_audio_driver *audio_driver;
380 
381 		if (!*children_devices[i].is_enabled)
382 			continue;
383 
384 		audio_driver = children_devices[i].audio_driver;
385 
386 		if (audio_driver->minchannels > numchans) {
387 			dev_err(device,
388 				"Out of channels, needed %d but only %d left\n",
389 				audio_driver->minchannels,
390 				numchans);
391 			continue;
392 		}
393 
394 		numchannels_this_device =
395 			audio_driver->minchannels + extrachannels_per_driver +
396 			extrachannels_remainder;
397 		extrachannels_remainder = 0;
398 
399 		numchans -= numchannels_this_device;
400 
401 		err = snd_add_child_device(device, audio_driver,
402 					   numchannels_this_device);
403 		if (err)
404 			return err;
405 	}
406 
407 	return 0;
408 }
409 
410 static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev)
411 {
412 	struct device *dev = &pdev->dev;
413 	u32 numchans;
414 	int err;
415 
416 	err = of_property_read_u32(dev->of_node, "brcm,pwm-channels",
417 				   &numchans);
418 	if (err) {
419 		dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'");
420 		return err;
421 	}
422 
423 	if (numchans == 0 || numchans > MAX_SUBSTREAMS) {
424 		numchans = MAX_SUBSTREAMS;
425 		dev_warn(dev,
426 			 "Illegal 'brcm,pwm-channels' value, will use %u\n",
427 			 numchans);
428 	}
429 
430 	err = bcm2835_devm_add_vchi_ctx(dev);
431 	if (err)
432 		return err;
433 
434 	err = snd_add_child_devices(dev, numchans);
435 	if (err)
436 		return err;
437 
438 	return 0;
439 }
440 
441 #ifdef CONFIG_PM
442 
443 static int snd_bcm2835_alsa_suspend(struct platform_device *pdev,
444 				    pm_message_t state)
445 {
446 	return 0;
447 }
448 
449 static int snd_bcm2835_alsa_resume(struct platform_device *pdev)
450 {
451 	return 0;
452 }
453 
454 #endif
455 
456 static const struct of_device_id snd_bcm2835_of_match_table[] = {
457 	{ .compatible = "brcm,bcm2835-audio",},
458 	{},
459 };
460 MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
461 
462 static struct platform_driver bcm2835_alsa0_driver = {
463 	.probe = snd_bcm2835_alsa_probe_dt,
464 #ifdef CONFIG_PM
465 	.suspend = snd_bcm2835_alsa_suspend,
466 	.resume = snd_bcm2835_alsa_resume,
467 #endif
468 	.driver = {
469 		.name = "bcm2835_audio",
470 		.of_match_table = snd_bcm2835_of_match_table,
471 	},
472 };
473 
474 static int bcm2835_alsa_device_init(void)
475 {
476 	int retval;
477 
478 	retval = platform_driver_register(&bcm2835_alsa0_driver);
479 	if (retval)
480 		pr_err("Error registering bcm2835_audio driver %d .\n", retval);
481 
482 	return retval;
483 }
484 
485 static void bcm2835_alsa_device_exit(void)
486 {
487 	platform_driver_unregister(&bcm2835_alsa0_driver);
488 }
489 
490 late_initcall(bcm2835_alsa_device_init);
491 module_exit(bcm2835_alsa_device_exit);
492 
493 MODULE_AUTHOR("Dom Cobley");
494 MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
495 MODULE_LICENSE("GPL");
496