1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 06:47:34 +00:00

Kernel/Audio: Introduce a new design architecture for the subsystem

We have 3 new components:
1. The AudioManagement singleton. This class like in other subsystems,
is responsible to find hardware audio controllers and keep a reference
to them.
2. AudioController class - this class is the parent class for hardware
controllers like the Sound Blaster 16 or Intel 82801AA (AC97). For now,
this class has simple interface for getting and controlling sample rate
of audio channels, as well a write interface for specific audio channel
but not reading from it. One AudioController object might have multiple
AudioChannel "child" objects to hold with reference counting.
3. AudioChannel class - this is based on the CharacterDevice class, and
represents hardware PCM audio channel. It facilitates an ioctl interface
which should be consistent across all supported hardware currently.
It has a weak reference to a parent AudioController, and when trying to
write to a channel, it redirects the data to the parent AudioController.
Each audio channel device should be added into a new directory under the
/dev filesystem called "audio".
This commit is contained in:
Liav A 2022-02-11 21:47:45 +02:00 committed by Andreas Kling
parent 6218ec8afa
commit 6efa27537a
13 changed files with 382 additions and 127 deletions

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Singleton.h>
#include <Kernel/Bus/PCI/API.h>
#include <Kernel/Bus/PCI/IDs.h>
#include <Kernel/Devices/Audio/AC97.h>
#include <Kernel/Devices/Audio/Management.h>
#include <Kernel/Devices/Audio/SB16.h>
#include <Kernel/Sections.h>
namespace Kernel {
static Singleton<AudioManagement> s_the;
static Atomic<u32> s_device_minor_number;
MajorNumber AudioManagement::audio_type_major_number()
{
return 116;
}
MinorNumber AudioManagement::generate_storage_minor_number()
{
auto minor_number = s_device_minor_number.load();
s_device_minor_number++;
return minor_number;
}
AudioManagement& AudioManagement::the()
{
return *s_the;
}
UNMAP_AFTER_INIT AudioManagement::AudioManagement()
{
}
UNMAP_AFTER_INIT void AudioManagement::enumerate_hardware_controllers()
{
if (auto controller = SB16::try_detect_and_create(); !controller.is_error())
m_controllers_list.append(controller.release_value());
PCI::enumerate([&](PCI::DeviceIdentifier const& device_identifier) {
// Note: Only consider PCI audio controllers
if (device_identifier.class_code().value() != to_underlying(PCI::ClassID::Multimedia)
|| device_identifier.subclass_code().value() != to_underlying(PCI::Multimedia::SubclassID::AudioController))
return;
dbgln("AC97: found audio controller at {}", device_identifier.address());
// FIXME: Propagate errors properly
m_controllers_list.append(AC97::try_create(device_identifier).release_value());
});
}
UNMAP_AFTER_INIT void AudioManagement::enumerate_hardware_audio_channels()
{
for (auto& controller : m_controllers_list)
controller.detect_hardware_audio_channels({});
}
UNMAP_AFTER_INIT bool AudioManagement::initialize()
{
/* Explanation on the flow:
* 1. Enumerate all audio controllers connected to the system:
* a. Try to find the SB16 ISA-based controller.
* b. Enumerate the PCI bus and try to find audio controllers there too
* 2. Ask each controller to detect the audio channels and instantiate AudioChannel objects.
*/
enumerate_hardware_controllers();
enumerate_hardware_audio_channels();
if (m_controllers_list.is_empty()) {
dbgln("No audio controller was initialized.");
return false;
}
return true;
}
}