diff --git a/nx/include/switch.h b/nx/include/switch.h index 6562f501..f5752f67 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -126,6 +126,7 @@ extern "C" { #include "switch/services/ins.h" #include "switch/services/ectx.h" #include "switch/services/avm.h" +#include "switch/services/mm.h" #include "switch/display/binder.h" #include "switch/display/parcel.h" diff --git a/nx/include/switch/services/mm.h b/nx/include/switch/services/mm.h new file mode 100644 index 00000000..393f661a --- /dev/null +++ b/nx/include/switch/services/mm.h @@ -0,0 +1,30 @@ +/** + * @file mmu.h + * @brief Multimedia (mm) IPC wrapper. + * @author averne + * @copyright libnx Authors + */ + +#pragma once +#include "../types.h" +#include "../sf/service.h" + +typedef enum { + MmuModuleId_Ram = 2, + MmuModuleId_Nvenc = 5, + MmuModuleId_Nvdec = 6, + MmuModuleId_Nvjpg = 7, +} MmuModuleId; + +typedef struct { + MmuModuleId module; + u32 id; +} MmuRequest; + +Result mmuInitialize(void); +void mmuExit(void); + +Result mmuRequestInitialize(MmuRequest *request, MmuModuleId module, u32 unk, bool autoclear); ///< unk is ignored by official software +Result mmuRequestFinalize(MmuRequest *request); +Result mmuRequestGet(MmuRequest *request, u32 *out_freq_hz); +Result mmuRequestSetAndWait(MmuRequest *request, u32 freq_hz, s32 timeout); diff --git a/nx/source/services/mm.c b/nx/source/services/mm.c new file mode 100644 index 00000000..9993a1ed --- /dev/null +++ b/nx/source/services/mm.c @@ -0,0 +1,56 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" +#include "services/mm.h" + +static Service g_mmuSrv; + +NX_GENERATE_SERVICE_GUARD(mmu); + +Result _mmuInitialize(void) { + return smGetService(&g_mmuSrv, "mm:u"); +} + +void _mmuCleanup(void) { + serviceClose(&g_mmuSrv); +} + +Result mmuRequestInitialize(MmuRequest *request, MmuModuleId module, u32 unk, bool autoclear) { + struct { + u32 module_id; + u32 unk; + u32 autoclear; + } data = { module, unk, autoclear }; + u32 out = -1; + + Result rc = serviceDispatchInOut(&g_mmuSrv, 4, data, out); + + if (R_SUCCEEDED(rc)) { + request->module = module; + request->id = out; + } + + return rc; +} + +Result mmuRequestFinalize(MmuRequest *request) { + return serviceDispatchIn(&g_mmuSrv, 5, request->id); +} + +Result mmuRequestSetAndWait(MmuRequest *request, u32 freq_hz, s32 timeout) { + struct { + u32 id; + u32 freq; + s32 timeout; + } data = { request->id, freq_hz, timeout }; + return serviceDispatchIn(&g_mmuSrv, 6, data); +} + +Result mmuRequestGet(MmuRequest *request, u32 *out_freq_hz) { + u32 freq = 0; + Result rc = serviceDispatchInOut(&g_mmuSrv, 7, request->id, freq); + + if (R_SUCCEEDED(rc) && out_freq_hz) + *out_freq_hz = freq; + + return rc; +}