Commit 23b028c8 authored by Michael Zoran's avatar Michael Zoran Committed by Greg Kroah-Hartman

staging: bcm2835-audio: initial staging submission

Initial cleanup of bcm2835-audio driver for the
bcm2535(Raspberry PI)

Driver provides HDMI audio through ALSA and is built
on top of the vc04_services driver.

Original version of the driver is available at:
http://www.github.com/raspberry/linux

Driver compiles without any build errors or warnings.

Tested on a RPI 3 running in ARM64 mode with the
vlc player and alsautils.
Signed-off-by: default avatarMichael Zoran <mzoran@crowfest.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e7b56b14
...@@ -102,4 +102,6 @@ source "drivers/staging/greybus/Kconfig" ...@@ -102,4 +102,6 @@ source "drivers/staging/greybus/Kconfig"
source "drivers/staging/vc04_services/Kconfig" source "drivers/staging/vc04_services/Kconfig"
source "drivers/staging/bcm2835-audio/Kconfig"
endif # STAGING endif # STAGING
...@@ -40,3 +40,5 @@ obj-$(CONFIG_MOST) += most/ ...@@ -40,3 +40,5 @@ obj-$(CONFIG_MOST) += most/
obj-$(CONFIG_KS7010) += ks7010/ obj-$(CONFIG_KS7010) += ks7010/
obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_GREYBUS) += greybus/
obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/
obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/
config SND_BCM2835
tristate "BCM2835 ALSA driver"
depends on ARCH_BCM2835 && BCM2835_VCHIQ && SND
select SND_PCM
help
Say Y or M if you want to support BCM2835 Alsa pcm card driver
obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o
snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o
ccflags-y += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*****************************************************************************
* Copyright 2011 Broadcom Corporation. All rights reserved.
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2, available at
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
*
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a
* license other than the GPL, without Broadcom's express prior written
* consent.
*****************************************************************************/
#ifndef __SOUND_ARM_BCM2835_H
#define __SOUND_ARM_BCM2835_H
#include <linux/device.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/pcm-indirect.h>
#include <linux/workqueue.h>
/*
#define AUDIO_DEBUG_ENABLE
#define AUDIO_VERBOSE_DEBUG_ENABLE
*/
/* Debug macros */
#ifdef AUDIO_DEBUG_ENABLE
#ifdef AUDIO_VERBOSE_DEBUG_ENABLE
#define audio_debug(fmt, arg...) \
printk(KERN_INFO"%s:%d " fmt, __func__, __LINE__, ##arg)
#define audio_info(fmt, arg...) \
printk(KERN_INFO"%s:%d " fmt, __func__, __LINE__, ##arg)
#else
#define audio_debug(fmt, arg...)
#define audio_info(fmt, arg...)
#endif /* AUDIO_VERBOSE_DEBUG_ENABLE */
#else
#define audio_debug(fmt, arg...)
#define audio_info(fmt, arg...)
#endif /* AUDIO_DEBUG_ENABLE */
#define audio_error(fmt, arg...) \
printk(KERN_ERR"%s:%d " fmt, __func__, __LINE__, ##arg)
#define audio_warning(fmt, arg...) \
printk(KERN_WARNING"%s:%d " fmt, __func__, __LINE__, ##arg)
#define audio_alert(fmt, arg...) \
printk(KERN_ALERT"%s:%d " fmt, __func__, __LINE__, ##arg)
#define MAX_SUBSTREAMS (8)
#define AVAIL_SUBSTREAMS_MASK (0xff)
enum {
CTRL_VOL_MUTE,
CTRL_VOL_UNMUTE
};
/* macros for alsa2chip and chip2alsa, instead of functions */
#define alsa2chip(vol) (uint)(-((vol << 8) / 100)) /* convert alsa to chip volume (defined as macro rather than function call) */
#define chip2alsa(vol) -((vol * 100) >> 8) /* convert chip to alsa volume */
/* Some constants for values .. */
enum snd_bcm2835_route {
AUDIO_DEST_AUTO = 0,
AUDIO_DEST_HEADPHONES = 1,
AUDIO_DEST_HDMI = 2,
AUDIO_DEST_MAX,
};
enum snd_bcm2835_ctrl {
PCM_PLAYBACK_VOLUME,
PCM_PLAYBACK_MUTE,
PCM_PLAYBACK_DEVICE,
};
/* definition of the chip-specific record */
struct bcm2835_chip {
struct snd_card *card;
struct snd_pcm *pcm;
struct snd_pcm *pcm_spdif;
/* Bitmat for valid reg_base and irq numbers */
unsigned int avail_substreams;
struct platform_device *pdev[MAX_SUBSTREAMS];
struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
int volume;
int old_volume; /* stores the volume value whist muted */
int dest;
int mute;
unsigned int opened;
unsigned int spdif_status;
struct mutex audio_mutex;
};
struct bcm2835_alsa_stream {
struct bcm2835_chip *chip;
struct snd_pcm_substream *substream;
struct snd_pcm_indirect pcm_indirect;
struct semaphore buffers_update_sem;
struct semaphore control_sem;
spinlock_t lock;
volatile unsigned int control;
volatile unsigned int status;
int open;
int running;
int draining;
int channels;
int params_rate;
int pcm_format_width;
unsigned int pos;
unsigned int buffer_size;
unsigned int period_size;
unsigned int enable_fifo_irq;
irq_handler_t fifo_irq_handler;
atomic_t retrieved;
struct bcm2835_audio_instance *instance;
struct workqueue_struct *my_wq;
int idx;
};
int snd_bcm2835_new_ctl(struct bcm2835_chip *chip);
int snd_bcm2835_new_pcm(struct bcm2835_chip *chip);
int snd_bcm2835_new_spdif_pcm(struct bcm2835_chip *chip);
int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream);
int bcm2835_audio_close(struct bcm2835_alsa_stream *alsa_stream);
int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream,
unsigned int channels, unsigned int samplerate,
unsigned int bps);
int bcm2835_audio_setup(struct bcm2835_alsa_stream *alsa_stream);
int bcm2835_audio_start(struct bcm2835_alsa_stream *alsa_stream);
int bcm2835_audio_stop(struct bcm2835_alsa_stream *alsa_stream);
int bcm2835_audio_set_ctls(struct bcm2835_chip *chip);
int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream,
unsigned int count,
void *src);
unsigned int bcm2835_audio_retrieve_buffers(struct bcm2835_alsa_stream *alsa_stream);
void bcm2835_audio_flush_buffers(struct bcm2835_alsa_stream *alsa_stream);
void bcm2835_audio_flush_playback_buffers(struct bcm2835_alsa_stream *alsa_stream);
#endif /* __SOUND_ARM_BCM2835_H */
/*****************************************************************************
* Copyright 2011 Broadcom Corporation. All rights reserved.
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2, available at
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
*
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a
* license other than the GPL, without Broadcom's express prior written
* consent.
*****************************************************************************/
#ifndef _VC_AUDIO_DEFS_H_
#define _VC_AUDIO_DEFS_H_
#define VC_AUDIOSERV_MIN_VER 1
#define VC_AUDIOSERV_VER 2
/* FourCC code used for VCHI connection */
#define VC_AUDIO_SERVER_NAME MAKE_FOURCC("AUDS")
/* Maximum message length */
#define VC_AUDIO_MAX_MSG_LEN (sizeof( VC_AUDIO_MSG_T ))
/*
* List of screens that are currently supported
* All message types supported for HOST->VC direction
*/
enum vc_audio_msg_type {
VC_AUDIO_MSG_TYPE_RESULT, // Generic result
VC_AUDIO_MSG_TYPE_COMPLETE, // Generic result
VC_AUDIO_MSG_TYPE_CONFIG, // Configure audio
VC_AUDIO_MSG_TYPE_CONTROL, // Configure audio
VC_AUDIO_MSG_TYPE_OPEN, // Configure audio
VC_AUDIO_MSG_TYPE_CLOSE, // Configure audio
VC_AUDIO_MSG_TYPE_START, // Configure audio
VC_AUDIO_MSG_TYPE_STOP, // Configure audio
VC_AUDIO_MSG_TYPE_WRITE, // Configure audio
VC_AUDIO_MSG_TYPE_MAX
};
/* configure the audio */
struct vc_audio_config {
u32 channels;
u32 samplerate;
u32 bps;
};
struct vc_audio_control {
u32 volume;
u32 dest;
};
struct vc_audio_open {
u32 dummy;
};
struct vc_audio_close {
u32 dummy;
};
struct vc_audio_start {
u32 dummy;
};
struct vc_audio_stop {
u32 draining;
};
/* configure the write audio samples */
struct vc_audio_write {
u32 count; // in bytes
#if defined(CONFIG_64BIT)
u32 callbackl;
u32 callbackh;
#else
void *callback;
void *cookie;
#endif
s16 silence;
s16 max_packet;
};
/* Generic result for a request (VC->HOST) */
struct vc_audio_result {
s32 success; // Success value
};
/* Generic result for a request (VC->HOST) */
struct vc_audio_complete {
s32 count; // Success value
#if defined(CONFIG_64BIT)
u32 callbackl;
u32 callbackh;
#else
void *callback;
void *cookie;
#endif
};
/* Message header for all messages in HOST->VC direction */
struct vc_audio_msg {
s32 type; /* Message type (VC_AUDIO_MSG_TYPE) */
union {
struct vc_audio_config config;
struct vc_audio_control control;
struct vc_audio_open open;
struct vc_audio_close close;
struct vc_audio_start start;
struct vc_audio_stop stop;
struct vc_audio_write write;
struct vc_audio_result result;
struct vc_audio_complete complete;
} u;
};
#endif /* _VC_AUDIO_DEFS_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment