1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * mt2701-hdmi.c -- MT2701 HDMI ALSA SoC machine driver 4 * 5 * Copyright (c) 2026 Daniel Golle <daniel@makrotopia.org> 6 * 7 * Based on mt2701-cs42448.c 8 */ 9 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/platform_device.h> 13 #include <sound/soc.h> 14 15 enum { 16 DAI_LINK_FE_HDMI_OUT, 17 DAI_LINK_BE_HDMI_I2S, 18 }; 19 20 SND_SOC_DAILINK_DEFS(fe_hdmi_out, 21 DAILINK_COMP_ARRAY(COMP_CPU("PCM_HDMI")), 22 DAILINK_COMP_ARRAY(COMP_DUMMY()), 23 DAILINK_COMP_ARRAY(COMP_EMPTY())); 24 25 SND_SOC_DAILINK_DEFS(be_hdmi_i2s, 26 DAILINK_COMP_ARRAY(COMP_CPU("HDMI I2S")), 27 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), 28 DAILINK_COMP_ARRAY(COMP_EMPTY())); 29 30 static struct snd_soc_dai_link mt2701_hdmi_dai_links[] = { 31 [DAI_LINK_FE_HDMI_OUT] = { 32 .name = "HDMI Playback", 33 .stream_name = "HDMI Playback", 34 .trigger = { SND_SOC_DPCM_TRIGGER_POST, 35 SND_SOC_DPCM_TRIGGER_POST }, 36 .dynamic = 1, 37 .playback_only = 1, 38 SND_SOC_DAILINK_REG(fe_hdmi_out), 39 }, 40 [DAI_LINK_BE_HDMI_I2S] = { 41 .name = "HDMI BE", 42 .no_pcm = 1, 43 .playback_only = 1, 44 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 45 SND_SOC_DAIFMT_CBC_CFC, 46 SND_SOC_DAILINK_REG(be_hdmi_i2s), 47 }, 48 }; 49 50 static struct snd_soc_card mt2701_hdmi_soc_card = { 51 .name = "mt2701-hdmi", 52 .owner = THIS_MODULE, 53 .dai_link = mt2701_hdmi_dai_links, 54 .num_links = ARRAY_SIZE(mt2701_hdmi_dai_links), 55 }; 56 57 static int mt2701_hdmi_machine_probe(struct platform_device *pdev) 58 { 59 struct snd_soc_card *card = &mt2701_hdmi_soc_card; 60 struct device *dev = &pdev->dev; 61 struct device_node *platform_node; 62 struct device_node *codec_node; 63 struct snd_soc_dai_link *dai_link; 64 int ret; 65 int i; 66 67 platform_node = of_parse_phandle(dev->of_node, "mediatek,platform", 0); 68 if (!platform_node) 69 return dev_err_probe(dev, -EINVAL, 70 "Property 'mediatek,platform' missing\n"); 71 72 for_each_card_prelinks(card, i, dai_link) { 73 if (dai_link->platforms->name) 74 continue; 75 dai_link->platforms->of_node = platform_node; 76 } 77 78 codec_node = of_parse_phandle(dev->of_node, "mediatek,audio-codec", 0); 79 if (!codec_node) { 80 of_node_put(platform_node); 81 return dev_err_probe(dev, -EINVAL, 82 "Property 'mediatek,audio-codec' missing\n"); 83 } 84 mt2701_hdmi_dai_links[DAI_LINK_BE_HDMI_I2S].codecs->of_node = codec_node; 85 86 card->dev = dev; 87 88 ret = devm_snd_soc_register_card(dev, card); 89 90 of_node_put(platform_node); 91 of_node_put(codec_node); 92 return ret; 93 } 94 95 static const struct of_device_id mt2701_hdmi_machine_dt_match[] = { 96 { .compatible = "mediatek,mt2701-hdmi-audio" }, 97 { .compatible = "mediatek,mt7623n-hdmi-audio" }, 98 {} 99 }; 100 MODULE_DEVICE_TABLE(of, mt2701_hdmi_machine_dt_match); 101 102 static struct platform_driver mt2701_hdmi_machine = { 103 .driver = { 104 .name = "mt2701-hdmi", 105 .of_match_table = mt2701_hdmi_machine_dt_match, 106 }, 107 .probe = mt2701_hdmi_machine_probe, 108 }; 109 module_platform_driver(mt2701_hdmi_machine); 110 111 MODULE_DESCRIPTION("MT2701 HDMI ALSA SoC machine driver"); 112 MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>"); 113 MODULE_LICENSE("GPL"); 114 MODULE_ALIAS("platform:mt2701-hdmi"); 115