162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * mt8173-rt5650.c -- MT8173 machine driver with RT5650 codecs 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2016 MediaTek Inc. 662306a36Sopenharmony_ci * Author: Koro Chen <koro.chen@mediatek.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/gpio.h> 1162306a36Sopenharmony_ci#include <linux/of_gpio.h> 1262306a36Sopenharmony_ci#include <sound/soc.h> 1362306a36Sopenharmony_ci#include <sound/jack.h> 1462306a36Sopenharmony_ci#include "../../codecs/rt5645.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define MCLK_FOR_CODECS 12288000 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cienum mt8173_rt5650_mclk { 1962306a36Sopenharmony_ci MT8173_RT5650_MCLK_EXTERNAL = 0, 2062306a36Sopenharmony_ci MT8173_RT5650_MCLK_INTERNAL, 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct mt8173_rt5650_platform_data { 2462306a36Sopenharmony_ci enum mt8173_rt5650_mclk pll_from; 2562306a36Sopenharmony_ci /* 0 = external oscillator; 1 = internal source from mt8173 */ 2662306a36Sopenharmony_ci}; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic struct mt8173_rt5650_platform_data mt8173_rt5650_priv = { 2962306a36Sopenharmony_ci .pll_from = MT8173_RT5650_MCLK_EXTERNAL, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget mt8173_rt5650_widgets[] = { 3362306a36Sopenharmony_ci SND_SOC_DAPM_SPK("Ext Spk", NULL), 3462306a36Sopenharmony_ci SND_SOC_DAPM_MIC("Int Mic", NULL), 3562306a36Sopenharmony_ci SND_SOC_DAPM_HP("Headphone", NULL), 3662306a36Sopenharmony_ci SND_SOC_DAPM_MIC("Headset Mic", NULL), 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic const struct snd_soc_dapm_route mt8173_rt5650_routes[] = { 4062306a36Sopenharmony_ci {"Ext Spk", NULL, "SPOL"}, 4162306a36Sopenharmony_ci {"Ext Spk", NULL, "SPOR"}, 4262306a36Sopenharmony_ci {"DMIC L1", NULL, "Int Mic"}, 4362306a36Sopenharmony_ci {"DMIC R1", NULL, "Int Mic"}, 4462306a36Sopenharmony_ci {"Headphone", NULL, "HPOL"}, 4562306a36Sopenharmony_ci {"Headphone", NULL, "HPOR"}, 4662306a36Sopenharmony_ci {"IN1P", NULL, "Headset Mic"}, 4762306a36Sopenharmony_ci {"IN1N", NULL, "Headset Mic"}, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic const struct snd_kcontrol_new mt8173_rt5650_controls[] = { 5162306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Ext Spk"), 5262306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Int Mic"), 5362306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Headphone"), 5462306a36Sopenharmony_ci SOC_DAPM_PIN_SWITCH("Headset Mic"), 5562306a36Sopenharmony_ci}; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic struct snd_soc_jack_pin mt8173_rt5650_jack_pins[] = { 5862306a36Sopenharmony_ci { 5962306a36Sopenharmony_ci .pin = "Headphone", 6062306a36Sopenharmony_ci .mask = SND_JACK_HEADPHONE, 6162306a36Sopenharmony_ci }, 6262306a36Sopenharmony_ci { 6362306a36Sopenharmony_ci .pin = "Headset Mic", 6462306a36Sopenharmony_ci .mask = SND_JACK_MICROPHONE, 6562306a36Sopenharmony_ci }, 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic int mt8173_rt5650_hw_params(struct snd_pcm_substream *substream, 6962306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 7262306a36Sopenharmony_ci unsigned int mclk_clock; 7362306a36Sopenharmony_ci struct snd_soc_dai *codec_dai; 7462306a36Sopenharmony_ci int i, ret; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci switch (mt8173_rt5650_priv.pll_from) { 7762306a36Sopenharmony_ci case MT8173_RT5650_MCLK_EXTERNAL: 7862306a36Sopenharmony_ci /* mclk = 12.288M */ 7962306a36Sopenharmony_ci mclk_clock = MCLK_FOR_CODECS; 8062306a36Sopenharmony_ci break; 8162306a36Sopenharmony_ci case MT8173_RT5650_MCLK_INTERNAL: 8262306a36Sopenharmony_ci /* mclk = sampling rate*256 */ 8362306a36Sopenharmony_ci mclk_clock = params_rate(params) * 256; 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci default: 8662306a36Sopenharmony_ci /* mclk = 12.288M */ 8762306a36Sopenharmony_ci mclk_clock = MCLK_FOR_CODECS; 8862306a36Sopenharmony_ci break; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci for_each_rtd_codec_dais(rtd, i, codec_dai) { 9262306a36Sopenharmony_ci /* pll from mclk */ 9362306a36Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, 0, mclk_clock, 9462306a36Sopenharmony_ci params_rate(params) * 512); 9562306a36Sopenharmony_ci if (ret) 9662306a36Sopenharmony_ci return ret; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci /* sysclk from pll */ 9962306a36Sopenharmony_ci ret = snd_soc_dai_set_sysclk(codec_dai, 1, 10062306a36Sopenharmony_ci params_rate(params) * 512, 10162306a36Sopenharmony_ci SND_SOC_CLOCK_IN); 10262306a36Sopenharmony_ci if (ret) 10362306a36Sopenharmony_ci return ret; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci return 0; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic const struct snd_soc_ops mt8173_rt5650_ops = { 10962306a36Sopenharmony_ci .hw_params = mt8173_rt5650_hw_params, 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic struct snd_soc_jack mt8173_rt5650_jack, mt8173_rt5650_hdmi_jack; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic int mt8173_rt5650_init(struct snd_soc_pcm_runtime *runtime) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci struct snd_soc_card *card = runtime->card; 11762306a36Sopenharmony_ci struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; 11862306a36Sopenharmony_ci const char *codec_capture_dai = asoc_rtd_to_codec(runtime, 1)->name; 11962306a36Sopenharmony_ci int ret; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci rt5645_sel_asrc_clk_src(component, 12262306a36Sopenharmony_ci RT5645_DA_STEREO_FILTER, 12362306a36Sopenharmony_ci RT5645_CLK_SEL_I2S1_ASRC); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (!strcmp(codec_capture_dai, "rt5645-aif1")) { 12662306a36Sopenharmony_ci rt5645_sel_asrc_clk_src(component, 12762306a36Sopenharmony_ci RT5645_AD_STEREO_FILTER, 12862306a36Sopenharmony_ci RT5645_CLK_SEL_I2S1_ASRC); 12962306a36Sopenharmony_ci } else if (!strcmp(codec_capture_dai, "rt5645-aif2")) { 13062306a36Sopenharmony_ci rt5645_sel_asrc_clk_src(component, 13162306a36Sopenharmony_ci RT5645_AD_STEREO_FILTER, 13262306a36Sopenharmony_ci RT5645_CLK_SEL_I2S2_ASRC); 13362306a36Sopenharmony_ci } else { 13462306a36Sopenharmony_ci dev_warn(card->dev, 13562306a36Sopenharmony_ci "Only one dai codec found in DTS, enabled rt5645 AD filter\n"); 13662306a36Sopenharmony_ci rt5645_sel_asrc_clk_src(component, 13762306a36Sopenharmony_ci RT5645_AD_STEREO_FILTER, 13862306a36Sopenharmony_ci RT5645_CLK_SEL_I2S1_ASRC); 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* enable jack detection */ 14262306a36Sopenharmony_ci ret = snd_soc_card_jack_new_pins(card, "Headset Jack", 14362306a36Sopenharmony_ci SND_JACK_HEADPHONE | SND_JACK_MICROPHONE | 14462306a36Sopenharmony_ci SND_JACK_BTN_0 | SND_JACK_BTN_1 | 14562306a36Sopenharmony_ci SND_JACK_BTN_2 | SND_JACK_BTN_3, 14662306a36Sopenharmony_ci &mt8173_rt5650_jack, 14762306a36Sopenharmony_ci mt8173_rt5650_jack_pins, 14862306a36Sopenharmony_ci ARRAY_SIZE(mt8173_rt5650_jack_pins)); 14962306a36Sopenharmony_ci if (ret) { 15062306a36Sopenharmony_ci dev_err(card->dev, "Can't new Headset Jack %d\n", ret); 15162306a36Sopenharmony_ci return ret; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci return rt5645_set_jack_detect(component, 15562306a36Sopenharmony_ci &mt8173_rt5650_jack, 15662306a36Sopenharmony_ci &mt8173_rt5650_jack, 15762306a36Sopenharmony_ci &mt8173_rt5650_jack); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic int mt8173_rt5650_hdmi_init(struct snd_soc_pcm_runtime *rtd) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci int ret; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, 16562306a36Sopenharmony_ci &mt8173_rt5650_hdmi_jack); 16662306a36Sopenharmony_ci if (ret) 16762306a36Sopenharmony_ci return ret; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci return snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, 17062306a36Sopenharmony_ci &mt8173_rt5650_hdmi_jack, NULL); 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cienum { 17462306a36Sopenharmony_ci DAI_LINK_PLAYBACK, 17562306a36Sopenharmony_ci DAI_LINK_CAPTURE, 17662306a36Sopenharmony_ci DAI_LINK_HDMI, 17762306a36Sopenharmony_ci DAI_LINK_CODEC_I2S, 17862306a36Sopenharmony_ci DAI_LINK_HDMI_I2S, 17962306a36Sopenharmony_ci}; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(playback, 18262306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("DL1")), 18362306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 18462306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(capture, 18762306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("VUL")), 18862306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 18962306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(hdmi_pcm, 19262306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), 19362306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 19462306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(codec, 19762306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("I2S")), 19862306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1"), /* Playback */ 19962306a36Sopenharmony_ci COMP_CODEC(NULL, "rt5645-aif1")),/* Capture */ 20062306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciSND_SOC_DAILINK_DEFS(hdmi_be, 20362306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("HDMIO")), 20462306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), 20562306a36Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* Digital audio interface glue - connects codec <---> CPU */ 20862306a36Sopenharmony_cistatic struct snd_soc_dai_link mt8173_rt5650_dais[] = { 20962306a36Sopenharmony_ci /* Front End DAI links */ 21062306a36Sopenharmony_ci [DAI_LINK_PLAYBACK] = { 21162306a36Sopenharmony_ci .name = "rt5650 Playback", 21262306a36Sopenharmony_ci .stream_name = "rt5650 Playback", 21362306a36Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 21462306a36Sopenharmony_ci .dynamic = 1, 21562306a36Sopenharmony_ci .dpcm_playback = 1, 21662306a36Sopenharmony_ci SND_SOC_DAILINK_REG(playback), 21762306a36Sopenharmony_ci }, 21862306a36Sopenharmony_ci [DAI_LINK_CAPTURE] = { 21962306a36Sopenharmony_ci .name = "rt5650 Capture", 22062306a36Sopenharmony_ci .stream_name = "rt5650 Capture", 22162306a36Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 22262306a36Sopenharmony_ci .dynamic = 1, 22362306a36Sopenharmony_ci .dpcm_capture = 1, 22462306a36Sopenharmony_ci SND_SOC_DAILINK_REG(capture), 22562306a36Sopenharmony_ci }, 22662306a36Sopenharmony_ci [DAI_LINK_HDMI] = { 22762306a36Sopenharmony_ci .name = "HDMI", 22862306a36Sopenharmony_ci .stream_name = "HDMI PCM", 22962306a36Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, 23062306a36Sopenharmony_ci .dynamic = 1, 23162306a36Sopenharmony_ci .dpcm_playback = 1, 23262306a36Sopenharmony_ci SND_SOC_DAILINK_REG(hdmi_pcm), 23362306a36Sopenharmony_ci }, 23462306a36Sopenharmony_ci /* Back End DAI links */ 23562306a36Sopenharmony_ci [DAI_LINK_CODEC_I2S] = { 23662306a36Sopenharmony_ci .name = "Codec", 23762306a36Sopenharmony_ci .no_pcm = 1, 23862306a36Sopenharmony_ci .init = mt8173_rt5650_init, 23962306a36Sopenharmony_ci .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 24062306a36Sopenharmony_ci SND_SOC_DAIFMT_CBS_CFS, 24162306a36Sopenharmony_ci .ops = &mt8173_rt5650_ops, 24262306a36Sopenharmony_ci .ignore_pmdown_time = 1, 24362306a36Sopenharmony_ci .dpcm_playback = 1, 24462306a36Sopenharmony_ci .dpcm_capture = 1, 24562306a36Sopenharmony_ci SND_SOC_DAILINK_REG(codec), 24662306a36Sopenharmony_ci }, 24762306a36Sopenharmony_ci [DAI_LINK_HDMI_I2S] = { 24862306a36Sopenharmony_ci .name = "HDMI BE", 24962306a36Sopenharmony_ci .no_pcm = 1, 25062306a36Sopenharmony_ci .dpcm_playback = 1, 25162306a36Sopenharmony_ci .init = mt8173_rt5650_hdmi_init, 25262306a36Sopenharmony_ci SND_SOC_DAILINK_REG(hdmi_be), 25362306a36Sopenharmony_ci }, 25462306a36Sopenharmony_ci}; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic struct snd_soc_card mt8173_rt5650_card = { 25762306a36Sopenharmony_ci .name = "mtk-rt5650", 25862306a36Sopenharmony_ci .owner = THIS_MODULE, 25962306a36Sopenharmony_ci .dai_link = mt8173_rt5650_dais, 26062306a36Sopenharmony_ci .num_links = ARRAY_SIZE(mt8173_rt5650_dais), 26162306a36Sopenharmony_ci .controls = mt8173_rt5650_controls, 26262306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(mt8173_rt5650_controls), 26362306a36Sopenharmony_ci .dapm_widgets = mt8173_rt5650_widgets, 26462306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_widgets), 26562306a36Sopenharmony_ci .dapm_routes = mt8173_rt5650_routes, 26662306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_routes), 26762306a36Sopenharmony_ci}; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic int mt8173_rt5650_dev_probe(struct platform_device *pdev) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct snd_soc_card *card = &mt8173_rt5650_card; 27262306a36Sopenharmony_ci struct device_node *platform_node; 27362306a36Sopenharmony_ci struct device_node *np; 27462306a36Sopenharmony_ci const char *codec_capture_dai; 27562306a36Sopenharmony_ci struct snd_soc_dai_link *dai_link; 27662306a36Sopenharmony_ci int i, ret; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci platform_node = of_parse_phandle(pdev->dev.of_node, 27962306a36Sopenharmony_ci "mediatek,platform", 0); 28062306a36Sopenharmony_ci if (!platform_node) { 28162306a36Sopenharmony_ci dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); 28262306a36Sopenharmony_ci return -EINVAL; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci for_each_card_prelinks(card, i, dai_link) { 28662306a36Sopenharmony_ci if (dai_link->platforms->name) 28762306a36Sopenharmony_ci continue; 28862306a36Sopenharmony_ci dai_link->platforms->of_node = platform_node; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node = 29262306a36Sopenharmony_ci of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0); 29362306a36Sopenharmony_ci if (!mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) { 29462306a36Sopenharmony_ci dev_err(&pdev->dev, 29562306a36Sopenharmony_ci "Property 'audio-codec' missing or invalid\n"); 29662306a36Sopenharmony_ci ret = -EINVAL; 29762306a36Sopenharmony_ci goto put_platform_node; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node = 30062306a36Sopenharmony_ci mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci np = of_get_child_by_name(pdev->dev.of_node, "codec-capture"); 30362306a36Sopenharmony_ci if (np) { 30462306a36Sopenharmony_ci ret = snd_soc_of_get_dai_name(np, &codec_capture_dai, 0); 30562306a36Sopenharmony_ci of_node_put(np); 30662306a36Sopenharmony_ci if (ret < 0) { 30762306a36Sopenharmony_ci dev_err(&pdev->dev, 30862306a36Sopenharmony_ci "%s codec_capture_dai name fail %d\n", 30962306a36Sopenharmony_ci __func__, ret); 31062306a36Sopenharmony_ci goto put_platform_node; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci mt8173_rt5650_dais[DAI_LINK_CODEC_I2S].codecs[1].dai_name = 31362306a36Sopenharmony_ci codec_capture_dai; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (device_property_present(&pdev->dev, "mediatek,mclk")) { 31762306a36Sopenharmony_ci ret = device_property_read_u32(&pdev->dev, 31862306a36Sopenharmony_ci "mediatek,mclk", 31962306a36Sopenharmony_ci &mt8173_rt5650_priv.pll_from); 32062306a36Sopenharmony_ci if (ret) { 32162306a36Sopenharmony_ci dev_err(&pdev->dev, 32262306a36Sopenharmony_ci "%s snd_soc_register_card fail %d\n", 32362306a36Sopenharmony_ci __func__, ret); 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci mt8173_rt5650_dais[DAI_LINK_HDMI_I2S].codecs->of_node = 32862306a36Sopenharmony_ci of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1); 32962306a36Sopenharmony_ci if (!mt8173_rt5650_dais[DAI_LINK_HDMI_I2S].codecs->of_node) { 33062306a36Sopenharmony_ci dev_err(&pdev->dev, 33162306a36Sopenharmony_ci "Property 'audio-codec' missing or invalid\n"); 33262306a36Sopenharmony_ci ret = -EINVAL; 33362306a36Sopenharmony_ci goto put_platform_node; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci card->dev = &pdev->dev; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci ret = devm_snd_soc_register_card(&pdev->dev, card); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ciput_platform_node: 34062306a36Sopenharmony_ci of_node_put(platform_node); 34162306a36Sopenharmony_ci return ret; 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic const struct of_device_id mt8173_rt5650_dt_match[] = { 34562306a36Sopenharmony_ci { .compatible = "mediatek,mt8173-rt5650", }, 34662306a36Sopenharmony_ci { } 34762306a36Sopenharmony_ci}; 34862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, mt8173_rt5650_dt_match); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic struct platform_driver mt8173_rt5650_driver = { 35162306a36Sopenharmony_ci .driver = { 35262306a36Sopenharmony_ci .name = "mtk-rt5650", 35362306a36Sopenharmony_ci .of_match_table = mt8173_rt5650_dt_match, 35462306a36Sopenharmony_ci .pm = &snd_soc_pm_ops, 35562306a36Sopenharmony_ci }, 35662306a36Sopenharmony_ci .probe = mt8173_rt5650_dev_probe, 35762306a36Sopenharmony_ci}; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cimodule_platform_driver(mt8173_rt5650_driver); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci/* Module information */ 36262306a36Sopenharmony_ciMODULE_DESCRIPTION("MT8173 RT5650 SoC machine driver"); 36362306a36Sopenharmony_ciMODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>"); 36462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 36562306a36Sopenharmony_ciMODULE_ALIAS("platform:mtk-rt5650"); 36662306a36Sopenharmony_ci 367