Path: blob/master/sound/soc/mediatek/mt8173/mt8173-max98090.c
26488 views
// SPDX-License-Identifier: GPL-2.01/*2* mt8173-max98090.c -- MT8173 MAX98090 ALSA SoC machine driver3*4* Copyright (c) 2015 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/max98090.h"1213static struct snd_soc_jack mt8173_max98090_jack;1415static struct snd_soc_jack_pin mt8173_max98090_jack_pins[] = {16{17.pin = "Headphone",18.mask = SND_JACK_HEADPHONE,19},20{21.pin = "Headset Mic",22.mask = SND_JACK_MICROPHONE,23},24};2526static const struct snd_soc_dapm_widget mt8173_max98090_widgets[] = {27SND_SOC_DAPM_SPK("Speaker", NULL),28SND_SOC_DAPM_MIC("Int Mic", NULL),29SND_SOC_DAPM_HP("Headphone", NULL),30SND_SOC_DAPM_MIC("Headset Mic", NULL),31};3233static const struct snd_soc_dapm_route mt8173_max98090_routes[] = {34{"Speaker", NULL, "SPKL"},35{"Speaker", NULL, "SPKR"},36{"DMICL", NULL, "Int Mic"},37{"Headphone", NULL, "HPL"},38{"Headphone", NULL, "HPR"},39{"Headset Mic", NULL, "MICBIAS"},40{"IN34", NULL, "Headset Mic"},41};4243static const struct snd_kcontrol_new mt8173_max98090_controls[] = {44SOC_DAPM_PIN_SWITCH("Speaker"),45SOC_DAPM_PIN_SWITCH("Int Mic"),46SOC_DAPM_PIN_SWITCH("Headphone"),47SOC_DAPM_PIN_SWITCH("Headset Mic"),48};4950static int mt8173_max98090_hw_params(struct snd_pcm_substream *substream,51struct snd_pcm_hw_params *params)52{53struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);54struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);5556return snd_soc_dai_set_sysclk(codec_dai, 0, params_rate(params) * 256,57SND_SOC_CLOCK_IN);58}5960static const struct snd_soc_ops mt8173_max98090_ops = {61.hw_params = mt8173_max98090_hw_params,62};6364static int mt8173_max98090_init(struct snd_soc_pcm_runtime *runtime)65{66int ret;67struct snd_soc_card *card = runtime->card;68struct snd_soc_component *component = snd_soc_rtd_to_codec(runtime, 0)->component;6970/* enable jack detection */71ret = snd_soc_card_jack_new_pins(card, "Headphone", SND_JACK_HEADSET,72&mt8173_max98090_jack,73mt8173_max98090_jack_pins,74ARRAY_SIZE(mt8173_max98090_jack_pins));75if (ret) {76dev_err(card->dev, "Can't create a new Jack %d\n", ret);77return ret;78}7980return max98090_mic_detect(component, &mt8173_max98090_jack);81}8283SND_SOC_DAILINK_DEFS(playback,84DAILINK_COMP_ARRAY(COMP_CPU("DL1")),85DAILINK_COMP_ARRAY(COMP_DUMMY()),86DAILINK_COMP_ARRAY(COMP_EMPTY()));8788SND_SOC_DAILINK_DEFS(capture,89DAILINK_COMP_ARRAY(COMP_CPU("VUL")),90DAILINK_COMP_ARRAY(COMP_DUMMY()),91DAILINK_COMP_ARRAY(COMP_EMPTY()));9293SND_SOC_DAILINK_DEFS(hifi,94DAILINK_COMP_ARRAY(COMP_CPU("I2S")),95DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "HiFi")),96DAILINK_COMP_ARRAY(COMP_EMPTY()));9798/* Digital audio interface glue - connects codec <---> CPU */99static struct snd_soc_dai_link mt8173_max98090_dais[] = {100/* Front End DAI links */101{102.name = "MAX98090 Playback",103.stream_name = "MAX98090 Playback",104.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},105.dynamic = 1,106.playback_only = 1,107SND_SOC_DAILINK_REG(playback),108},109{110.name = "MAX98090 Capture",111.stream_name = "MAX98090 Capture",112.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},113.dynamic = 1,114.capture_only = 1,115SND_SOC_DAILINK_REG(capture),116},117/* Back End DAI links */118{119.name = "Codec",120.no_pcm = 1,121.init = mt8173_max98090_init,122.ops = &mt8173_max98090_ops,123.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |124SND_SOC_DAIFMT_CBC_CFC,125SND_SOC_DAILINK_REG(hifi),126},127};128129static struct snd_soc_card mt8173_max98090_card = {130.name = "mt8173-max98090",131.owner = THIS_MODULE,132.dai_link = mt8173_max98090_dais,133.num_links = ARRAY_SIZE(mt8173_max98090_dais),134.controls = mt8173_max98090_controls,135.num_controls = ARRAY_SIZE(mt8173_max98090_controls),136.dapm_widgets = mt8173_max98090_widgets,137.num_dapm_widgets = ARRAY_SIZE(mt8173_max98090_widgets),138.dapm_routes = mt8173_max98090_routes,139.num_dapm_routes = ARRAY_SIZE(mt8173_max98090_routes),140};141142static int mt8173_max98090_dev_probe(struct platform_device *pdev)143{144struct snd_soc_card *card = &mt8173_max98090_card;145struct device_node *codec_node, *platform_node;146struct snd_soc_dai_link *dai_link;147int ret, i;148149platform_node = of_parse_phandle(pdev->dev.of_node,150"mediatek,platform", 0);151if (!platform_node) {152dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");153return -EINVAL;154}155for_each_card_prelinks(card, i, dai_link) {156if (dai_link->platforms->name)157continue;158dai_link->platforms->of_node = platform_node;159}160161codec_node = of_parse_phandle(pdev->dev.of_node,162"mediatek,audio-codec", 0);163if (!codec_node) {164dev_err(&pdev->dev,165"Property 'audio-codec' missing or invalid\n");166ret = -EINVAL;167goto put_platform_node;168}169for_each_card_prelinks(card, i, dai_link) {170if (dai_link->codecs->name)171continue;172dai_link->codecs->of_node = codec_node;173}174card->dev = &pdev->dev;175176ret = devm_snd_soc_register_card(&pdev->dev, card);177178of_node_put(codec_node);179180put_platform_node:181of_node_put(platform_node);182return ret;183}184185static const struct of_device_id mt8173_max98090_dt_match[] = {186{ .compatible = "mediatek,mt8173-max98090", },187{ }188};189MODULE_DEVICE_TABLE(of, mt8173_max98090_dt_match);190191static struct platform_driver mt8173_max98090_driver = {192.driver = {193.name = "mt8173-max98090",194.of_match_table = mt8173_max98090_dt_match,195.pm = &snd_soc_pm_ops,196},197.probe = mt8173_max98090_dev_probe,198};199200module_platform_driver(mt8173_max98090_driver);201202/* Module information */203MODULE_DESCRIPTION("MT8173 MAX98090 ALSA SoC machine driver");204MODULE_AUTHOR("Koro Chen <[email protected]>");205MODULE_LICENSE("GPL v2");206MODULE_ALIAS("platform:mt8173-max98090");207208209210