diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi index de7a0658e5000f..e9fa6cbc3c37c5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi @@ -73,11 +73,32 @@ reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; }; - hdmi-sound { - status = "okay"; - compatible = "rockchip,rk3399-hdmi-dp"; - rockchip,cpu = <&i2s2>; - rockchip,codec = <&hdmi>, <&cdn_dp>; + cdn_dp_hdmi_sound: cdn-dp-hdmi-sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,mclk-fs = <256>; + simple-audio-card,name = "cdn-dp-hdmi-sound"; + + simple-audio-card,dai-link@0 { + format = "i2s"; + cpu { + sound-dai = <&i2s2>; + }; + + codec { + sound-dai = <&hdmi 0>; + }; + }; + simple-audio-card,dai-link@1 { + format = "i2s"; + cpu { + sound-dai = <&i2s2>; + }; + + codec { + sound-dai = <&cdn_dp 1>; + }; + }; }; sound { @@ -264,10 +285,6 @@ status = "okay"; }; -&hdmi_sound { - status = "okay"; -}; - &gpu { mali-supply = <&vdd_gpu>; status = "okay"; diff --git a/sound/soc/rockchip/rockchip_hdmi_dp.c b/sound/soc/rockchip/rockchip_hdmi_dp.c index 304d9c90e34fe3..70173ec6ce519e 100644 --- a/sound/soc/rockchip/rockchip_hdmi_dp.c +++ b/sound/soc/rockchip/rockchip_hdmi_dp.c @@ -35,6 +35,18 @@ #define DRV_NAME "rk-hdmi-dp-sound" #define MAX_CODECS 2 +static const struct snd_soc_dapm_widget rk_dapm_widgets[] = { + SND_SOC_DAPM_LINE("HDMI", NULL), +}; + +static const struct snd_soc_dapm_route rk_dapm_routes[] = { + {"HDMI", NULL, "TX"}, +}; + +static const struct snd_kcontrol_new rk_mc_controls[] = { + SOC_DAPM_PIN_SWITCH("HDMI"), +}; + static int rk_hdmi_dp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -142,6 +154,11 @@ static struct snd_soc_ops rockchip_sound_hdmidp_ops = { .hw_params = rk_hdmi_dp_hw_params, }; +SND_SOC_DAILINK_DEFS(audio, + DAILINK_COMP_ARRAY(COMP_CPU(NULL)), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, NULL), COMP_CODEC(NULL, NULL)), + DAILINK_COMP_ARRAY(COMP_PLATFORM(NULL))); + static struct snd_soc_dai_link rk_dailink = { .name = "HDMI-DP", .stream_name = "HDMI-DP", @@ -149,6 +166,7 @@ static struct snd_soc_dai_link rk_dailink = { .ops = &rockchip_sound_hdmidp_ops, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, + SND_SOC_DAILINK_REG(audio), }; static struct snd_soc_card snd_soc_card_rk = { @@ -156,6 +174,12 @@ static struct snd_soc_card snd_soc_card_rk = { .dai_link = &rk_dailink, .num_links = 1, .num_aux_devs = 0, + .dapm_widgets = rk_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rk_dapm_widgets), + .dapm_routes = rk_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rk_dapm_routes), + .controls = rk_mc_controls, + .num_controls = ARRAY_SIZE(rk_mc_controls), }; static int rk_hdmi_dp_probe(struct platform_device *pdev) @@ -163,11 +187,10 @@ static int rk_hdmi_dp_probe(struct platform_device *pdev) struct snd_soc_card *card = &snd_soc_card_rk; struct device_node *np = pdev->dev.of_node; struct snd_soc_dai_link *link = card->dai_link; - struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *codec; struct of_phandle_args args; - struct device_node *node; int count; - int ret = 0, i = 0, idx = 0; + int ret = 0, i = 0; card->dev = &pdev->dev; @@ -176,44 +199,51 @@ static int rk_hdmi_dp_probe(struct platform_device *pdev) return -EINVAL; /* refine codecs, remove unavailable node */ - for (i = 0; i < count; i++) { - node = of_parse_phandle(np, "rockchip,codec", i); - if (!node) - return -ENODEV; - if (of_device_is_available(node)) - idx++; - } - - if (!idx) - return -ENODEV; + link->num_codecs = 0; - codecs = devm_kcalloc(&pdev->dev, idx, - sizeof(*codecs), GFP_KERNEL); - link->codecs = codecs; - link->num_codecs = idx; - idx = 0; for (i = 0; i < count; i++) { - node = of_parse_phandle(np, "rockchip,codec", i); - if (!node) - return -ENODEV; - if (!of_device_is_available(node)) + codec = &link->codecs[link->num_codecs]; + + codec->of_node = of_parse_phandle(np, "rockchip,codec", i); + if (!codec->of_node) { + dev_err(&pdev->dev, + "Property 'rockchip,codec' missing or invalid\n"); + return -EINVAL; + } + + if (!of_device_is_available(codec->of_node)) { + dev_err(&pdev->dev, + "Property 'rockchip,codec' is not available\n"); continue; + } ret = of_parse_phandle_with_fixed_args(np, "rockchip,codec", 0, i, &args); - if (ret) + if (ret) { + dev_err(&pdev->dev, + "Unable to parse property 'rockchip,codec'\n"); return ret; + } - codecs[idx].of_node = node; - ret = snd_soc_get_dai_name(&args, &codecs[idx].dai_name); + ret = snd_soc_get_dai_name(&args, &codec->dai_name); if (ret) return ret; - idx++; + + link->num_codecs++; + } + + if (!link->num_codecs) { + dev_err(&pdev->dev, + "Property 'rockchip,cpu' missing or invalid\n"); + return -ENODEV; } link->cpus->of_node = of_parse_phandle(np, "rockchip,cpu", 0); - if (!link->cpus->of_node) + if (!link->cpus->of_node) { + dev_err(&pdev->dev, + "Property 'rockchip,cpu' missing or invalid\n"); return -ENODEV; + } link->platforms->of_node = link->cpus->of_node; ret = devm_snd_soc_register_card(&pdev->dev, card);