Path: blob/master/sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c
26488 views
// SPDX-License-Identifier: GPL-2.01/*2* mt8173-rt5650-rt5514.c -- MT8173 machine driver with RT5650/5514 codecs3*4* Copyright (c) 2016 MediaTek Inc.5* Author: Koro Chen <[email protected]>6*/78#include <linux/module.h>9#include <sound/soc.h>10#include <sound/jack.h>11#include "../../codecs/rt5645.h"1213#define MCLK_FOR_CODECS 122880001415static const struct snd_soc_dapm_widget mt8173_rt5650_rt5514_widgets[] = {16SND_SOC_DAPM_SPK("Speaker", NULL),17SND_SOC_DAPM_MIC("Int Mic", NULL),18SND_SOC_DAPM_HP("Headphone", NULL),19SND_SOC_DAPM_MIC("Headset Mic", NULL),20};2122static const struct snd_soc_dapm_route mt8173_rt5650_rt5514_routes[] = {23{"Speaker", NULL, "SPOL"},24{"Speaker", NULL, "SPOR"},25{"Sub DMIC1L", NULL, "Int Mic"},26{"Sub DMIC1R", NULL, "Int Mic"},27{"Headphone", NULL, "HPOL"},28{"Headphone", NULL, "HPOR"},29{"IN1P", NULL, "Headset Mic"},30{"IN1N", NULL, "Headset Mic"},31};3233static const struct snd_kcontrol_new mt8173_rt5650_rt5514_controls[] = {34SOC_DAPM_PIN_SWITCH("Speaker"),35SOC_DAPM_PIN_SWITCH("Int Mic"),36SOC_DAPM_PIN_SWITCH("Headphone"),37SOC_DAPM_PIN_SWITCH("Headset Mic"),38};3940static struct snd_soc_jack_pin mt8173_rt5650_rt5514_jack_pins[] = {41{42.pin = "Headphone",43.mask = SND_JACK_HEADPHONE,44},45{46.pin = "Headset Mic",47.mask = SND_JACK_MICROPHONE,48},49};5051static int mt8173_rt5650_rt5514_hw_params(struct snd_pcm_substream *substream,52struct snd_pcm_hw_params *params)53{54struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);55struct snd_soc_dai *codec_dai;56int i, ret;5758for_each_rtd_codec_dais(rtd, i, codec_dai) {59/* pll from mclk 12.288M */60ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS,61params_rate(params) * 512);62if (ret)63return ret;6465/* sysclk from pll */66ret = snd_soc_dai_set_sysclk(codec_dai, 1,67params_rate(params) * 512,68SND_SOC_CLOCK_IN);69if (ret)70return ret;71}72return 0;73}7475static const struct snd_soc_ops mt8173_rt5650_rt5514_ops = {76.hw_params = mt8173_rt5650_rt5514_hw_params,77};7879static struct snd_soc_jack mt8173_rt5650_rt5514_jack;8081static int mt8173_rt5650_rt5514_init(struct snd_soc_pcm_runtime *runtime)82{83struct snd_soc_card *card = runtime->card;84struct snd_soc_component *component = snd_soc_rtd_to_codec(runtime, 0)->component;85int ret;8687rt5645_sel_asrc_clk_src(component,88RT5645_DA_STEREO_FILTER |89RT5645_AD_STEREO_FILTER,90RT5645_CLK_SEL_I2S1_ASRC);9192/* enable jack detection */93ret = snd_soc_card_jack_new_pins(card, "Headset Jack",94SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |95SND_JACK_BTN_0 | SND_JACK_BTN_1 |96SND_JACK_BTN_2 | SND_JACK_BTN_3,97&mt8173_rt5650_rt5514_jack,98mt8173_rt5650_rt5514_jack_pins,99ARRAY_SIZE(mt8173_rt5650_rt5514_jack_pins));100if (ret) {101dev_err(card->dev, "Can't new Headset Jack %d\n", ret);102return ret;103}104105return rt5645_set_jack_detect(component,106&mt8173_rt5650_rt5514_jack,107&mt8173_rt5650_rt5514_jack,108&mt8173_rt5650_rt5514_jack);109}110111enum {112DAI_LINK_PLAYBACK,113DAI_LINK_CAPTURE,114DAI_LINK_CODEC_I2S,115};116117SND_SOC_DAILINK_DEFS(playback,118DAILINK_COMP_ARRAY(COMP_CPU("DL1")),119DAILINK_COMP_ARRAY(COMP_DUMMY()),120DAILINK_COMP_ARRAY(COMP_EMPTY()));121122SND_SOC_DAILINK_DEFS(capture,123DAILINK_COMP_ARRAY(COMP_CPU("VUL")),124DAILINK_COMP_ARRAY(COMP_DUMMY()),125DAILINK_COMP_ARRAY(COMP_EMPTY()));126127SND_SOC_DAILINK_DEFS(codec,128DAILINK_COMP_ARRAY(COMP_CPU("I2S")),129DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5645-aif1"),130COMP_CODEC(NULL, "rt5514-aif1")),131DAILINK_COMP_ARRAY(COMP_EMPTY()));132133/* Digital audio interface glue - connects codec <---> CPU */134static struct snd_soc_dai_link mt8173_rt5650_rt5514_dais[] = {135/* Front End DAI links */136[DAI_LINK_PLAYBACK] = {137.name = "rt5650_rt5514 Playback",138.stream_name = "rt5650_rt5514 Playback",139.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},140.dynamic = 1,141.playback_only = 1,142SND_SOC_DAILINK_REG(playback),143},144[DAI_LINK_CAPTURE] = {145.name = "rt5650_rt5514 Capture",146.stream_name = "rt5650_rt5514 Capture",147.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},148.dynamic = 1,149.capture_only = 1,150SND_SOC_DAILINK_REG(capture),151},152/* Back End DAI links */153[DAI_LINK_CODEC_I2S] = {154.name = "Codec",155.no_pcm = 1,156.init = mt8173_rt5650_rt5514_init,157.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |158SND_SOC_DAIFMT_CBC_CFC,159.ops = &mt8173_rt5650_rt5514_ops,160.ignore_pmdown_time = 1,161SND_SOC_DAILINK_REG(codec),162},163};164165static struct snd_soc_codec_conf mt8173_rt5650_rt5514_codec_conf[] = {166{167.name_prefix = "Sub",168},169};170171static struct snd_soc_card mt8173_rt5650_rt5514_card = {172.name = "mtk-rt5650-rt5514",173.owner = THIS_MODULE,174.dai_link = mt8173_rt5650_rt5514_dais,175.num_links = ARRAY_SIZE(mt8173_rt5650_rt5514_dais),176.codec_conf = mt8173_rt5650_rt5514_codec_conf,177.num_configs = ARRAY_SIZE(mt8173_rt5650_rt5514_codec_conf),178.controls = mt8173_rt5650_rt5514_controls,179.num_controls = ARRAY_SIZE(mt8173_rt5650_rt5514_controls),180.dapm_widgets = mt8173_rt5650_rt5514_widgets,181.num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_rt5514_widgets),182.dapm_routes = mt8173_rt5650_rt5514_routes,183.num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_rt5514_routes),184};185186static int mt8173_rt5650_rt5514_dev_probe(struct platform_device *pdev)187{188struct snd_soc_card *card = &mt8173_rt5650_rt5514_card;189struct device_node *platform_node;190struct snd_soc_dai_link *dai_link;191int i, ret;192193platform_node = of_parse_phandle(pdev->dev.of_node,194"mediatek,platform", 0);195if (!platform_node) {196dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");197return -EINVAL;198}199200for_each_card_prelinks(card, i, dai_link) {201if (dai_link->platforms->name)202continue;203dai_link->platforms->of_node = platform_node;204}205206mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node =207of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0);208if (!mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[0].of_node) {209dev_err(&pdev->dev,210"Property 'audio-codec' missing or invalid\n");211ret = -EINVAL;212goto out;213}214mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node =215of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1);216if (!mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node) {217dev_err(&pdev->dev,218"Property 'audio-codec' missing or invalid\n");219ret = -EINVAL;220goto out;221}222mt8173_rt5650_rt5514_codec_conf[0].dlc.of_node =223mt8173_rt5650_rt5514_dais[DAI_LINK_CODEC_I2S].codecs[1].of_node;224225card->dev = &pdev->dev;226227ret = devm_snd_soc_register_card(&pdev->dev, card);228229out:230of_node_put(platform_node);231return ret;232}233234static const struct of_device_id mt8173_rt5650_rt5514_dt_match[] = {235{ .compatible = "mediatek,mt8173-rt5650-rt5514", },236{ }237};238MODULE_DEVICE_TABLE(of, mt8173_rt5650_rt5514_dt_match);239240static struct platform_driver mt8173_rt5650_rt5514_driver = {241.driver = {242.name = "mtk-rt5650-rt5514",243.of_match_table = mt8173_rt5650_rt5514_dt_match,244.pm = &snd_soc_pm_ops,245},246.probe = mt8173_rt5650_rt5514_dev_probe,247};248249module_platform_driver(mt8173_rt5650_rt5514_driver);250251/* Module information */252MODULE_DESCRIPTION("MT8173 RT5650 and RT5514 SoC machine driver");253MODULE_AUTHOR("Koro Chen <[email protected]>");254MODULE_LICENSE("GPL v2");255MODULE_ALIAS("platform:mtk-rt5650-rt5514");256257258259