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);