From 7fa9c2d5d59bea4c8ac036e15252f3b13171b48d Mon Sep 17 00:00:00 2001 From: William Norman Date: Thu, 10 Sep 2026 15:12:42 +0800 Subject: [PATCH 1/6] misc: fastrpc: allow initial audio PD creation Signed-off-by: William Norman --- drivers/misc/fastrpc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 8bda3e503b68f..0a24a0763486b 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1616,7 +1616,9 @@ static int fastrpc_mmap_remove_pdr(struct fastrpc_user *fl) if (session < 0) return -EUSERS; - if (atomic_read(&fl->cctx->spd[session].ispdup) == 0) + /* The service cannot be up before its initial static PD is created. */ + if (fl->cctx->spd[session].pdrcount && + atomic_read(&fl->cctx->spd[session].ispdup) == 0) return -ENOTCONN; if (fl->cctx->spd[session].pdrcount != From 8553d40d676ec3c58512ac9944484d34e7ee16e8 Mon Sep 17 00:00:00 2001 From: William Norman Date: Fri, 11 Sep 2026 11:15:29 +0800 Subject: [PATCH 2/6] ASoC: qcom: sc8280xp: add VMARC Q9075 DP sound card support Add a sound card for the Radxa VMARC Q9075 IO board. The card exposes a single DisplayPort DAI link with a "DP0 Jack" widget so that audio can be routed over the on-board DisplayPort output. Also enable CONFIG_SND_SOC_SC8280XP so that the driver is built. Signed-off-by: William Norman --- arch/arm64/configs/qcom_addons.config | 2 +- sound/soc/qcom/sc8280xp.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm64/configs/qcom_addons.config b/arch/arm64/configs/qcom_addons.config index 231d62b4effc6..8115c3140120c 100644 --- a/arch/arm64/configs/qcom_addons.config +++ b/arch/arm64/configs/qcom_addons.config @@ -55,4 +55,4 @@ CONFIG_VIRT_DRIVERS=y CONFIG_SENSORS_EMC2305=y CONFIG_HWMON=y CONFIG_SND_SOC_QCS9100=m - +CONFIG_SND_SOC_SC8280XP=m diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 4532c4b75ce41..abb6aa1334025 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -46,6 +46,10 @@ static struct snd_soc_dapm_widget qcs9100_dapm_widgets[] = { SND_SOC_DAPM_SPK("DP0 Jack", NULL), }; +static const struct snd_soc_dapm_widget vmarc_q9075_dapm_widgets[] = { + SND_SOC_DAPM_SPK("DP0 Jack", NULL), +}; + static const struct snd_soc_dapm_route qcs9100_dapm_routes[] = { {"Speaker", NULL, "MI2S_PINCTRL"}, {"DMic", NULL, "MI2S_PINCTRL"}, @@ -70,6 +74,12 @@ static struct snd_soc_common qcs9100_priv_data = { .num_dapm_routes = ARRAY_SIZE(qcs9100_dapm_routes), }; +static const struct snd_soc_common vmarc_q9075_priv_data = { + .driver_name = "sa8775p", + .dapm_widgets = vmarc_q9075_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(vmarc_q9075_dapm_widgets), +}; + static struct snd_soc_common lemans_amr_priv_data = { .driver_name = "sa8775p", .dapm_widgets = sc8280xp_dapm_widgets, @@ -341,6 +351,7 @@ static int sc8280xp_platform_probe(struct platform_device *pdev) } static const struct of_device_id snd_sc8280xp_dt_match[] = { + {.compatible = "radxa,vmarc-q9075-sndcard", .data = &vmarc_q9075_priv_data}, {.compatible = "qcom,qcm6490-idp-sndcard", .data = &qcm6490_priv_data}, {.compatible = "qcom,qcs615-sndcard", .data = &qcs615_priv_data}, {.compatible = "qcom,qcs6490-rb3gen2-sndcard", .data = &qcs6490_priv_data}, From 6ef11130cd754c3b904b77ed076c13b49cddc762 Mon Sep 17 00:00:00 2001 From: William Norman Date: Fri, 11 Sep 2026 11:15:29 +0800 Subject: [PATCH 3/6] arm64: dts: qcom: qcs9075-radxa-vmarc-q9075: add DP sound card Describe the DisplayPort audio DAI link on the Radxa VMARC Q9075 IO board: the CPU DAI is the ADSP DISPLAY_PORT_RX_0 bedai, the codec is the MDSS0 DisplayPort controller and the platform is the ADSP APM. The DP enablement overlay switches the codec over to MDSS1 when the board is configured for the DisplayPort output. Also document the new sndcard compatible. Signed-off-by: William Norman --- .../bindings/sound/qcom,sm8250.yaml | 3 +++ .../dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 6f419747273e3..8db00a38d3579 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -27,9 +27,12 @@ properties: - qcom,sm8650-sndcard - const: qcom,sm8450-sndcard - enum: + - radxa,vmarc-q9075-sndcard - qcom,apq8016-sbc-sndcard - qcom,msm8916-qdsp6-sndcard - qcom,qrb5165-rb5-sndcard + - qcom,qcs9075-sndcard + - qcom,qcs9100-sndcard - qcom,sc7180-qdsp6-sndcard - qcom,sc8280xp-sndcard - qcom,sdm845-sndcard diff --git a/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi b/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi index 628be2d2f1943..4308689d7fe12 100644 --- a/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi @@ -83,6 +83,27 @@ stdout-path = "serial0:115200n8"; }; + sound { + compatible = "radxa,vmarc-q9075-sndcard"; + model = "VMARC-Q9075-DP"; + + dp0-dai-link { + link-name = "DISPLAY_PORT-RX"; + + cpu { + sound-dai = <&q6apmbedai DISPLAY_PORT_RX_0>; + }; + + codec { + sound-dai = <&mdss0_dp0>; + }; + + platform { + sound-dai = <&q6apm>; + }; + }; + }; + vcc_5v0_regulator: vcc-5v0-regulator { compatible = "regulator-fixed"; regulator-name = "vcc_5v0"; From 9f8b07b136e6bcbaad12651f05349513ce84e2a1 Mon Sep 17 00:00:00 2001 From: William Norman Date: Mon, 14 Sep 2026 14:18:22 +0800 Subject: [PATCH 4/6] dt-bindings: display: msm: add Radxa DP audio properties Document the board controller index used by VMARC audio firmware and the CH7218 fixed-EDID audio capability override. Signed-off-by: William Norman --- .../bindings/display/msm/dp-controller.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index ae53cbfb21932..0045423594b62 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -102,6 +102,17 @@ properties: "#sound-dai-cells": const: 0 + radxa,display-controller-index: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Index of the display controller used by board audio firmware. + maximum: 1 + + radxa,force-audio: + type: boolean + description: + Forces audio support for a DP-to-HDMI bridge whose fixed EDID omits the + CTA audio data block. + vdda-0p9-supply: deprecated: true vdda-1p2-supply: From aadbe46f9d0c106c0c8e0742afcdf3b2c6262949 Mon Sep 17 00:00:00 2001 From: William Norman Date: Mon, 14 Sep 2026 14:19:09 +0800 Subject: [PATCH 5/6] ASoC: qcom: select VMARC display audio controller Keep the standard DPTX index local to each LPASS block and pass the MDSS controller through a separate VMARC parameter derived from the active codec node. Signed-off-by: William Norman --- .../dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi | 5 ++ sound/soc/qcom/qdsp6/audioreach.c | 24 +++++++++- sound/soc/qcom/qdsp6/audioreach.h | 8 ++++ sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 48 +++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi b/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi index 4308689d7fe12..2be1e7960a455 100644 --- a/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi @@ -713,9 +713,14 @@ }; &mdss0_dp0 { + radxa,display-controller-index = <0>; status = "okay"; }; +&mdss1_dp0 { + radxa,display-controller-index = <1>; +}; + &mdss0_dp0_out { data-lanes = <0 1 2 3>; link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>; diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index 7922a6cea0e57..741cb6173b88a 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -203,6 +203,13 @@ struct apm_display_port_module_intf_cfg { } __packed; #define APM_DP_INTF_CFG_PSIZE ALIGN(sizeof(struct apm_display_port_module_intf_cfg), 8) +struct apm_vmarc_display_ctrl_cfg { + struct apm_module_param_data param_data; + struct param_id_vmarc_display_ctrl_cfg cfg; +} __packed; + +#define APM_VMARC_DISPLAY_CTRL_CFG_PSIZE ALIGN(sizeof(struct apm_vmarc_display_ctrl_cfg), 8) + static void *__audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr) { @@ -611,10 +618,11 @@ static int audioreach_display_port_set_media_format(struct q6apm_graph *graph, struct audioreach_module_config *cfg) { struct apm_display_port_module_intf_cfg *intf_cfg; + struct apm_vmarc_display_ctrl_cfg *ctrl_cfg; struct apm_module_frame_size_factor_cfg *fs_cfg; struct apm_module_param_data *param_data; struct apm_module_hw_ep_mf_cfg *hw_cfg; - int ic_sz, ep_sz, fs_sz, dl_sz; + int ic_sz, ep_sz, fs_sz, ctrl_sz, dl_sz; int rc, payload_size; struct gpr_pkt *pkt; void *p; @@ -622,9 +630,10 @@ static int audioreach_display_port_set_media_format(struct q6apm_graph *graph, ic_sz = APM_DP_INTF_CFG_PSIZE; ep_sz = APM_HW_EP_CFG_PSIZE; fs_sz = APM_FS_CFG_PSIZE; + ctrl_sz = cfg->has_display_ctrl_idx ? APM_VMARC_DISPLAY_CTRL_CFG_PSIZE : 0; dl_sz = 0; - payload_size = ic_sz + ep_sz + fs_sz + dl_sz; + payload_size = ic_sz + ep_sz + fs_sz + ctrl_sz + dl_sz; pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); if (IS_ERR(pkt)) @@ -654,6 +663,17 @@ static int audioreach_display_port_set_media_format(struct q6apm_graph *graph, fs_cfg->frame_size_factor = 1; p += fs_sz; + if (cfg->has_display_ctrl_idx) { + ctrl_cfg = p; + param_data = &ctrl_cfg->param_data; + param_data->module_instance_id = module->instance_id; + param_data->error_code = 0; + param_data->param_id = PARAM_ID_VMARC_DISPLAY_CTRL_CFG; + param_data->param_size = ctrl_sz - APM_MODULE_PARAM_DATA_SIZE; + ctrl_cfg->cfg.display_ctrl_idx = cfg->display_ctrl_idx; + p += ctrl_sz; + } + intf_cfg = p; param_data = &intf_cfg->param_data; param_data->module_instance_id = module->instance_id; diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 2c82917b71621..6fbb26ce731ec 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -483,6 +483,12 @@ struct param_id_display_port_intf_cfg { uint32_t dptx_idx; } __packed; +#define PARAM_ID_VMARC_DISPLAY_CTRL_CFG 0x0800F001 + +struct param_id_vmarc_display_ctrl_cfg { + u32 display_ctrl_idx; +} __packed; + #define PARAM_ID_HW_EP_MF_CFG 0x08001017 struct param_id_hw_ep_mf { uint32_t sample_rate; @@ -757,6 +763,8 @@ struct audioreach_module_config { u16 num_channels; u16 active_channels_mask; u16 dp_idx; + u8 display_ctrl_idx; + bool has_display_ctrl_idx; u32 channel_allocation; u32 sd_line_mask; int fmt; diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c index 9f51bf2882ae7..81622e2cd7c41 100644 --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c @@ -109,11 +109,47 @@ static int q6dma_set_channel_map(struct snd_soc_dai *dai, return 0; } +/* + * Resolve the codec device node of a DAI link from the sound card's DT node. + * The DAI link component's of_node is not populated for links parsed by + * snd_soc_of_get_dai_link_codecs(), so walk the "link-name" matching child and + * dereference its "codec"/"sound-dai" phandle instead. + */ +static struct device_node *q6hdmi_codec_of_node(struct snd_soc_pcm_runtime *rtd) +{ + struct device_node *sound_np = rtd->card->dev->of_node; + struct device_node *link_np, *codec_np, *codec_of = NULL; + const char *link_name; + + if (!sound_np || !rtd->dai_link->name) + return NULL; + + for_each_child_of_node(sound_np, link_np) { + if (of_property_read_string(link_np, "link-name", &link_name)) + continue; + if (strcmp(link_name, rtd->dai_link->name)) + continue; + + codec_np = of_get_child_by_name(link_np, "codec"); + if (codec_np) { + codec_of = of_parse_phandle(codec_np, "sound-dai", 0); + of_node_put(codec_np); + } + of_node_put(link_np); + break; + } + + return codec_of; +} + static int q6hdmi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev); struct audioreach_module_config *cfg = &dai_data->module_config[dai->id]; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct device_node *dp_np = q6hdmi_codec_of_node(rtd); + u32 display_ctrl_idx; int channels = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS)->max; int ret; @@ -130,6 +166,18 @@ static int q6hdmi_hw_params(struct snd_pcm_substream *substream, break; } + cfg->has_display_ctrl_idx = false; + if (dp_np && + !of_property_read_u32(dp_np, "radxa,display-controller-index", &display_ctrl_idx)) { + if (display_ctrl_idx > 1) { + of_node_put(dp_np); + return -EINVAL; + } + cfg->display_ctrl_idx = display_ctrl_idx; + cfg->has_display_ctrl_idx = true; + } + of_node_put(dp_np); + ret = q6dsp_get_channel_allocation(channels); if (ret < 0) return ret; From 55b7bddfb0d19cc4e9c26251dd8a39c8cc4d57c9 Mon Sep 17 00:00:00 2001 From: William Norman Date: Mon, 14 Sep 2026 14:19:45 +0800 Subject: [PATCH 6/6] drm/msm/dp: force audio for the VMARC HDMI bridge Allow the VMARC CH7218 path to initialize DP audio even when the bridge fallback EDID omits its CTA audio data block. Signed-off-by: William Norman --- arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi b/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi index 2be1e7960a455..45b45cafd3d96 100644 --- a/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs9075-radxa-vmarc-q9075.dtsi @@ -714,6 +714,7 @@ &mdss0_dp0 { radxa,display-controller-index = <0>; + radxa,force-audio; status = "okay"; }; diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index bb050b5e03078..d79d0f3a0133c 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -497,7 +497,9 @@ static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) dp->msm_dp_display.psr_supported = dp->panel->psr_cap.version && psr_enabled; - dp->audio_supported = info->has_audio; + dp->audio_supported = info->has_audio || + of_property_read_bool(dp->msm_dp_display.pdev->dev.of_node, + "radxa,force-audio"); msm_dp_panel_handle_sink_request(dp->panel); /*