1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2011 Broadcom Corporation. All rights reserved. */
4 #include <linux/platform_device.h>
6 #include <linux/init.h>
7 #include <linux/slab.h>
8 #include <linux/module.h>
13 static bool enable_hdmi;
14 static bool enable_headphones;
15 static bool enable_compat_alsa = true;
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");
25 static void snd_devm_unregister_child(struct device *dev, void *res)
27 struct device *childdev = *(struct device **)res;
28 struct bcm2835_chip *chip = dev_get_drvdata(childdev);
29 struct snd_card *card = chip->card;
33 device_unregister(childdev);
36 static int snd_devm_add_child(struct device *dev, struct device *child)
41 dr = devres_alloc(snd_devm_unregister_child, sizeof(*dr), GFP_KERNEL);
45 ret = device_add(child);
57 static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
59 struct bcm2835_vchi_ctx *vchi_ctx = res;
61 bcm2835_free_vchi_ctx(vchi_ctx);
64 static int bcm2835_devm_add_vchi_ctx(struct device *dev)
66 struct bcm2835_vchi_ctx *vchi_ctx;
69 vchi_ctx = devres_alloc(bcm2835_devm_free_vchi_ctx, sizeof(*vchi_ctx),
74 memset(vchi_ctx, 0, sizeof(*vchi_ctx));
76 ret = bcm2835_new_vchi_ctx(vchi_ctx);
78 devres_free(vchi_ctx);
82 devres_add(dev, vchi_ctx);
87 static void snd_bcm2835_release(struct device *dev)
89 struct bcm2835_chip *chip = dev_get_drvdata(dev);
94 static struct device *
95 snd_create_device(struct device *parent,
96 struct device_driver *driver,
99 struct device *device;
102 device = devm_kzalloc(parent, sizeof(*device), GFP_KERNEL);
104 return ERR_PTR(-ENOMEM);
106 device_initialize(device);
107 device->parent = parent;
108 device->driver = driver;
109 device->release = snd_bcm2835_release;
111 dev_set_name(device, "%s", name);
113 ret = snd_devm_add_child(parent, device);
120 /* component-destructor
121 * (see "Management of Cards and Components")
123 static int snd_bcm2835_dev_free(struct snd_device *device)
125 struct bcm2835_chip *chip = device->device_data;
126 struct snd_card *card = chip->card;
128 snd_device_free(card, chip);
133 /* chip-specific constructor
134 * (see "Management of Cards and Components")
136 static int snd_bcm2835_create(struct snd_card *card,
137 struct bcm2835_chip **rchip)
139 struct bcm2835_chip *chip;
141 static struct snd_device_ops ops = {
142 .dev_free = snd_bcm2835_dev_free,
147 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
153 chip->vchi_ctx = devres_find(card->dev->parent,
154 bcm2835_devm_free_vchi_ctx, NULL, NULL);
155 if (!chip->vchi_ctx) {
160 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
170 static struct snd_card *snd_bcm2835_card_new(struct device *dev)
172 struct snd_card *card;
175 ret = snd_card_new(dev, -1, NULL, THIS_MODULE, 0, &card);
182 typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
184 enum snd_bcm2835_route route,
187 typedef int (*bcm2835_audio_newctl_func)(struct bcm2835_chip *chip);
189 struct bcm2835_audio_driver {
190 struct device_driver driver;
191 const char *shortname;
192 const char *longname;
194 bcm2835_audio_newpcm_func newpcm;
195 bcm2835_audio_newctl_func newctl;
196 enum snd_bcm2835_route route;
199 static int bcm2835_audio_alsa_newpcm(struct bcm2835_chip *chip,
201 enum snd_bcm2835_route route,
206 err = snd_bcm2835_new_pcm(chip, numchannels - 1);
210 err = snd_bcm2835_new_spdif_pcm(chip);
217 static struct bcm2835_audio_driver bcm2835_audio_alsa = {
219 .name = "bcm2835_alsa",
220 .owner = THIS_MODULE,
222 .shortname = "bcm2835 ALSA",
223 .longname = "bcm2835 ALSA",
225 .newpcm = bcm2835_audio_alsa_newpcm,
226 .newctl = snd_bcm2835_new_ctl,
229 static struct bcm2835_audio_driver bcm2835_audio_hdmi = {
231 .name = "bcm2835_hdmi",
232 .owner = THIS_MODULE,
234 .shortname = "bcm2835 HDMI",
235 .longname = "bcm2835 HDMI",
237 .newpcm = snd_bcm2835_new_simple_pcm,
238 .newctl = snd_bcm2835_new_hdmi_ctl,
239 .route = AUDIO_DEST_HDMI
242 static struct bcm2835_audio_driver bcm2835_audio_headphones = {
244 .name = "bcm2835_headphones",
245 .owner = THIS_MODULE,
247 .shortname = "bcm2835 Headphones",
248 .longname = "bcm2835 Headphones",
250 .newpcm = snd_bcm2835_new_simple_pcm,
251 .newctl = snd_bcm2835_new_headphones_ctl,
252 .route = AUDIO_DEST_HEADPHONES
255 struct bcm2835_audio_drivers {
256 struct bcm2835_audio_driver *audio_driver;
257 const bool *is_enabled;
260 static struct bcm2835_audio_drivers children_devices[] = {
262 .audio_driver = &bcm2835_audio_alsa,
263 .is_enabled = &enable_compat_alsa,
266 .audio_driver = &bcm2835_audio_hdmi,
267 .is_enabled = &enable_hdmi,
270 .audio_driver = &bcm2835_audio_headphones,
271 .is_enabled = &enable_headphones,
275 static int snd_add_child_device(struct device *device,
276 struct bcm2835_audio_driver *audio_driver,
279 struct snd_card *card;
280 struct device *child;
281 struct bcm2835_chip *chip;
284 child = snd_create_device(device, &audio_driver->driver,
285 audio_driver->driver.name);
288 "Unable to create child device %p, error %ld",
289 audio_driver->driver.name,
291 return PTR_ERR(child);
294 card = snd_bcm2835_card_new(child);
296 dev_err(child, "Failed to create card");
297 return PTR_ERR(card);
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);
305 err = snd_bcm2835_create(card, &chip);
307 dev_err(child, "Failed to create chip, error %d\n", err);
313 err = audio_driver->newpcm(chip, audio_driver->shortname,
317 dev_err(child, "Failed to create pcm, error %d\n", err);
321 err = audio_driver->newctl(chip);
323 dev_err(child, "Failed to create controls, error %d\n", err);
327 for (i = 0; i < numchans; i++)
328 chip->avail_substreams |= (1 << i);
330 err = snd_card_register(card);
332 dev_err(child, "Failed to register card, error %d\n", err);
336 dev_set_drvdata(child, chip);
337 dev_info(child, "card created with %d channels\n", numchans);
342 static int snd_add_child_devices(struct device *device, u32 numchans)
345 int count_devices = 0;
347 int extrachannels = 0;
348 int extrachannels_per_driver = 0;
349 int extrachannels_remainder = 0;
351 for (i = 0; i < ARRAY_SIZE(children_devices); i++)
352 if (*children_devices[i].is_enabled)
358 for (i = 0; i < ARRAY_SIZE(children_devices); i++)
359 if (*children_devices[i].is_enabled)
361 children_devices[i].audio_driver->minchannels;
363 if (minchannels < numchans) {
364 extrachannels = numchans - minchannels;
365 extrachannels_per_driver = extrachannels / count_devices;
366 extrachannels_remainder = extrachannels % count_devices;
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);
376 for (i = 0; i < ARRAY_SIZE(children_devices); i++) {
378 int numchannels_this_device;
379 struct bcm2835_audio_driver *audio_driver;
381 if (!*children_devices[i].is_enabled)
384 audio_driver = children_devices[i].audio_driver;
386 if (audio_driver->minchannels > numchans) {
388 "Out of channels, needed %d but only %d left\n",
389 audio_driver->minchannels,
394 numchannels_this_device =
395 audio_driver->minchannels + extrachannels_per_driver +
396 extrachannels_remainder;
397 extrachannels_remainder = 0;
399 numchans -= numchannels_this_device;
401 err = snd_add_child_device(device, audio_driver,
402 numchannels_this_device);
410 static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev)
412 struct device *dev = &pdev->dev;
416 err = of_property_read_u32(dev->of_node, "brcm,pwm-channels",
419 dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'");
423 if (numchans == 0 || numchans > MAX_SUBSTREAMS) {
424 numchans = MAX_SUBSTREAMS;
426 "Illegal 'brcm,pwm-channels' value, will use %u\n",
430 err = bcm2835_devm_add_vchi_ctx(dev);
434 err = snd_add_child_devices(dev, numchans);
443 static int snd_bcm2835_alsa_suspend(struct platform_device *pdev,
449 static int snd_bcm2835_alsa_resume(struct platform_device *pdev)
456 static const struct of_device_id snd_bcm2835_of_match_table[] = {
457 { .compatible = "brcm,bcm2835-audio",},
460 MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
462 static struct platform_driver bcm2835_alsa0_driver = {
463 .probe = snd_bcm2835_alsa_probe_dt,
465 .suspend = snd_bcm2835_alsa_suspend,
466 .resume = snd_bcm2835_alsa_resume,
469 .name = "bcm2835_audio",
470 .of_match_table = snd_bcm2835_of_match_table,
474 static int bcm2835_alsa_device_init(void)
478 retval = platform_driver_register(&bcm2835_alsa0_driver);
480 pr_err("Error registering bcm2835_audio driver %d .\n", retval);
485 static void bcm2835_alsa_device_exit(void)
487 platform_driver_unregister(&bcm2835_alsa0_driver);
490 late_initcall(bcm2835_alsa_device_init);
491 module_exit(bcm2835_alsa_device_exit);
493 MODULE_AUTHOR("Dom Cobley");
494 MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
495 MODULE_LICENSE("GPL");