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: 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..45b45cafd3d96 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"; @@ -692,9 +713,15 @@ }; &mdss0_dp0 { + radxa,display-controller-index = <0>; + radxa,force-audio; 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/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/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); /* 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 != 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; 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},