Merge pull request #4490 from wwylele/teakra-new
audio: implement DSP LLE
This commit is contained in:
commit
4f23d5d69e
23 changed files with 766 additions and 61 deletions
|
@ -6,6 +6,7 @@
|
|||
#include <utility>
|
||||
#include "audio_core/dsp_interface.h"
|
||||
#include "audio_core/hle/hle.h"
|
||||
#include "audio_core/lle/lle.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
|
@ -188,7 +189,13 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) {
|
|||
cpu_core = std::make_unique<ARM_DynCom>(*this, USER32MODE);
|
||||
}
|
||||
|
||||
dsp_core = std::make_unique<AudioCore::DspHle>(*memory);
|
||||
if (Settings::values.enable_dsp_lle) {
|
||||
dsp_core = std::make_unique<AudioCore::DspLle>(*memory,
|
||||
Settings::values.enable_dsp_lle_multithread);
|
||||
} else {
|
||||
dsp_core = std::make_unique<AudioCore::DspHle>(*memory);
|
||||
}
|
||||
|
||||
dsp_core->SetSink(Settings::values.sink_id, Settings::values.audio_device_id);
|
||||
dsp_core->EnableStretching(Settings::values.enable_audio_stretching);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
|
@ -86,10 +87,17 @@ void WaitObject::WakeupAllWaitingThreads() {
|
|||
|
||||
thread->ResumeFromWait();
|
||||
}
|
||||
|
||||
if (hle_notifier)
|
||||
hle_notifier();
|
||||
}
|
||||
|
||||
const std::vector<SharedPtr<Thread>>& WaitObject::GetWaitingThreads() const {
|
||||
return waiting_threads;
|
||||
}
|
||||
|
||||
void WaitObject::SetHLENotifier(std::function<void()> callback) {
|
||||
hle_notifier = std::move(callback);
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <boost/smart_ptr/intrusive_ptr.hpp>
|
||||
#include "common/common_types.h"
|
||||
|
@ -52,9 +53,15 @@ public:
|
|||
/// Get a const reference to the waiting threads list for debug use
|
||||
const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;
|
||||
|
||||
/// Sets a callback which is called when the object becomes available
|
||||
void SetHLENotifier(std::function<void()> callback);
|
||||
|
||||
private:
|
||||
/// Threads waiting for this object to become available
|
||||
std::vector<SharedPtr<Thread>> waiting_threads;
|
||||
|
||||
/// Function to call when this object becomes available
|
||||
std::function<void()> hle_notifier;
|
||||
};
|
||||
|
||||
// Specialization of DynamicObjectCast for WaitObjects
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include "audio_core/audio_types.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/hash.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
|
@ -24,26 +23,9 @@ void DSP_DSP::RecvData(Kernel::HLERequestContext& ctx) {
|
|||
IPC::RequestParser rp(ctx, 0x01, 1, 0);
|
||||
const u32 register_number = rp.Pop<u32>();
|
||||
|
||||
ASSERT_MSG(register_number == 0, "Unknown register_number {}", register_number);
|
||||
|
||||
// Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown
|
||||
// or slept.
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
switch (Core::DSP().GetDspState()) {
|
||||
case AudioCore::DspState::On:
|
||||
rb.Push<u32>(0);
|
||||
break;
|
||||
case AudioCore::DspState::Off:
|
||||
case AudioCore::DspState::Sleeping:
|
||||
rb.Push<u32>(1);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
rb.Push(system.DSP().RecvData(register_number));
|
||||
|
||||
LOG_DEBUG(Service_DSP, "register_number={}", register_number);
|
||||
}
|
||||
|
@ -52,11 +34,9 @@ void DSP_DSP::RecvDataIsReady(Kernel::HLERequestContext& ctx) {
|
|||
IPC::RequestParser rp(ctx, 0x02, 1, 0);
|
||||
const u32 register_number = rp.Pop<u32>();
|
||||
|
||||
ASSERT_MSG(register_number == 0, "Unknown register_number {}", register_number);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(true); /// 0 = not ready, 1 = ready to read
|
||||
rb.Push(system.DSP().RecvDataIsReady(register_number));
|
||||
|
||||
LOG_DEBUG(Service_DSP, "register_number={}", register_number);
|
||||
}
|
||||
|
@ -65,10 +45,12 @@ void DSP_DSP::SetSemaphore(Kernel::HLERequestContext& ctx) {
|
|||
IPC::RequestParser rp(ctx, 0x07, 1, 0);
|
||||
const u16 semaphore_value = rp.Pop<u16>();
|
||||
|
||||
system.DSP().SetSemaphore(semaphore_value);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_WARNING(Service_DSP, "(STUBBED) called, semaphore_value={:04X}", semaphore_value);
|
||||
LOG_INFO(Service_DSP, "called, semaphore_value={:04X}", semaphore_value);
|
||||
}
|
||||
|
||||
void DSP_DSP::ConvertProcessAddressFromDspDram(Kernel::HLERequestContext& ctx) {
|
||||
|
@ -111,7 +93,7 @@ void DSP_DSP::WriteProcessPipe(Kernel::HLERequestContext& ctx) {
|
|||
break;
|
||||
}
|
||||
|
||||
Core::DSP().PipeWrite(pipe, buffer);
|
||||
system.DSP().PipeWrite(pipe, buffer);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
@ -127,11 +109,11 @@ void DSP_DSP::ReadPipe(Kernel::HLERequestContext& ctx) {
|
|||
const u16 size = rp.Pop<u16>();
|
||||
|
||||
const DspPipe pipe = static_cast<DspPipe>(channel);
|
||||
const u16 pipe_readable_size = static_cast<u16>(Core::DSP().GetPipeReadableSize(pipe));
|
||||
const u16 pipe_readable_size = static_cast<u16>(system.DSP().GetPipeReadableSize(pipe));
|
||||
|
||||
std::vector<u8> pipe_buffer;
|
||||
if (pipe_readable_size >= size)
|
||||
pipe_buffer = Core::DSP().PipeRead(pipe, size);
|
||||
pipe_buffer = system.DSP().PipeRead(pipe, size);
|
||||
else
|
||||
UNREACHABLE(); // No more data is in pipe. Hardware hangs in this case; Should never happen.
|
||||
|
||||
|
@ -149,7 +131,7 @@ void DSP_DSP::GetPipeReadableSize(Kernel::HLERequestContext& ctx) {
|
|||
const u32 peer = rp.Pop<u32>();
|
||||
|
||||
const DspPipe pipe = static_cast<DspPipe>(channel);
|
||||
const u16 pipe_readable_size = static_cast<u16>(Core::DSP().GetPipeReadableSize(pipe));
|
||||
const u16 pipe_readable_size = static_cast<u16>(system.DSP().GetPipeReadableSize(pipe));
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
@ -166,11 +148,11 @@ void DSP_DSP::ReadPipeIfPossible(Kernel::HLERequestContext& ctx) {
|
|||
const u16 size = rp.Pop<u16>();
|
||||
|
||||
const DspPipe pipe = static_cast<DspPipe>(channel);
|
||||
const u16 pipe_readable_size = static_cast<u16>(Core::DSP().GetPipeReadableSize(pipe));
|
||||
const u16 pipe_readable_size = static_cast<u16>(system.DSP().GetPipeReadableSize(pipe));
|
||||
|
||||
std::vector<u8> pipe_buffer;
|
||||
if (pipe_readable_size >= size)
|
||||
pipe_buffer = Core::DSP().PipeRead(pipe, size);
|
||||
pipe_buffer = system.DSP().PipeRead(pipe, size);
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
@ -190,23 +172,27 @@ void DSP_DSP::LoadComponent(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push(true); /// Pretend that we actually loaded the DSP firmware
|
||||
rb.Push(true);
|
||||
rb.PushMappedBuffer(buffer);
|
||||
|
||||
// TODO(bunnei): Implement real DSP firmware loading
|
||||
|
||||
std::vector<u8> component_data(size);
|
||||
buffer.Read(component_data.data(), 0, size);
|
||||
|
||||
LOG_INFO(Service_DSP, "Firmware hash: {:#018x}",
|
||||
Common::ComputeHash64(component_data.data(), component_data.size()));
|
||||
// Some versions of the firmware have the location of DSP structures listed here.
|
||||
if (size > 0x37C) {
|
||||
LOG_INFO(Service_DSP, "Structures hash: {:#018x}",
|
||||
Common::ComputeHash64(component_data.data() + 0x340, 60));
|
||||
}
|
||||
LOG_WARNING(Service_DSP, "(STUBBED) called size=0x{:X}, prog_mask=0x{:08X}, data_mask=0x{:08X}",
|
||||
size, prog_mask, data_mask);
|
||||
system.DSP().LoadComponent(component_data);
|
||||
|
||||
LOG_INFO(Service_DSP, "called size=0x{:X}, prog_mask=0x{:08X}, data_mask=0x{:08X}", size,
|
||||
prog_mask, data_mask);
|
||||
}
|
||||
|
||||
void DSP_DSP::UnloadComponent(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x12, 0, 0);
|
||||
|
||||
system.DSP().UnloadComponent();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_INFO(Service_DSP, "(STUBBED)");
|
||||
}
|
||||
|
||||
void DSP_DSP::FlushDataCache(Kernel::HLERequestContext& ctx) {
|
||||
|
@ -282,12 +268,12 @@ void DSP_DSP::GetSemaphoreEventHandle(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
void DSP_DSP::SetSemaphoreMask(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x17, 1, 0);
|
||||
const u32 mask = rp.Pop<u32>();
|
||||
preset_semaphore = rp.Pop<u16>();
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
|
||||
LOG_WARNING(Service_DSP, "(STUBBED) called mask=0x{:08X}", mask);
|
||||
LOG_WARNING(Service_DSP, "(STUBBED) called mask=0x{:04X}", preset_semaphore);
|
||||
}
|
||||
|
||||
void DSP_DSP::GetHeadphoneStatus(Kernel::HLERequestContext& ctx) {
|
||||
|
@ -350,7 +336,8 @@ bool DSP_DSP::HasTooManyEventsRegistered() const {
|
|||
return number >= max_number_of_interrupt_events;
|
||||
}
|
||||
|
||||
DSP_DSP::DSP_DSP(Core::System& system) : ServiceFramework("dsp::DSP", DefaultMaxSessions) {
|
||||
DSP_DSP::DSP_DSP(Core::System& system)
|
||||
: ServiceFramework("dsp::DSP", DefaultMaxSessions), system(system) {
|
||||
static const FunctionInfo functions[] = {
|
||||
// clang-format off
|
||||
{0x00010040, &DSP_DSP::RecvData, "RecvData"},
|
||||
|
@ -370,7 +357,7 @@ DSP_DSP::DSP_DSP(Core::System& system) : ServiceFramework("dsp::DSP", DefaultMax
|
|||
{0x000F0080, &DSP_DSP::GetPipeReadableSize, "GetPipeReadableSize"},
|
||||
{0x001000C0, &DSP_DSP::ReadPipeIfPossible, "ReadPipeIfPossible"},
|
||||
{0x001100C2, &DSP_DSP::LoadComponent, "LoadComponent"},
|
||||
{0x00120000, nullptr, "UnloadComponent"},
|
||||
{0x00120000, &DSP_DSP::UnloadComponent, "UnloadComponent"},
|
||||
{0x00130082, &DSP_DSP::FlushDataCache, "FlushDataCache"},
|
||||
{0x00140082, &DSP_DSP::InvalidateDataCache, "InvalidateDCache"},
|
||||
{0x00150082, &DSP_DSP::RegisterInterruptEvents, "RegisterInterruptEvents"},
|
||||
|
@ -393,6 +380,9 @@ DSP_DSP::DSP_DSP(Core::System& system) : ServiceFramework("dsp::DSP", DefaultMax
|
|||
|
||||
semaphore_event =
|
||||
system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "DSP_DSP::semaphore_event");
|
||||
|
||||
semaphore_event->SetHLENotifier(
|
||||
[this]() { this->system.DSP().SetSemaphore(preset_semaphore); });
|
||||
}
|
||||
|
||||
DSP_DSP::~DSP_DSP() {
|
||||
|
|
|
@ -153,6 +153,15 @@ private:
|
|||
*/
|
||||
void LoadComponent(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* DSP_DSP::UnloadComponent service function
|
||||
* Inputs:
|
||||
* 0 : Header Code[0x00120000]
|
||||
* Outputs:
|
||||
* 1 : Result of function, 0 on success, otherwise error code
|
||||
*/
|
||||
void UnloadComponent(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/**
|
||||
* DSP_DSP::FlushDataCache service function
|
||||
*
|
||||
|
@ -245,7 +254,10 @@ private:
|
|||
/// Checks if we are trying to register more than 6 events
|
||||
bool HasTooManyEventsRegistered() const;
|
||||
|
||||
Core::System& system;
|
||||
|
||||
Kernel::SharedPtr<Kernel::Event> semaphore_event;
|
||||
u16 preset_semaphore = 0;
|
||||
|
||||
Kernel::SharedPtr<Kernel::Event> interrupt_zero = nullptr; /// Currently unknown purpose
|
||||
Kernel::SharedPtr<Kernel::Event> interrupt_one = nullptr; /// Currently unknown purpose
|
||||
|
|
|
@ -79,6 +79,8 @@ void LogSettings() {
|
|||
LogSetting("Layout_Factor3d", Settings::values.factor_3d);
|
||||
LogSetting("Layout_LayoutOption", static_cast<int>(Settings::values.layout_option));
|
||||
LogSetting("Layout_SwapScreen", Settings::values.swap_screen);
|
||||
LogSetting("Audio_EnableDspLle", Settings::values.enable_dsp_lle);
|
||||
LogSetting("Audio_EnableDspLleMultithread", Settings::values.enable_dsp_lle_multithread);
|
||||
LogSetting("Audio_OutputEngine", Settings::values.sink_id);
|
||||
LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching);
|
||||
LogSetting("Audio_OutputDevice", Settings::values.audio_device_id);
|
||||
|
|
|
@ -151,6 +151,8 @@ struct Values {
|
|||
u8 factor_3d;
|
||||
|
||||
// Audio
|
||||
bool enable_dsp_lle;
|
||||
bool enable_dsp_lle_multithread;
|
||||
std::string sink_id;
|
||||
bool enable_audio_stretching;
|
||||
std::string audio_device_id;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue