Re: [PATCH v1 2/4] ASoC: qcom: q6prm: add support for LPASS LPR resource voting
From: Bartosz Golaszewski
Date: Thu Jul 09 2026 - 04:30:33 EST
On Wed, 8 Jul 2026 13:49:22 +0200, Prasad Kumpatla
<prasad.kumpatla@xxxxxxxxxxxxxxxx> said:
> 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 | 18 ++++++++++++++----
> sound/soc/qcom/qdsp6/q6prm.h | 1 +
> 4 files changed, 18 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..22ace8bcb 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;
Please use braces here for better readability.
>
> 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;
> + 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);
> -
> }
> EXPORT_SYMBOL_GPL(q6prm_vote_lpass_core_hw);
>
> @@ -210,6 +219,7 @@ static int prm_probe(gpr_device_t *gdev)
> cc->gdev = gdev;
> mutex_init(&cc->lock);
> init_waitqueue_head(&cc->wait);
> +
> dev_set_drvdata(dev, cc);
These newline ninja changes are just unneeded noise in this patch.
>
> if (!q6apm_is_adsp_ready())
> 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);
> --
> 2.34.1
>
>
Bart