Skip to content

Commit 6b9b2f8

Browse files
committed
First pass at alsa sound driver. Some functionality, but also some underruns
1 parent 54afb78 commit 6b9b2f8

File tree

9 files changed

+2240
-0
lines changed

9 files changed

+2240
-0
lines changed

arch/arm/mach-bcm2708/bcm2708.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,16 @@ struct platform_device bcm2708_powerman_device = {
467467
.coherent_dma_mask = 0xffffffffUL},
468468
};
469469

470+
471+
static struct platform_device bcm2708_alsa_devices[] = {
472+
[0] = {
473+
.name = "bcm2835_AUD0",
474+
.id = 0, /* first audio device */
475+
.resource = 0,
476+
.num_resources = 0,
477+
},
478+
};
479+
470480
int __init bcm_register_device(struct platform_device *pdev)
471481
{
472482
int ret;
@@ -503,6 +513,8 @@ void __init bcm2708_init(void)
503513
bcm_register_device(&bcm2708_emmc_device);
504514
#endif
505515
bcm2708_init_led();
516+
for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
517+
bcm_register_device(&bcm2708_alsa_devices[i]);
506518

507519
#ifdef CONFIG_BCM2708_VCMEM
508520
{

sound/arm/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,12 @@ config SND_PXA2XX_AC97
3939
Say Y or M if you want to support any AC97 codec attached to
4040
the PXA2xx AC97 interface.
4141

42+
config SND_BCM2835
43+
tristate "BCM2835 ALSA driver"
44+
depends on ARCH_BCM2708 && SND
45+
select SND_PCM
46+
help
47+
Say Y or M if you want to support BCM2835 Alsa pcm card driver
48+
4249
endif # SND_ARM
4350

sound/arm/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,9 @@ snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o
1414

1515
obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
1616
snd-pxa2xx-ac97-objs := pxa2xx-ac97.o
17+
18+
obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o
19+
snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o
20+
21+
EXTRA_CFLAGS += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel
22+

sound/arm/bcm2835-ctl.c

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*****************************************************************************
2+
* Copyright 2011 Broadcom Corporation. All rights reserved.
3+
*
4+
* Unless you and Broadcom execute a separate written software license
5+
* agreement governing use of this software, this software is licensed to you
6+
* under the terms of the GNU General Public License version 2, available at
7+
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
8+
*
9+
* Notwithstanding the above, under no circumstances may you combine this
10+
* software in any way with any other Broadcom software provided under a
11+
* license other than the GPL, without Broadcom's express prior written
12+
* consent.
13+
*****************************************************************************/
14+
15+
#include <linux/platform_device.h>
16+
#include <linux/init.h>
17+
#include <linux/io.h>
18+
#include <linux/jiffies.h>
19+
#include <linux/slab.h>
20+
#include <linux/time.h>
21+
#include <linux/wait.h>
22+
#include <linux/delay.h>
23+
#include <linux/moduleparam.h>
24+
#include <linux/sched.h>
25+
26+
#include <sound/core.h>
27+
#include <sound/control.h>
28+
#include <sound/pcm.h>
29+
#include <sound/pcm_params.h>
30+
#include <sound/rawmidi.h>
31+
#include <sound/initval.h>
32+
#include <sound/tlv.h>
33+
34+
#include "bcm2835.h"
35+
36+
static int snd_bcm2835_ctl_info(struct snd_kcontrol * kcontrol,
37+
struct snd_ctl_elem_info * uinfo)
38+
{
39+
if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
40+
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
41+
uinfo->count = 1;
42+
uinfo->value.integer.min = -10240;
43+
uinfo->value.integer.max = 2303;
44+
} else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
45+
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
46+
uinfo->count = 1;
47+
uinfo->value.integer.min = 0;
48+
uinfo->value.integer.max = 1;
49+
} else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
50+
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
51+
uinfo->count = 1;
52+
uinfo->value.integer.min = AUDIO_DEST_LOCAL;
53+
uinfo->value.integer.max = AUDIO_DEST_ALL;
54+
}
55+
56+
return 0;
57+
}
58+
59+
static int snd_bcm2835_ctl_get(struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol)
60+
{
61+
struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
62+
63+
BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
64+
65+
if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
66+
ucontrol->value.integer.value[0] = chip->volume;
67+
else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
68+
ucontrol->value.integer.value[0] = chip->mute;
69+
else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
70+
ucontrol->value.integer.value[0] = chip->dest;
71+
72+
return 0;
73+
}
74+
75+
static int snd_bcm2835_ctl_put(struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol)
76+
{
77+
struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
78+
int changed = 0;
79+
80+
if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
81+
if (chip->mute) {
82+
chip->mute = 0;
83+
changed = 1;
84+
}
85+
if (changed || (ucontrol->value.integer.value[0] != chip->volume)) {
86+
int atten;
87+
88+
chip->volume = ucontrol->value.integer.value[0];
89+
changed = 1;
90+
atten = -((chip->volume << 8) / 100);
91+
chip->volume = atten;
92+
}
93+
94+
} else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
95+
// Not implemented
96+
if (ucontrol->value.integer.value[0] != chip->mute) {
97+
chip->mute = ucontrol->value.integer.value[0];
98+
changed = 0;
99+
}
100+
} else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
101+
if (ucontrol->value.integer.value[0] != chip->dest && ucontrol->value.integer.value[0] != 1) {
102+
chip->dest= ucontrol->value.integer.value[0];
103+
changed = 1;
104+
}
105+
}
106+
107+
if (changed) {
108+
if (bcm2835_audio_set_ctls(chip))
109+
printk(KERN_ERR"Failed to set ALSA controls..\n");
110+
}
111+
112+
return changed;
113+
}
114+
115+
static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, -10240, 1, 1);
116+
117+
static struct snd_kcontrol_new snd_bcm2835_ctl[] __devinitdata =
118+
{
119+
{
120+
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
121+
.name = "PCM Playback Volume",
122+
.index = 0,
123+
.access= SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE,
124+
.private_value = PCM_PLAYBACK_VOLUME,
125+
.info = snd_bcm2835_ctl_info,
126+
.get = snd_bcm2835_ctl_get,
127+
.put = snd_bcm2835_ctl_put,
128+
.count = 1,
129+
.tlv = { .p = snd_bcm2835_db_scale }
130+
},
131+
{
132+
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
133+
.name = "PCM Playback Switch",
134+
.index = 0,
135+
.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
136+
.private_value = PCM_PLAYBACK_MUTE,
137+
.info = snd_bcm2835_ctl_info,
138+
.get = snd_bcm2835_ctl_get,
139+
.put = snd_bcm2835_ctl_put,
140+
.count = 1,
141+
},
142+
{
143+
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
144+
.name = "PCM Playback Route",
145+
.index = 0,
146+
.access= SNDRV_CTL_ELEM_ACCESS_READWRITE,
147+
.private_value = PCM_PLAYBACK_DEVICE,
148+
.info = snd_bcm2835_ctl_info,
149+
.get = snd_bcm2835_ctl_get,
150+
.put = snd_bcm2835_ctl_put,
151+
.count = 1,
152+
},
153+
};
154+
155+
int __devinit snd_bcm2835_new_ctl(bcm2835_chip_t *chip)
156+
{
157+
int err;
158+
unsigned int idx;
159+
160+
strcpy(chip->card->mixername, "Broadcom Mixer");
161+
for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++)
162+
{
163+
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_bcm2835_ctl[idx], chip));
164+
if (err < 0)
165+
return err;
166+
}
167+
return 0;
168+
}

0 commit comments

Comments
 (0)