Skip to content

Commit

Permalink
Add low water threshold ioctl to sound core.
Browse files Browse the repository at this point in the history
OSS offers an ioctl that dictates how many bytes need to be available
before a sound device is signalled. This change implements support for
that.

To make this easier, as a bit of clean-up, sound buffers now keep track
of the number of available bytes, rather than having to calculate them
based on the core and controller offsets. This actually ends up making
a few other ioctls and the I/O routine simpler. And to make some of the
calculations performant, buffer size, fragment size, and fragment count
must be a power of 2.
  • Loading branch information
ccstevens committed Jun 26, 2017
1 parent 29bf201 commit 97abb21
Show file tree
Hide file tree
Showing 9 changed files with 299 additions and 203 deletions.
8 changes: 8 additions & 0 deletions apps/libc/include/sys/soundcard.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ extern "C" {

#define SNDCTL_DSP_CHANNELS 0x5013

//
// This ioctl sets the low water mark, in bytes, that is required to be reached
// before an input device will signal that bytes are ready to read or before
// an output device will signal that empty bytes are available to write into.
//

#define SNDCTL_DSP_LOW_WATER 0x5014

//
// This ioctl forces the sound device into non-blocking mode, ignoring the
// file descriptor's O_NONBLOCK file mode flag's state. Using fcntl to
Expand Down
31 changes: 24 additions & 7 deletions drivers/sound/broadcom/bc27pwma/pwma.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,23 @@ Module Name:
#define BCM27_PWMA_FRAGMENT_COUNT_MAX 256

//
// Define the minimum fragment size, in bytes.
// Define the minimum fragment size, in bytes. This must be a power of 2.
//

#define BCM27_PWMA_FRAGMENT_SIZE_MIN 256

//
// Define the maximum fragment size, in bytes. This must be a power of 2.
//

#define BCM27_PWMA_FRAGMENT_SIZE_MAX 0x40000000

//
// Define the maximum buffer size, in bytes. This must be a power of 2.
//

#define BCM27_PWMA_BUFFER_SIZE_MAX 0x80000000

//
// Define the mask and value for the upper byte of the physical addresses that
// must be supplied to the DMA controller.
Expand Down Expand Up @@ -1573,8 +1585,8 @@ Return Value:
Registration.MinFragmentCount = BCM27_PWMA_FRAGMENT_COUNT_MIN;
Registration.MaxFragmentCount = BCM27_PWMA_FRAGMENT_COUNT_MAX;
Registration.MinFragmentSize = BCM27_PWMA_FRAGMENT_SIZE_MIN;
Registration.MaxFragmentSize = MAX_ULONG;
Registration.MaxBufferSize = MAX_ULONG;
Registration.MaxFragmentSize = BCM27_PWMA_FRAGMENT_SIZE_MAX;
Registration.MaxBufferSize = BCM27_PWMA_BUFFER_SIZE_MAX;
Registration.DeviceCount = 1;
SoundDevice = &(Controller->Device.Public.SoundDevice);
Registration.Devices = &SoundDevice;
Expand Down Expand Up @@ -1812,9 +1824,15 @@ Return Value:

Device = Transfer->UserContext;
Device->BufferPosition += Device->Buffer->FragmentSize;
if (Device->BufferPosition >= Device->Buffer->Size) {
Device->BufferPosition -= Device->Buffer->Size;
}

//
// The buffer size should be a power of 2, so just mask off the size.
//

ASSERT(POWER_OF_2(Device->Buffer->Size) != FALSE);

Device->BufferPosition = REMAINDER(Device->BufferPosition,
Device->Buffer->Size);

SoundUpdateBufferState(Device->Buffer,
SoundDeviceOutput,
Expand Down Expand Up @@ -1989,7 +2007,6 @@ Return Value:

DmaConfig |= BCM2709_PWM_DMA_CONFIG_ENABLE;
BCM27_WRITE_PWMA(Controller, Bcm2709PwmDmaConfig, DmaConfig);
IoSetIoObjectState(Device->Buffer->IoState, POLL_EVENT_OUT, TRUE);
break;

//
Expand Down
Loading

0 comments on commit 97abb21

Please sign in to comment.