summaryrefslogtreecommitdiffstats
path: root/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
diff options
context:
space:
mode:
authorMichael Zoran <mzoran@crowfest.net>2017-03-14 17:01:25 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-21 08:38:33 +0100
commit325b5b6c96a863989078df402d1670d061f52d88 (patch)
treee0fd2152f21ba6a6952b7fc0b7629acf9e8ead8b /drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
parentf7d51372d7d1779bf60f7de35a4b12850442a9de (diff)
downloadop-kernel-dev-325b5b6c96a863989078df402d1670d061f52d88.zip
op-kernel-dev-325b5b6c96a863989078df402d1670d061f52d88.tar.gz
staging: bcm2835-audio: Add support for simultanous HDMI and Headphone audio
The firmware for the Raspberry PI already supports simultanous output of audio through both the HDMI and the Headphone jack. The current implementation of ALSA doesn't expose this well to user mode since the firmware audio is represented as a single card. A newer approach is taken here and a virtual card is created for each output(HDMI, Headphones, and Traditional ALSA). The firmware has the concept of channels or streams for which the number to use is passed in the device tree. These streams are allocated to each of the virtual cards. As a side effect of this change, since each output is represented independenly it's now very easy to use PulseAudio to control the priorities of the outputs. Testing: Audacity and VLC were both loaded at the same time. Each application was assigned to a different card. With this change I was able to play different music files at the same time through the HDMI and Headphones jacks and control the audio independently. Signed-off-by: Michael Zoran <mzoran@crowfest.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c')
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
index 059f54a..8bd69b9 100644
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c
@@ -479,7 +479,7 @@ static struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = {
};
/* create a pcm device */
-int snd_bcm2835_new_pcm(struct bcm2835_chip *chip)
+int snd_bcm2835_new_pcm(struct bcm2835_chip *chip, u32 numchannels)
{
struct snd_pcm *pcm;
int err;
@@ -490,7 +490,7 @@ int snd_bcm2835_new_pcm(struct bcm2835_chip *chip)
audio_error("Interrupted whilst waiting for lock\n");
return -EINTR;
}
- err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm);
+ err = snd_pcm_new(chip->card, "bcm2835 ALSA", 0, numchannels, 0, &pcm);
if (err < 0)
goto out;
pcm->private_data = chip;
@@ -549,3 +549,39 @@ out:
return 0;
}
+
+int snd_bcm2835_new_simple_pcm(struct bcm2835_chip *chip,
+ const char *name,
+ enum snd_bcm2835_route route,
+ u32 numchannels)
+{
+ struct snd_pcm *pcm;
+ int err;
+
+ mutex_init(&chip->audio_mutex);
+
+ err = snd_pcm_new(chip->card, name, 0, numchannels,
+ 0, &pcm);
+ if (err)
+ return err;
+
+ pcm->private_data = chip;
+ strcpy(pcm->name, name);
+ chip->pcm = pcm;
+ chip->dest = route;
+ chip->volume = alsa2chip(0);
+ chip->mute = CTRL_VOL_UNMUTE;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_bcm2835_playback_ops);
+
+ snd_pcm_lib_preallocate_pages_for_all(
+ pcm,
+ SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL),
+ snd_bcm2835_playback_hw.buffer_bytes_max,
+ snd_bcm2835_playback_hw.buffer_bytes_max);
+
+ return 0;
+}
+
OpenPOWER on IntegriCloud