Compare commits
No commits in common. "5c20d5e2915549c118743e94b03d17f7bad6e08f" and "35e2a70de05edd10025a2bcdedfdd30dbe976ade" have entirely different histories.
5c20d5e291
...
35e2a70de0
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/Device/Device.h>
|
#include <kernel/Device/Device.h>
|
||||||
#include <kernel/Memory/ByteRingBuffer.h>
|
|
||||||
#include <kernel/PCI.h>
|
#include <kernel/PCI.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
|
@ -17,7 +16,6 @@ namespace Kernel
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AudioController();
|
AudioController();
|
||||||
BAN::ErrorOr<void> initialize();
|
|
||||||
|
|
||||||
virtual void handle_new_data() = 0;
|
virtual void handle_new_data() = 0;
|
||||||
|
|
||||||
|
|
@ -29,7 +27,7 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<void> set_current_pin(uint32_t) = 0;
|
virtual BAN::ErrorOr<void> set_current_pin(uint32_t) = 0;
|
||||||
|
|
||||||
bool can_read_impl() const override { return false; }
|
bool can_read_impl() const override { return false; }
|
||||||
bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return !m_sample_data->full(); }
|
bool can_write_impl() const override { SpinLockGuard _(m_spinlock); return m_sample_data_size < m_sample_data_capacity; }
|
||||||
bool has_error_impl() const override { return false; }
|
bool has_error_impl() const override { return false; }
|
||||||
bool has_hungup_impl() const override { return false; }
|
bool has_hungup_impl() const override { return false; }
|
||||||
|
|
||||||
|
|
@ -42,7 +40,9 @@ namespace Kernel
|
||||||
mutable SpinLock m_spinlock;
|
mutable SpinLock m_spinlock;
|
||||||
|
|
||||||
static constexpr size_t m_sample_data_capacity = 1 << 20;
|
static constexpr size_t m_sample_data_capacity = 1 << 20;
|
||||||
BAN::UniqPtr<ByteRingBuffer> m_sample_data;
|
uint8_t m_sample_data[m_sample_data_capacity];
|
||||||
|
size_t m_sample_data_head { 0 };
|
||||||
|
size_t m_sample_data_size { 0 };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dev_t m_rdev;
|
const dev_t m_rdev;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ namespace Kernel
|
||||||
void queue_bdl_data();
|
void queue_bdl_data();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr size_t m_max_path_length = 16;
|
||||||
|
|
||||||
// use 6 512 sample BDL entries
|
// use 6 512 sample BDL entries
|
||||||
// each entry is ~10.7 ms at 48 kHz
|
// each entry is ~10.7 ms at 48 kHz
|
||||||
// -> total buffered audio is 64 ms
|
// -> total buffered audio is 64 ms
|
||||||
|
|
@ -64,7 +66,6 @@ namespace Kernel
|
||||||
const uint8_t m_cid;
|
const uint8_t m_cid;
|
||||||
|
|
||||||
BAN::Vector<BAN::Vector<const HDAudio::AFGWidget*>> m_output_paths;
|
BAN::Vector<BAN::Vector<const HDAudio::AFGWidget*>> m_output_paths;
|
||||||
BAN::Vector<const HDAudio::AFGWidget*> m_output_pins;
|
|
||||||
size_t m_output_path_index { SIZE_MAX };
|
size_t m_output_path_index { SIZE_MAX };
|
||||||
|
|
||||||
uint8_t m_stream_id { 0xFF };
|
uint8_t m_stream_id { 0xFF };
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,6 @@ namespace Kernel::HDAudio
|
||||||
{
|
{
|
||||||
bool input;
|
bool input;
|
||||||
bool output;
|
bool output;
|
||||||
bool display; // HDMI or DP
|
|
||||||
uint32_t config;
|
|
||||||
} pin_complex;
|
} pin_complex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ namespace Kernel::HDAudio
|
||||||
VMIN = 0x02,
|
VMIN = 0x02,
|
||||||
VMAJ = 0x03,
|
VMAJ = 0x03,
|
||||||
GCTL = 0x08,
|
GCTL = 0x08,
|
||||||
STATESTS = 0x0E,
|
|
||||||
|
|
||||||
INTCTL = 0x20,
|
INTCTL = 0x20,
|
||||||
INTSTS = 0x24,
|
INTSTS = 0x24,
|
||||||
|
|
|
||||||
|
|
@ -118,8 +118,6 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> AC97AudioController::initialize()
|
BAN::ErrorOr<void> AC97AudioController::initialize()
|
||||||
{
|
{
|
||||||
TRY(AudioController::initialize());
|
|
||||||
|
|
||||||
m_pci_device.enable_bus_mastering();
|
m_pci_device.enable_bus_mastering();
|
||||||
|
|
||||||
m_mixer = TRY(m_pci_device.allocate_bar_region(0));
|
m_mixer = TRY(m_pci_device.allocate_bar_region(0));
|
||||||
|
|
@ -205,22 +203,23 @@ namespace Kernel
|
||||||
if (next_bld_head == m_bdl_tail)
|
if (next_bld_head == m_bdl_tail)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const size_t sample_frames = BAN::Math::min(m_sample_data->size() / get_channels() / sizeof(uint16_t), m_samples_per_entry / get_channels());
|
const size_t sample_data_tail = (m_sample_data_head + m_sample_data_capacity - m_sample_data_size) % m_sample_data_capacity;
|
||||||
if (sample_frames == 0)
|
|
||||||
|
const size_t max_memcpy = BAN::Math::min(m_sample_data_size, m_sample_data_capacity - sample_data_tail);
|
||||||
|
const size_t samples = BAN::Math::min(max_memcpy / 2, m_samples_per_entry);
|
||||||
|
if (samples == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const size_t copy_total_bytes = sample_frames * get_channels() * sizeof(uint16_t);
|
|
||||||
|
|
||||||
auto& entry = reinterpret_cast<AC97::BufferDescriptorListEntry*>(m_bdl_region->vaddr())[m_bdl_head];
|
auto& entry = reinterpret_cast<AC97::BufferDescriptorListEntry*>(m_bdl_region->vaddr())[m_bdl_head];
|
||||||
entry.samples = sample_frames * get_channels();
|
entry.samples = samples;
|
||||||
entry.flags = (1 << 15);
|
entry.flags = (1 << 15);
|
||||||
memcpy(
|
memcpy(
|
||||||
reinterpret_cast<void*>(m_bdl_region->paddr_to_vaddr(entry.address)),
|
reinterpret_cast<void*>(m_bdl_region->paddr_to_vaddr(entry.address)),
|
||||||
m_sample_data->get_data().data(),
|
&m_sample_data[sample_data_tail],
|
||||||
copy_total_bytes
|
samples * 2
|
||||||
);
|
);
|
||||||
|
|
||||||
m_sample_data->pop(copy_total_bytes);
|
m_sample_data_size -= samples * 2;
|
||||||
|
|
||||||
lvi = m_bdl_head;
|
lvi = m_bdl_head;
|
||||||
m_bdl_head = next_bld_head;
|
m_bdl_head = next_bld_head;
|
||||||
|
|
|
||||||
|
|
@ -53,28 +53,34 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> AudioController::initialize()
|
|
||||||
{
|
|
||||||
m_sample_data = TRY(ByteRingBuffer::create(m_sample_data_capacity));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> AudioController::write_impl(off_t, BAN::ConstByteSpan buffer)
|
BAN::ErrorOr<size_t> AudioController::write_impl(off_t, BAN::ConstByteSpan buffer)
|
||||||
{
|
{
|
||||||
SpinLockGuard lock_guard(m_spinlock);
|
SpinLockGuard lock_guard(m_spinlock);
|
||||||
|
|
||||||
while (m_sample_data->full())
|
while (m_sample_data_size >= m_sample_data_capacity)
|
||||||
{
|
{
|
||||||
SpinLockGuardAsMutex smutex(lock_guard);
|
SpinLockGuardAsMutex smutex(lock_guard);
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_sample_data_blocker, &smutex));
|
TRY(Thread::current().block_or_eintr_indefinite(m_sample_data_blocker, &smutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t to_copy = BAN::Math::min(buffer.size(), m_sample_data->free());
|
size_t nwritten = 0;
|
||||||
m_sample_data->push(buffer.slice(0, to_copy));
|
while (nwritten < buffer.size())
|
||||||
|
{
|
||||||
|
if (m_sample_data_size >= m_sample_data_capacity)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const size_t max_memcpy = BAN::Math::min(m_sample_data_capacity - m_sample_data_size, m_sample_data_capacity - m_sample_data_head);
|
||||||
|
const size_t to_copy = BAN::Math::min(buffer.size() - nwritten, max_memcpy);
|
||||||
|
memcpy(m_sample_data + m_sample_data_head, buffer.data() + nwritten, to_copy);
|
||||||
|
|
||||||
|
nwritten += to_copy;
|
||||||
|
m_sample_data_head = (m_sample_data_head + to_copy) % m_sample_data_capacity;
|
||||||
|
m_sample_data_size += to_copy;
|
||||||
|
}
|
||||||
|
|
||||||
handle_new_data();
|
handle_new_data();
|
||||||
|
|
||||||
return to_copy;
|
return nwritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> AudioController::ioctl_impl(int cmd, void* arg)
|
BAN::ErrorOr<long> AudioController::ioctl_impl(int cmd, void* arg)
|
||||||
|
|
@ -91,9 +97,9 @@ namespace Kernel
|
||||||
case SND_GET_BUFFERSZ:
|
case SND_GET_BUFFERSZ:
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_spinlock);
|
SpinLockGuard _(m_spinlock);
|
||||||
*static_cast<uint32_t*>(arg) = m_sample_data->size();
|
*static_cast<uint32_t*>(arg) = m_sample_data_size;
|
||||||
if (cmd == SND_RESET_BUFFER)
|
if (cmd == SND_RESET_BUFFER)
|
||||||
m_sample_data->pop(m_sample_data->size());
|
m_sample_data_size = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SND_GET_TOTAL_PINS:
|
case SND_GET_TOTAL_PINS:
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
#include <kernel/Audio/HDAudio/Registers.h>
|
#include <kernel/Audio/HDAudio/Registers.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
|
|
||||||
#include <BAN/Sort.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -27,8 +25,6 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> HDAudioFunctionGroup::initialize()
|
BAN::ErrorOr<void> HDAudioFunctionGroup::initialize()
|
||||||
{
|
{
|
||||||
TRY(AudioController::initialize());
|
|
||||||
|
|
||||||
if constexpr(DEBUG_HDAUDIO)
|
if constexpr(DEBUG_HDAUDIO)
|
||||||
{
|
{
|
||||||
const auto widget_to_string =
|
const auto widget_to_string =
|
||||||
|
|
@ -54,13 +50,19 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (widget.type == HDAudio::AFGWidget::Type::PinComplex)
|
if (widget.type == HDAudio::AFGWidget::Type::PinComplex)
|
||||||
{
|
{
|
||||||
dprintln(" widget {}: {} ({}, {}, {}), {32b}",
|
const uint32_t config = TRY(m_controller->send_command({
|
||||||
|
.data = 0x00,
|
||||||
|
.command = 0xF1C,
|
||||||
|
.node_index = widget.id,
|
||||||
|
.codec_address = m_cid,
|
||||||
|
}));
|
||||||
|
|
||||||
|
dprintln(" widget {}: {} ({}, {}), {32b}",
|
||||||
widget.id,
|
widget.id,
|
||||||
widget_to_string(widget.type),
|
widget_to_string(widget.type),
|
||||||
(int)widget.pin_complex.output,
|
(int)widget.pin_complex.output,
|
||||||
(int)widget.pin_complex.input,
|
(int)widget.pin_complex.input,
|
||||||
(int)widget.pin_complex.display,
|
config
|
||||||
widget.pin_complex.config
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -77,49 +79,59 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(initialize_stream());
|
TRY(initialize_stream());
|
||||||
|
TRY(initialize_output());
|
||||||
if (auto ret = initialize_output(); ret.is_error())
|
|
||||||
{
|
|
||||||
// No usable pins, not really an error
|
|
||||||
if (ret.error().get_error_code() == ENODEV)
|
|
||||||
return {};
|
|
||||||
return ret.release_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
DevFileSystem::get().add_device(this);
|
DevFileSystem::get().add_device(this);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t HDAudioFunctionGroup::get_total_pins() const
|
uint32_t HDAudioFunctionGroup::get_total_pins() const
|
||||||
{
|
{
|
||||||
return m_output_pins.size();
|
uint32_t count = 0;
|
||||||
|
for (const auto& widget : m_afg_node.widgets)
|
||||||
|
if (widget.type == HDAudio::AFGWidget::Type::PinComplex && widget.pin_complex.output)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t HDAudioFunctionGroup::get_current_pin() const
|
uint32_t HDAudioFunctionGroup::get_current_pin() const
|
||||||
{
|
{
|
||||||
const auto current_id = m_output_paths[m_output_path_index].front()->id;
|
const auto current_id = m_output_paths[m_output_path_index].front()->id;
|
||||||
for (size_t i = 0; i < m_output_pins.size(); i++)
|
|
||||||
if (m_output_pins[i]->id == current_id)
|
uint32_t pin = 0;
|
||||||
return i;
|
for (const auto& widget : m_afg_node.widgets)
|
||||||
|
{
|
||||||
|
if (widget.type != HDAudio::AFGWidget::Type::PinComplex || !widget.pin_complex.output)
|
||||||
|
continue;
|
||||||
|
if (widget.id == current_id)
|
||||||
|
return pin;
|
||||||
|
pin++;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> HDAudioFunctionGroup::set_current_pin(uint32_t pin)
|
BAN::ErrorOr<void> HDAudioFunctionGroup::set_current_pin(uint32_t pin)
|
||||||
{
|
{
|
||||||
if (pin >= m_output_pins.size())
|
uint32_t pin_id = 0;
|
||||||
return BAN::Error::from_errno(EINVAL);
|
for (const auto& widget : m_afg_node.widgets)
|
||||||
|
{
|
||||||
|
if (widget.type != HDAudio::AFGWidget::Type::PinComplex || !widget.pin_complex.output)
|
||||||
|
continue;
|
||||||
|
if (pin-- > 0)
|
||||||
|
continue;
|
||||||
|
pin_id = widget.id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (auto ret = disable_output_path(m_output_path_index); ret.is_error())
|
if (auto ret = disable_output_path(m_output_path_index); ret.is_error())
|
||||||
dwarnln("failed to disable old output path {}", ret.error());
|
dwarnln("failed to disable old output path {}", ret.error());
|
||||||
|
|
||||||
const uint32_t pin_id = m_output_pins[pin]->id;
|
|
||||||
for (size_t i = 0; i < m_output_paths.size(); i++)
|
for (size_t i = 0; i < m_output_paths.size(); i++)
|
||||||
{
|
{
|
||||||
if (m_output_paths[i].front()->id != pin_id)
|
if (m_output_paths[i].front()->id != pin_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (auto ret = enable_output_path(i); ret.is_error())
|
if (auto ret = enable_output_path(i); !ret.is_error())
|
||||||
{
|
{
|
||||||
if (ret.error().get_error_code() == ENOTSUP)
|
if (ret.error().get_error_code() == ENOTSUP)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -127,6 +139,7 @@ namespace Kernel
|
||||||
return ret.release_error();
|
return ret.release_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dprintln("set output widget to {}", pin_id);
|
||||||
m_output_path_index = i;
|
m_output_path_index = i;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
@ -217,39 +230,18 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> HDAudioFunctionGroup::initialize_output()
|
BAN::ErrorOr<void> HDAudioFunctionGroup::initialize_output()
|
||||||
{
|
{
|
||||||
|
BAN::Vector<const HDAudio::AFGWidget*> path;
|
||||||
|
TRY(path.reserve(m_max_path_length));
|
||||||
|
|
||||||
for (const auto& widget : m_afg_node.widgets)
|
for (const auto& widget : m_afg_node.widgets)
|
||||||
{
|
{
|
||||||
if (widget.type != HDAudio::AFGWidget::Type::PinComplex || !widget.pin_complex.output)
|
if (widget.type != HDAudio::AFGWidget::Type::PinComplex || !widget.pin_complex.output)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// no physical connection
|
|
||||||
if ((widget.pin_complex.config >> 30) == 0b01)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// needs a GPU
|
|
||||||
if (widget.pin_complex.display)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BAN::Vector<const HDAudio::AFGWidget*> path;
|
|
||||||
TRY(path.push_back(&widget));
|
TRY(path.push_back(&widget));
|
||||||
TRY(recurse_output_paths(widget, path));
|
TRY(recurse_output_paths(widget, path));
|
||||||
|
path.pop_back();
|
||||||
if (!m_output_paths.empty() && m_output_paths.back().front()->id == widget.id)
|
|
||||||
TRY(m_output_pins.push_back(&widget));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_output_pins.empty())
|
|
||||||
return BAN::Error::from_errno(ENODEV);
|
|
||||||
|
|
||||||
// prefer short paths
|
|
||||||
BAN::sort::sort(m_output_paths.begin(), m_output_paths.end(),
|
|
||||||
[](const auto& a, const auto& b) {
|
|
||||||
if (a.front()->id != b.front()->id)
|
|
||||||
return a.front()->id < b.front()->id;
|
|
||||||
return a.size() < b.size();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
dprintln_if(DEBUG_HDAUDIO, "found {} paths from output to DAC", m_output_paths.size());
|
dprintln_if(DEBUG_HDAUDIO, "found {} paths from output to DAC", m_output_paths.size());
|
||||||
|
|
||||||
// select first supported path
|
// select first supported path
|
||||||
|
|
@ -450,6 +442,10 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> HDAudioFunctionGroup::recurse_output_paths(const HDAudio::AFGWidget& widget, BAN::Vector<const HDAudio::AFGWidget*>& path)
|
BAN::ErrorOr<void> HDAudioFunctionGroup::recurse_output_paths(const HDAudio::AFGWidget& widget, BAN::Vector<const HDAudio::AFGWidget*>& path)
|
||||||
{
|
{
|
||||||
|
// cycle "detection"
|
||||||
|
if (path.size() >= m_max_path_length)
|
||||||
|
return {};
|
||||||
|
|
||||||
// we've reached a DAC
|
// we've reached a DAC
|
||||||
if (widget.type == HDAudio::AFGWidget::Type::OutputConverter)
|
if (widget.type == HDAudio::AFGWidget::Type::OutputConverter)
|
||||||
{
|
{
|
||||||
|
|
@ -466,18 +462,9 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (!widget.connections.contains(connection.id))
|
if (!widget.connections.contains(connection.id))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// cycle detection
|
|
||||||
for (const auto* w : path)
|
|
||||||
if (w == &connection)
|
|
||||||
goto already_visited;
|
|
||||||
|
|
||||||
TRY(path.push_back(&connection));
|
TRY(path.push_back(&connection));
|
||||||
TRY(recurse_output_paths(connection, path));
|
TRY(recurse_output_paths(connection, path));
|
||||||
path.pop_back();
|
path.pop_back();
|
||||||
|
|
||||||
already_visited:
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
@ -496,18 +483,30 @@ namespace Kernel
|
||||||
|
|
||||||
while ((m_bdl_head + 1) % m_bdl_entry_count != m_bdl_tail)
|
while ((m_bdl_head + 1) % m_bdl_entry_count != m_bdl_tail)
|
||||||
{
|
{
|
||||||
const size_t sample_frames = BAN::Math::min(m_sample_data->size() / get_channels() / sizeof(uint16_t), m_bdl_entry_sample_frames);
|
const size_t sample_data_tail = (m_sample_data_head + m_sample_data_capacity - m_sample_data_size) % m_sample_data_capacity;
|
||||||
|
|
||||||
|
const size_t sample_frames = BAN::Math::min(m_sample_data_size / get_channels() / sizeof(uint16_t), m_bdl_entry_sample_frames);
|
||||||
if (sample_frames == 0)
|
if (sample_frames == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const size_t copy_total_bytes = sample_frames * get_channels() * sizeof(uint16_t);
|
const size_t copy_total_bytes = sample_frames * get_channels() * sizeof(uint16_t);
|
||||||
|
const size_t copy_before_wrap = BAN::Math::min(copy_total_bytes, m_sample_data_capacity - sample_data_tail);
|
||||||
|
|
||||||
memcpy(
|
memcpy(
|
||||||
reinterpret_cast<void*>(m_bdl_region->vaddr() + m_bdl_head * bdl_entry_bytes),
|
reinterpret_cast<void*>(m_bdl_region->vaddr() + m_bdl_head * bdl_entry_bytes),
|
||||||
m_sample_data->get_data().data(),
|
&m_sample_data[sample_data_tail],
|
||||||
copy_total_bytes
|
copy_before_wrap
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (copy_before_wrap < copy_total_bytes)
|
||||||
|
{
|
||||||
|
memcpy(
|
||||||
|
reinterpret_cast<void*>(m_bdl_region->vaddr() + m_bdl_head * bdl_entry_bytes + copy_before_wrap),
|
||||||
|
&m_sample_data[0],
|
||||||
|
copy_total_bytes - copy_before_wrap
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (copy_total_bytes < bdl_entry_bytes)
|
if (copy_total_bytes < bdl_entry_bytes)
|
||||||
{
|
{
|
||||||
memset(
|
memset(
|
||||||
|
|
@ -517,7 +516,8 @@ namespace Kernel
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sample_data->pop(copy_total_bytes);
|
m_sample_data_size -= copy_total_bytes;
|
||||||
|
|
||||||
m_bdl_head = (m_bdl_head + 1) % m_bdl_entry_count;
|
m_bdl_head = (m_bdl_head + 1) % m_bdl_entry_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,12 +65,8 @@ namespace Kernel
|
||||||
m_pci_device.enable_interrupt(0, *this);
|
m_pci_device.enable_interrupt(0, *this);
|
||||||
m_bar0->write32(Regs::INTCTL, UINT32_MAX);
|
m_bar0->write32(Regs::INTCTL, UINT32_MAX);
|
||||||
|
|
||||||
const uint16_t state_sts = m_bar0->read16(Regs::STATESTS);
|
for (uint8_t codec_id = 0; codec_id < 0x10; codec_id++)
|
||||||
for (uint8_t codec_id = 0; codec_id < 15; codec_id++)
|
|
||||||
{
|
{
|
||||||
if (!(state_sts & (1 << codec_id)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto codec_or_error = initialize_codec(codec_id);
|
auto codec_or_error = initialize_codec(codec_id);
|
||||||
if (codec_or_error.is_error())
|
if (codec_or_error.is_error())
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -311,12 +307,8 @@ namespace Kernel
|
||||||
if (result.type == AFGWidget::Type::PinComplex)
|
if (result.type == AFGWidget::Type::PinComplex)
|
||||||
{
|
{
|
||||||
const uint32_t cap = send_command_or_zero(0xF00, 0x0C);
|
const uint32_t cap = send_command_or_zero(0xF00, 0x0C);
|
||||||
result.pin_complex = {
|
result.pin_complex.output = !!(cap & (1 << 4));
|
||||||
.input = !!(cap & (1 << 5)),
|
result.pin_complex.input = !!(cap & (1 << 5));
|
||||||
.output = !!(cap & (1 << 4)),
|
|
||||||
.display = !!(cap & ((1 << 7) | (1 << 24))),
|
|
||||||
.config = send_command_or_zero(0xF1C, 0x00),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t connection_info = send_command_or_zero(0xF00, 0x0E);
|
const uint8_t connection_info = send_command_or_zero(0xF00, 0x0E);
|
||||||
|
|
|
||||||
|
|
@ -68,12 +68,7 @@ bool AudioServer::on_client_packet(int fd, LibAudio::Packet packet)
|
||||||
response = m_audio_devices.size();
|
response = m_audio_devices.size();
|
||||||
break;
|
break;
|
||||||
case LibAudio::Packet::QueryPins:
|
case LibAudio::Packet::QueryPins:
|
||||||
if (packet.parameter >= m_audio_devices.size())
|
response = device().total_pins;
|
||||||
{
|
|
||||||
dwarnln("Client tried to get pins of device {} while there are only {}", packet.parameter, m_audio_devices.size());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
response = m_audio_devices[packet.parameter].total_pins;
|
|
||||||
break;
|
break;
|
||||||
case LibAudio::Packet::GetDevice:
|
case LibAudio::Packet::GetDevice:
|
||||||
response = m_current_audio_device;
|
response = m_current_audio_device;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue