Merge tag 'v5.15.57' into rpi-5.15.y
[platform/kernel/linux-rpi.git] / drivers / staging / vc04_services / bcm2835-audio / bcm2835.c
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 #include <soc/bcm2835/raspberrypi-firmware.h>
13
14 static bool enable_hdmi, enable_hdmi0, enable_hdmi1;
15 static bool enable_headphones;
16 static bool enable_compat_alsa = true;
17
18 module_param(enable_hdmi, bool, 0444);
19 MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device");
20 module_param(enable_headphones, bool, 0444);
21 MODULE_PARM_DESC(enable_headphones, "Enables Headphones virtual audio device");
22 module_param(enable_compat_alsa, bool, 0444);
23 MODULE_PARM_DESC(enable_compat_alsa,
24                  "Enables ALSA compatibility virtual audio device");
25
26 static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res)
27 {
28         struct bcm2835_vchi_ctx *vchi_ctx = res;
29
30         bcm2835_free_vchi_ctx(vchi_ctx);
31 }
32
33 static int bcm2835_devm_add_vchi_ctx(struct device *dev)
34 {
35         struct bcm2835_vchi_ctx *vchi_ctx;
36         int ret;
37
38         vchi_ctx = devres_alloc(bcm2835_devm_free_vchi_ctx, sizeof(*vchi_ctx),
39                                 GFP_KERNEL);
40         if (!vchi_ctx)
41                 return -ENOMEM;
42
43         ret = bcm2835_new_vchi_ctx(dev, vchi_ctx);
44         if (ret) {
45                 devres_free(vchi_ctx);
46                 return ret;
47         }
48
49         devres_add(dev, vchi_ctx);
50
51         return 0;
52 }
53
54 typedef int (*bcm2835_audio_newpcm_func)(struct bcm2835_chip *chip,
55                                          const char *name,
56                                          enum snd_bcm2835_route route,
57                                          u32 numchannels);
58
59 typedef int (*bcm2835_audio_newctl_func)(struct bcm2835_chip *chip);
60
61 struct bcm2835_audio_driver {
62         struct device_driver driver;
63         const char *shortname;
64         const char *longname;
65         int minchannels;
66         bcm2835_audio_newpcm_func newpcm;
67         bcm2835_audio_newctl_func newctl;
68         enum snd_bcm2835_route route;
69 };
70
71 static int bcm2835_audio_alsa_newpcm(struct bcm2835_chip *chip,
72                                      const char *name,
73                                      enum snd_bcm2835_route route,
74                                      u32 numchannels)
75 {
76         int err;
77
78         err = snd_bcm2835_new_pcm(chip, "bcm2835 ALSA", 0, AUDIO_DEST_AUTO,
79                                   numchannels - 1, false);
80         if (err)
81                 return err;
82
83         err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI", 1, AUDIO_DEST_HDMI0, 1, true);
84         if (err)
85                 return err;
86
87         err = snd_bcm2835_new_pcm(chip, "bcm2835 IEC958/HDMI1", 2, AUDIO_DEST_HDMI1, 1, true);
88         if (err)
89                 return err;
90
91         return 0;
92 }
93
94 static int bcm2835_audio_simple_newpcm(struct bcm2835_chip *chip,
95                                        const char *name,
96                                        enum snd_bcm2835_route route,
97                                        u32 numchannels)
98 {
99         return snd_bcm2835_new_pcm(chip, name, 0, route, numchannels, false);
100 }
101
102 static struct bcm2835_audio_driver bcm2835_audio_alsa = {
103         .driver = {
104                 .name = "bcm2835_alsa",
105                 .owner = THIS_MODULE,
106         },
107         .shortname = "bcm2835 ALSA",
108         .longname  = "bcm2835 ALSA",
109         .minchannels = 2,
110         .newpcm = bcm2835_audio_alsa_newpcm,
111         .newctl = snd_bcm2835_new_ctl,
112 };
113
114 static struct bcm2835_audio_driver bcm2835_audio_hdmi0 = {
115         .driver = {
116                 .name = "bcm2835_hdmi",
117                 .owner = THIS_MODULE,
118         },
119         .shortname = "bcm2835 HDMI 1",
120         .longname  = "bcm2835 HDMI 1",
121         .minchannels = 1,
122         .newpcm = bcm2835_audio_simple_newpcm,
123         .newctl = snd_bcm2835_new_hdmi_ctl,
124         .route = AUDIO_DEST_HDMI0
125 };
126
127 static struct bcm2835_audio_driver bcm2835_audio_hdmi1 = {
128         .driver = {
129                 .name = "bcm2835_hdmi",
130                 .owner = THIS_MODULE,
131         },
132         .shortname = "bcm2835 HDMI 2",
133         .longname  = "bcm2835 HDMI 2",
134         .minchannels = 1,
135         .newpcm = bcm2835_audio_simple_newpcm,
136         .newctl = snd_bcm2835_new_hdmi_ctl,
137         .route = AUDIO_DEST_HDMI1
138 };
139
140 static struct bcm2835_audio_driver bcm2835_audio_headphones = {
141         .driver = {
142                 .name = "bcm2835_headphones",
143                 .owner = THIS_MODULE,
144         },
145         .shortname = "bcm2835 Headphones",
146         .longname  = "bcm2835 Headphones",
147         .minchannels = 1,
148         .newpcm = bcm2835_audio_simple_newpcm,
149         .newctl = snd_bcm2835_new_headphones_ctl,
150         .route = AUDIO_DEST_HEADPHONES
151 };
152
153 struct bcm2835_audio_drivers {
154         struct bcm2835_audio_driver *audio_driver;
155         const bool *is_enabled;
156 };
157
158 static struct bcm2835_audio_drivers children_devices[] = {
159         {
160                 .audio_driver = &bcm2835_audio_alsa,
161                 .is_enabled = &enable_compat_alsa,
162         },
163         {
164                 .audio_driver = &bcm2835_audio_hdmi0,
165                 .is_enabled = &enable_hdmi0,
166         },
167         {
168                 .audio_driver = &bcm2835_audio_hdmi1,
169                 .is_enabled = &enable_hdmi1,
170         },
171         {
172                 .audio_driver = &bcm2835_audio_headphones,
173                 .is_enabled = &enable_headphones,
174         },
175 };
176
177 static void bcm2835_card_free(void *data)
178 {
179         snd_card_free(data);
180 }
181
182 static int snd_add_child_device(struct device *dev,
183                                 struct bcm2835_audio_driver *audio_driver,
184                                 u32 numchans)
185 {
186         struct bcm2835_chip *chip;
187         struct snd_card *card;
188         int err;
189
190         err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card);
191         if (err < 0) {
192                 dev_err(dev, "Failed to create card");
193                 return err;
194         }
195
196         chip = card->private_data;
197         chip->card = card;
198         chip->dev = dev;
199         mutex_init(&chip->audio_mutex);
200
201         chip->vchi_ctx = devres_find(dev,
202                                      bcm2835_devm_free_vchi_ctx, NULL, NULL);
203         if (!chip->vchi_ctx) {
204                 err = -ENODEV;
205                 goto error;
206         }
207
208         strscpy(card->driver, audio_driver->driver.name, sizeof(card->driver));
209         strscpy(card->shortname, audio_driver->shortname, sizeof(card->shortname));
210         strscpy(card->longname, audio_driver->longname, sizeof(card->longname));
211
212         err = audio_driver->newpcm(chip, audio_driver->shortname,
213                 audio_driver->route,
214                 numchans);
215         if (err) {
216                 dev_err(dev, "Failed to create pcm, error %d\n", err);
217                 goto error;
218         }
219
220         err = audio_driver->newctl(chip);
221         if (err) {
222                 dev_err(dev, "Failed to create controls, error %d\n", err);
223                 goto error;
224         }
225
226         err = snd_card_register(card);
227         if (err) {
228                 dev_err(dev, "Failed to register card, error %d\n", err);
229                 goto error;
230         }
231
232         dev_set_drvdata(dev, chip);
233
234         err = devm_add_action(dev, bcm2835_card_free, card);
235         if (err < 0) {
236                 dev_err(dev, "Failed to add devm action, err %d\n", err);
237                 goto error;
238         }
239
240         dev_info(dev, "card created with %d channels\n", numchans);
241         return 0;
242
243  error:
244         snd_card_free(card);
245         return err;
246 }
247
248 static int snd_add_child_devices(struct device *device, u32 numchans)
249 {
250         int extrachannels_per_driver = 0;
251         int extrachannels_remainder = 0;
252         int count_devices = 0;
253         int extrachannels = 0;
254         int minchannels = 0;
255         int i;
256
257         for (i = 0; i < ARRAY_SIZE(children_devices); i++)
258                 if (*children_devices[i].is_enabled)
259                         count_devices++;
260
261         if (!count_devices)
262                 return 0;
263
264         for (i = 0; i < ARRAY_SIZE(children_devices); i++)
265                 if (*children_devices[i].is_enabled)
266                         minchannels +=
267                                 children_devices[i].audio_driver->minchannels;
268
269         if (minchannels < numchans) {
270                 extrachannels = numchans - minchannels;
271                 extrachannels_per_driver = extrachannels / count_devices;
272                 extrachannels_remainder = extrachannels % count_devices;
273         }
274
275         dev_dbg(device, "minchannels %d\n", minchannels);
276         dev_dbg(device, "extrachannels %d\n", extrachannels);
277         dev_dbg(device, "extrachannels_per_driver %d\n",
278                 extrachannels_per_driver);
279         dev_dbg(device, "extrachannels_remainder %d\n",
280                 extrachannels_remainder);
281
282         for (i = 0; i < ARRAY_SIZE(children_devices); i++) {
283                 struct bcm2835_audio_driver *audio_driver;
284                 int numchannels_this_device;
285                 int err;
286
287                 if (!*children_devices[i].is_enabled)
288                         continue;
289
290                 audio_driver = children_devices[i].audio_driver;
291
292                 if (audio_driver->minchannels > numchans) {
293                         dev_err(device,
294                                 "Out of channels, needed %d but only %d left\n",
295                                 audio_driver->minchannels,
296                                 numchans);
297                         continue;
298                 }
299
300                 numchannels_this_device =
301                         audio_driver->minchannels + extrachannels_per_driver +
302                         extrachannels_remainder;
303                 extrachannels_remainder = 0;
304
305                 numchans -= numchannels_this_device;
306
307                 err = snd_add_child_device(device, audio_driver,
308                                            numchannels_this_device);
309                 if (err)
310                         return err;
311         }
312
313         return 0;
314 }
315
316 static void set_hdmi_enables(struct device *dev)
317 {
318         struct device_node *firmware_node;
319         struct rpi_firmware *firmware;
320         u32 num_displays, i, display_id;
321         int ret;
322
323         firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0);
324         firmware = rpi_firmware_get(firmware_node);
325
326         if (!firmware)
327                 return;
328
329         of_node_put(firmware_node);
330
331         ret = rpi_firmware_property(firmware,
332                                     RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS,
333                                     &num_displays, sizeof(u32));
334
335         if (ret)
336                 return;
337
338         for (i = 0; i < num_displays; i++) {
339                 display_id = i;
340                 ret = rpi_firmware_property(firmware,
341                                 RPI_FIRMWARE_FRAMEBUFFER_GET_DISPLAY_ID,
342                                 &display_id, sizeof(display_id));
343                 if (!ret) {
344                         if (display_id == 2)
345                                 enable_hdmi0 = true;
346                         if (display_id == 7)
347                                 enable_hdmi1 = true;
348                 }
349         }
350
351         if (!enable_hdmi0 && enable_hdmi1) {
352                 /* Swap them over and reassign route. This means
353                  * that if we only have one connected, it is always named
354                  *  HDMI1, irrespective of if its on port HDMI0 or HDMI1.
355                  *  This should match with the naming of HDMI ports in DRM
356                  */
357                 enable_hdmi0 = true;
358                 enable_hdmi1 = false;
359                 bcm2835_audio_hdmi0.route = AUDIO_DEST_HDMI1;
360         }
361 }
362
363 static int snd_bcm2835_alsa_probe(struct platform_device *pdev)
364 {
365         struct device *dev = &pdev->dev;
366         u32 numchans;
367         int err;
368
369         err = of_property_read_u32(dev->of_node, "brcm,pwm-channels",
370                                    &numchans);
371         if (err) {
372                 dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'");
373                 return err;
374         }
375
376         if (numchans == 0 || numchans > MAX_SUBSTREAMS) {
377                 numchans = MAX_SUBSTREAMS;
378                 dev_warn(dev,
379                          "Illegal 'brcm,pwm-channels' value, will use %u\n",
380                          numchans);
381         }
382
383         if (!enable_compat_alsa) {
384                 // In this mode, enable analog output by default
385                 u32 disable_headphones = 0;
386
387                 if (!of_property_read_bool(dev->of_node, "brcm,disable-hdmi"))
388                         set_hdmi_enables(dev);
389
390                 of_property_read_u32(dev->of_node,
391                                      "brcm,disable-headphones",
392                                      &disable_headphones);
393                 enable_headphones = !disable_headphones;
394         } else {
395                 enable_hdmi0 = enable_hdmi;
396         }
397
398         err = bcm2835_devm_add_vchi_ctx(dev);
399         if (err)
400                 return err;
401
402         err = snd_add_child_devices(dev, numchans);
403         if (err)
404                 return err;
405
406         return 0;
407 }
408
409 #ifdef CONFIG_PM
410
411 static int snd_bcm2835_alsa_suspend(struct platform_device *pdev,
412                                     pm_message_t state)
413 {
414         return 0;
415 }
416
417 static int snd_bcm2835_alsa_resume(struct platform_device *pdev)
418 {
419         return 0;
420 }
421
422 #endif
423
424 static const struct of_device_id snd_bcm2835_of_match_table[] = {
425         { .compatible = "brcm,bcm2835-audio",},
426         {},
427 };
428 MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table);
429
430 static struct platform_driver bcm2835_alsa_driver = {
431         .probe = snd_bcm2835_alsa_probe,
432 #ifdef CONFIG_PM
433         .suspend = snd_bcm2835_alsa_suspend,
434         .resume = snd_bcm2835_alsa_resume,
435 #endif
436         .driver = {
437                 .name = "bcm2835_audio",
438                 .of_match_table = snd_bcm2835_of_match_table,
439         },
440 };
441 module_platform_driver(bcm2835_alsa_driver);
442
443 MODULE_AUTHOR("Dom Cobley");
444 MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
445 MODULE_LICENSE("GPL");
446 MODULE_ALIAS("platform:bcm2835_audio");