From ae491ce57b4e28a7d5691a81f6170a95370e6afa Mon Sep 17 00:00:00 2001 From: p-sam Date: Sun, 11 Jun 2023 18:10:51 +0000 Subject: [PATCH] Add GetPossibleClockRates method for pcv and clkrst --- nx/include/switch/services/clkrst.h | 1 + nx/include/switch/services/pcv.h | 9 +++++++++ nx/source/services/clkrst.c | 17 +++++++++++++++++ nx/source/services/pcv.c | 25 +++++++++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/nx/include/switch/services/clkrst.h b/nx/include/switch/services/clkrst.h index 305f20f1..761d42ea 100644 --- a/nx/include/switch/services/clkrst.h +++ b/nx/include/switch/services/clkrst.h @@ -27,3 +27,4 @@ Result clkrstOpenSession(ClkrstSession* session_out, PcvModuleId module_id, u32 void clkrstCloseSession(ClkrstSession* session); Result clkrstSetClockRate(ClkrstSession* session, u32 hz); Result clkrstGetClockRate(ClkrstSession* session, u32 *out_hz); +Result clkrstGetPossibleClockRates(ClkrstSession *session, u32 *rates, s32 max_count, PcvClockRatesListType *out_type, s32 *out_count); diff --git a/nx/include/switch/services/pcv.h b/nx/include/switch/services/pcv.h index 3887e9ba..bb55844d 100644 --- a/nx/include/switch/services/pcv.h +++ b/nx/include/switch/services/pcv.h @@ -191,6 +191,13 @@ typedef enum { PcvModuleId_EXTPERIPH2 = 0x40000057, } PcvModuleId; +// Clock list type returned by GetPossibleClockRates +typedef enum { + PcvClockRatesListType_Invalid = 0, + PcvClockRatesListType_Discrete = 1, + PcvClockRatesListType_Range = 2, +} PcvClockRatesListType; + /// Initialize pcv. Result pcvInitialize(void); @@ -210,3 +217,5 @@ Result pcvSetClockRate(PcvModule module, u32 hz); Result pcvSetVoltageEnabled(u32 power_domain, bool state); /// Only available on [1.0.0-7.0.1]. Result pcvGetVoltageEnabled(bool *isEnabled, u32 power_domain); +/// Only available on [1.0.0-7.0.1]. +Result pcvGetPossibleClockRates(PcvModule module, u32 *rates, s32 max_count, PcvClockRatesListType *out_type, s32 *out_count); diff --git a/nx/source/services/clkrst.c b/nx/source/services/clkrst.c index 476c7bea..b9091437 100644 --- a/nx/source/services/clkrst.c +++ b/nx/source/services/clkrst.c @@ -44,3 +44,20 @@ Result clkrstSetClockRate(ClkrstSession* session, u32 hz) { Result clkrstGetClockRate(ClkrstSession* session, u32 *out_hz) { return serviceDispatchOut(&session->s, 8, *out_hz); } + +Result clkrstGetPossibleClockRates(ClkrstSession *session, u32 *rates, s32 max_count, PcvClockRatesListType *out_type, s32 *out_count) { + struct { + s32 type; + s32 count; + } out; + + Result rc = serviceDispatchInOut(&session->s, 10, max_count, out, + .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcAutoSelect, }, + .buffers = { { rates, max_count * sizeof(u32) }, } + ); + + if (R_SUCCEEDED(rc) && out_type) *out_type = out.type; + if (R_SUCCEEDED(rc) && out_count) *out_count = out.count; + + return rc; +} diff --git a/nx/source/services/pcv.c b/nx/source/services/pcv.c index 5ef91cc0..e7b2271f 100644 --- a/nx/source/services/pcv.c +++ b/nx/source/services/pcv.c @@ -94,3 +94,28 @@ Result pcvGetVoltageEnabled(bool *isEnabled, u32 power_domain) { return rc; } + +Result pcvGetPossibleClockRates(PcvModule module, u32 *rates, s32 max_count, PcvClockRatesListType *out_type, s32 *out_count) { + if(hosversionAtLeast(8,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + PcvModule module; + s32 max_count; + } in = { module, max_count }; + + struct { + s32 type; + s32 count; + } out; + + Result rc = serviceDispatchInOut(&g_pcvSrv, 5, in, out, + .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcPointer, }, + .buffers = { { rates, max_count * sizeof(u32) }, } + ); + + if (R_SUCCEEDED(rc) && out_type) *out_type = out.type; + if (R_SUCCEEDED(rc) && out_count) *out_count = out.count; + + return rc; +}