Re: [PATCH v2 3/5] ASoC: qcom: q6prm: add support for LPASS LPR resource voting
From: Srinivas Kandagatla
Date: Wed Jul 15 2026 - 03:40:22 EST
On 7/14/26 9:43 AM, Prasad Kumpatla wrote:
>
> On 7/14/2026 1:13 PM, Srinivas Kandagatla wrote:
>> On 7/13/26 7:45 PM, Prasad Kumpatla wrote:
>>> Add support for issuing LPASS low-power resource (LPR) votes through
>>> the PRM interface.
>>>
>>> Some platforms (e.g. Hawi) require the LPASS to be kept active via LPR
>>> resource voting instead of the existing hardware core vote mechanism.
>>> Handle this by introducing support for PARAM_ID_RSC_CPU_LPR when the
>>> LPR vote clock ID is requested.
>>>
>>> For LPR requests, use the appropriate parameter ID and payload format
>>> to disable CPU subsystem sleep, ensuring that the LPASS register space
>>> remains accessible.
>>>
>>> Also add the corresponding clock mapping for LPASS_HW_LPR_VOTE and make
>>> the q6dsp clock ID range consistent with the dt-bindings by deriving
>>> it from Q6AFE_MAX_CLK_ID.
>>>
>>> Signed-off-by: Prasad Kumpatla <prasad.kumpatla@xxxxxxxxxxxxxxxx>
>>> ---
>>> sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c | 2 +-
>>> sound/soc/qcom/qdsp6/q6prm-clocks.c | 2 ++
>>> sound/soc/qcom/qdsp6/q6prm.c | 17 +++++++++++++----
>>> sound/soc/qcom/qdsp6/q6prm.h | 1 +
>>> 4 files changed, 17 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c b/sound/soc/
>>> qcom/qdsp6/q6dsp-lpass-clocks.c
>>> index 03838582a..79527a367 100644
>>> --- a/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c
>>> +++ b/sound/soc/qcom/qdsp6/q6dsp-lpass-clocks.c
>>> @@ -12,7 +12,7 @@
>>> #include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
>>> #include "q6dsp-lpass-clocks.h"
>>> -#define Q6DSP_MAX_CLK_ID 104
>>> +#define Q6DSP_MAX_CLK_ID Q6AFE_MAX_CLK_ID
>>> #define Q6DSP_LPASS_CLK_ROOT_DEFAULT 0
>>> diff --git a/sound/soc/qcom/qdsp6/q6prm-clocks.c b/sound/soc/
>>> qcom/qdsp6/q6prm-clocks.c
>>> index 4c574b48a..2b2b3872e 100644
>>> --- a/sound/soc/qcom/qdsp6/q6prm-clocks.c
>>> +++ b/sound/soc/qcom/qdsp6/q6prm-clocks.c
>>> @@ -63,6 +63,8 @@ static const struct q6dsp_clk_init q6prm_clks[] = {
>>> "LPASS_HW_MACRO"),
>>> Q6DSP_VOTE_CLK(LPASS_HW_DCODEC_VOTE, Q6PRM_HW_CORE_ID_DCODEC,
>>> "LPASS_HW_DCODEC"),
>>> + Q6DSP_VOTE_CLK(LPASS_HW_LPR_VOTE, Q6PRM_HW_LPR_VOTE,
>>> + "LPASS_HW_LPR_VOTE"),
>>> };
>>> static const struct q6dsp_clk_desc q6dsp_clk_q6prm __maybe_unused
>>> = {
>>> diff --git a/sound/soc/qcom/qdsp6/q6prm.c b/sound/soc/qcom/qdsp6/q6prm.c
>>> index 04892fb44..7a7a1d3d5 100644
>>> --- a/sound/soc/qcom/qdsp6/q6prm.c
>>> +++ b/sound/soc/qcom/qdsp6/q6prm.c
>>> @@ -31,10 +31,16 @@ struct q6prm {
>>> #define PARAM_ID_RSC_HW_CORE 0x08001032
>>> #define PARAM_ID_RSC_LPASS_CORE 0x0800102B
>>> #define PARAM_ID_RSC_AUDIO_HW_CLK 0x0800102C
>>> +#define PARAM_ID_RSC_CPU_LPR 0x08001A6E
>>> +
>>> +#define LPR_CPU_SS_SLEEP_DISABLED 0x1
>>> struct prm_cmd_request_hw_core {
>>> struct apm_module_param_data param_data;
>>> - uint32_t hw_clk_id;
>>> + union {
>>> + u32 hw_clk_id;
>>> + u32 lpr_state;
>>> + };
>>> } __packed;
>>> struct prm_cmd_request_rsc {
>>> @@ -62,6 +68,7 @@ static int q6prm_set_hw_core_req(struct device
>>> *dev, uint32_t hw_block_id, bool
>>> struct prm_cmd_request_hw_core *req;
>>> gpr_device_t *gdev = prm->gdev;
>>> uint32_t opcode, rsp_opcode;
>>> + bool lpr_req = (hw_block_id == Q6PRM_HW_LPR_VOTE);
>>> if (enable) {
>>> opcode = PRM_CMD_REQUEST_HW_RSC;
>>> @@ -82,10 +89,13 @@ static int q6prm_set_hw_core_req(struct device
>>> *dev, uint32_t hw_block_id, bool
>>> param_data->module_instance_id = GPR_PRM_MODULE_IID;
>>> param_data->error_code = 0;
>>> - param_data->param_id = PARAM_ID_RSC_HW_CORE;
>>> + param_data->param_id = lpr_req ? PARAM_ID_RSC_CPU_LPR :
>>> PARAM_ID_RSC_HW_CORE;
>>> param_data->param_size = sizeof(*req) -
>>> APM_MODULE_PARAM_DATA_SIZE;
>>> - req->hw_clk_id = hw_block_id;
>>> + if (lpr_req)
>>> + req->lpr_state = LPR_CPU_SS_SLEEP_DISABLED;
>> this does not make sense, this should be set based on enable flag, here
>> you are disabling the LPR for both enable and disable request.
> Hi Srini,
>
> The intent here is slightly different from a typical enable/disable
> state variable.
> For PARAM_ID_RSC_CPU_LPR, the payload field (lpr_state) identifies the
> low-power
> resource being controlled, and the DSP API defines a single valid value:
> LPR_CPU_SS_SLEEP_DISABLED(0x1).
>
> The actual operation is encoded by the PRM command:
> PRM_CMD_REQUEST_HW_RSC + LPR_CPU_SS_SLEEP_DISABLED - Requests the
> resource and prevents the subsystem from entering the corresponding low-
> power state.
> PRM_CMD_RELEASE_HW_RSC + LPR_CPU_SS_SLEEP_DISABLED - Releases the
> resource, allowing the subsystem to enter that low-power state again.
>
> In other words, the payload does not represent the desired runtime state
> and is therefore not toggled based on the enable flag.
> Instead, the request/release opcode determines whether the low-power
> state is being blocked or re-enabled, while lpr_state remains
> LPR_CPU_SS_SLEEP_DISABLED for both operations.
>
> Hope this clarifies why the payload remains unchanged across request and
> release paths.
Yes, makes sense,
I would suggest to rename the flag from LPR_CPU_SS_SLEEP_DISABLED to
LPR_CPU_SS_SLEEP_DISABLE
--srini
>
>>
>>
>>> + else
>>> + req->hw_clk_id = hw_block_id;
>>> return q6prm_send_cmd_sync(prm, pkt, rsp_opcode);
>>> }
>>> @@ -94,7 +104,6 @@ int q6prm_vote_lpass_core_hw(struct device *dev,
>>> uint32_t hw_block_id,
>>> const char *client_name, uint32_t *client_handle)
>>> {
>>> return q6prm_set_hw_core_req(dev, hw_block_id, true);
>>> -
>> unnecessary change.
> Agreed, the whitespace change is unrelated and will be dropped in the
> next revision.
>
> Thanks,
> Prasad
>
>>
>>> }
>>> EXPORT_SYMBOL_GPL(q6prm_vote_lpass_core_hw);
>>> diff --git a/sound/soc/qcom/qdsp6/q6prm.h b/sound/soc/qcom/qdsp6/
>>> q6prm.h
>>> index a988a3208..bd5ee0c40 100644
>>> --- a/sound/soc/qcom/qdsp6/q6prm.h
>>> +++ b/sound/soc/qcom/qdsp6/q6prm.h
>>> @@ -87,6 +87,7 @@
>>> #define Q6PRM_LPASS_CLK_ROOT_DEFAULT 0
>>> #define Q6PRM_HW_CORE_ID_LPASS 1
>>> #define Q6PRM_HW_CORE_ID_DCODEC 2
>>> +#define Q6PRM_HW_LPR_VOTE 3
>>> int q6prm_set_lpass_clock(struct device *dev, int clk_id, int
>>> clk_attr,
>>> int clk_root, unsigned int freq);