Path: blob/master/sound/soc/mediatek/mt8365/mt8365-mt6357.c
26488 views
// SPDX-License-Identifier: GPL-2.01/*2* MediaTek MT8365 Sound Card driver3*4* Copyright (c) 2024 MediaTek Inc.5* Authors: Nicolas Belin <[email protected]>6*/78#include <linux/array_size.h>9#include <linux/dev_printk.h>10#include <linux/err.h>11#include <linux/mod_devicetable.h>12#include <linux/module.h>13#include <linux/pinctrl/consumer.h>14#include <linux/platform_device.h>15#include <linux/types.h>1617#include <sound/soc.h>18#include <sound/pcm_params.h>1920#include "mt8365-afe-common.h"21#include "../common/mtk-soc-card.h"22#include "../common/mtk-soundcard-driver.h"2324enum pinctrl_pin_state {25PIN_STATE_DEFAULT,26PIN_STATE_DMIC,27PIN_STATE_MISO_OFF,28PIN_STATE_MISO_ON,29PIN_STATE_MOSI_OFF,30PIN_STATE_MOSI_ON,31PIN_STATE_MAX32};3334static const char * const mt8365_mt6357_pin_str[PIN_STATE_MAX] = {35"default",36"dmic",37"miso_off",38"miso_on",39"mosi_off",40"mosi_on",41};4243struct mt8365_mt6357_priv {44struct pinctrl *pinctrl;45struct pinctrl_state *pin_states[PIN_STATE_MAX];46};4748enum {49/* FE */50DAI_LINK_DL1_PLAYBACK = 0,51DAI_LINK_DL2_PLAYBACK,52DAI_LINK_AWB_CAPTURE,53DAI_LINK_VUL_CAPTURE,54/* BE */55DAI_LINK_2ND_I2S_INTF,56DAI_LINK_DMIC,57DAI_LINK_INT_ADDA,58DAI_LINK_NUM59};6061static const struct snd_soc_dapm_widget mt8365_mt6357_widgets[] = {62SND_SOC_DAPM_OUTPUT("HDMI Out"),63};6465static const struct snd_soc_dapm_route mt8365_mt6357_routes[] = {66{"HDMI Out", NULL, "2ND I2S Playback"},67{"DMIC In", NULL, "MICBIAS0"},68};6970static int mt8365_mt6357_int_adda_startup(struct snd_pcm_substream *substream)71{72struct snd_soc_pcm_runtime *rtd = substream->private_data;73struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card);74int ret = 0;7576if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {77if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_ON]))78return ret;7980ret = pinctrl_select_state(priv->pinctrl,81priv->pin_states[PIN_STATE_MOSI_ON]);82if (ret)83dev_err(rtd->card->dev, "%s failed to select state %d\n",84__func__, ret);85}8687if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {88if (IS_ERR(priv->pin_states[PIN_STATE_MISO_ON]))89return ret;9091ret = pinctrl_select_state(priv->pinctrl,92priv->pin_states[PIN_STATE_MISO_ON]);93if (ret)94dev_err(rtd->card->dev, "%s failed to select state %d\n",95__func__, ret);96}9798return 0;99}100101static void mt8365_mt6357_int_adda_shutdown(struct snd_pcm_substream *substream)102{103struct snd_soc_pcm_runtime *rtd = substream->private_data;104struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card);105int ret = 0;106107if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {108if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_OFF]))109return;110111ret = pinctrl_select_state(priv->pinctrl,112priv->pin_states[PIN_STATE_MOSI_OFF]);113if (ret)114dev_err(rtd->card->dev, "%s failed to select state %d\n",115__func__, ret);116}117118if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {119if (IS_ERR(priv->pin_states[PIN_STATE_MISO_OFF]))120return;121122ret = pinctrl_select_state(priv->pinctrl,123priv->pin_states[PIN_STATE_MISO_OFF]);124if (ret)125dev_err(rtd->card->dev, "%s failed to select state %d\n",126__func__, ret);127}128}129130static const struct snd_soc_ops mt8365_mt6357_int_adda_ops = {131.startup = mt8365_mt6357_int_adda_startup,132.shutdown = mt8365_mt6357_int_adda_shutdown,133};134135SND_SOC_DAILINK_DEFS(playback1,136DAILINK_COMP_ARRAY(COMP_CPU("DL1")),137DAILINK_COMP_ARRAY(COMP_DUMMY()),138DAILINK_COMP_ARRAY(COMP_EMPTY()));139SND_SOC_DAILINK_DEFS(playback2,140DAILINK_COMP_ARRAY(COMP_CPU("DL2")),141DAILINK_COMP_ARRAY(COMP_DUMMY()),142DAILINK_COMP_ARRAY(COMP_EMPTY()));143SND_SOC_DAILINK_DEFS(awb_capture,144DAILINK_COMP_ARRAY(COMP_CPU("AWB")),145DAILINK_COMP_ARRAY(COMP_DUMMY()),146DAILINK_COMP_ARRAY(COMP_EMPTY()));147SND_SOC_DAILINK_DEFS(vul,148DAILINK_COMP_ARRAY(COMP_CPU("VUL")),149DAILINK_COMP_ARRAY(COMP_DUMMY()),150DAILINK_COMP_ARRAY(COMP_EMPTY()));151152SND_SOC_DAILINK_DEFS(i2s3,153DAILINK_COMP_ARRAY(COMP_CPU("2ND I2S")),154DAILINK_COMP_ARRAY(COMP_DUMMY()),155DAILINK_COMP_ARRAY(COMP_EMPTY()));156SND_SOC_DAILINK_DEFS(dmic,157DAILINK_COMP_ARRAY(COMP_CPU("DMIC")),158DAILINK_COMP_ARRAY(COMP_DUMMY()),159DAILINK_COMP_ARRAY(COMP_EMPTY()));160SND_SOC_DAILINK_DEFS(primary_codec,161DAILINK_COMP_ARRAY(COMP_CPU("INT ADDA")),162DAILINK_COMP_ARRAY(COMP_CODEC("mt6357-sound", "mt6357-snd-codec-aif1")),163DAILINK_COMP_ARRAY(COMP_EMPTY()));164165/* Digital audio interface glue - connects codec <---> CPU */166static struct snd_soc_dai_link mt8365_mt6357_dais[] = {167/* Front End DAI links */168[DAI_LINK_DL1_PLAYBACK] = {169.name = "DL1_FE",170.stream_name = "MultiMedia1_PLayback",171.id = DAI_LINK_DL1_PLAYBACK,172.trigger = {173SND_SOC_DPCM_TRIGGER_POST,174SND_SOC_DPCM_TRIGGER_POST175},176.dynamic = 1,177.playback_only = 1,178.dpcm_merged_rate = 1,179SND_SOC_DAILINK_REG(playback1),180},181[DAI_LINK_DL2_PLAYBACK] = {182.name = "DL2_FE",183.stream_name = "MultiMedia2_PLayback",184.id = DAI_LINK_DL2_PLAYBACK,185.trigger = {186SND_SOC_DPCM_TRIGGER_POST,187SND_SOC_DPCM_TRIGGER_POST188},189.dynamic = 1,190.playback_only = 1,191.dpcm_merged_rate = 1,192SND_SOC_DAILINK_REG(playback2),193},194[DAI_LINK_AWB_CAPTURE] = {195.name = "AWB_FE",196.stream_name = "DL1_AWB_Record",197.id = DAI_LINK_AWB_CAPTURE,198.trigger = {199SND_SOC_DPCM_TRIGGER_POST,200SND_SOC_DPCM_TRIGGER_POST201},202.dynamic = 1,203.capture_only = 1,204.dpcm_merged_rate = 1,205SND_SOC_DAILINK_REG(awb_capture),206},207[DAI_LINK_VUL_CAPTURE] = {208.name = "VUL_FE",209.stream_name = "MultiMedia1_Capture",210.id = DAI_LINK_VUL_CAPTURE,211.trigger = {212SND_SOC_DPCM_TRIGGER_POST,213SND_SOC_DPCM_TRIGGER_POST214},215.dynamic = 1,216.capture_only = 1,217.dpcm_merged_rate = 1,218SND_SOC_DAILINK_REG(vul),219},220/* Back End DAI links */221[DAI_LINK_2ND_I2S_INTF] = {222.name = "I2S_OUT_BE",223.no_pcm = 1,224.id = DAI_LINK_2ND_I2S_INTF,225.dai_fmt = SND_SOC_DAIFMT_I2S |226SND_SOC_DAIFMT_NB_NF |227SND_SOC_DAIFMT_CBC_CFC,228SND_SOC_DAILINK_REG(i2s3),229},230[DAI_LINK_DMIC] = {231.name = "DMIC_BE",232.no_pcm = 1,233.id = DAI_LINK_DMIC,234.capture_only = 1,235SND_SOC_DAILINK_REG(dmic),236},237[DAI_LINK_INT_ADDA] = {238.name = "MTK_Codec",239.no_pcm = 1,240.id = DAI_LINK_INT_ADDA,241.ops = &mt8365_mt6357_int_adda_ops,242SND_SOC_DAILINK_REG(primary_codec),243},244};245246static int mt8365_mt6357_gpio_probe(struct snd_soc_card *card)247{248struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(card);249int ret, i;250251priv->pinctrl = devm_pinctrl_get(card->dev);252if (IS_ERR(priv->pinctrl)) {253ret = PTR_ERR(priv->pinctrl);254return dev_err_probe(card->dev, ret,255"Failed to get pinctrl\n");256}257258for (i = PIN_STATE_DEFAULT ; i < PIN_STATE_MAX ; i++) {259priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl,260mt8365_mt6357_pin_str[i]);261if (IS_ERR(priv->pin_states[i])) {262dev_info(card->dev, "No pin state for %s\n",263mt8365_mt6357_pin_str[i]);264} else {265ret = pinctrl_select_state(priv->pinctrl,266priv->pin_states[i]);267if (ret) {268dev_err_probe(card->dev, ret,269"Failed to select pin state %s\n",270mt8365_mt6357_pin_str[i]);271return ret;272}273}274}275return 0;276}277278static struct snd_soc_card mt8365_mt6357_soc_card = {279.name = "mt8365-evk",280.owner = THIS_MODULE,281.dai_link = mt8365_mt6357_dais,282.num_links = ARRAY_SIZE(mt8365_mt6357_dais),283.dapm_widgets = mt8365_mt6357_widgets,284.num_dapm_widgets = ARRAY_SIZE(mt8365_mt6357_widgets),285.dapm_routes = mt8365_mt6357_routes,286.num_dapm_routes = ARRAY_SIZE(mt8365_mt6357_routes),287};288289static int mt8365_mt6357_dev_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)290{291struct mtk_platform_card_data *card_data = soc_card_data->card_data;292struct snd_soc_card *card = card_data->card;293struct device *dev = card->dev;294struct mt8365_mt6357_priv *mach_priv;295int ret;296297card->dev = dev;298ret = parse_dai_link_info(card);299if (ret)300goto err;301302mach_priv = devm_kzalloc(dev, sizeof(*mach_priv),303GFP_KERNEL);304if (!mach_priv)305return -ENOMEM;306soc_card_data->mach_priv = mach_priv;307snd_soc_card_set_drvdata(card, soc_card_data);308mt8365_mt6357_gpio_probe(card);309return 0;310311err:312clean_card_reference(card);313return ret;314}315316static const struct mtk_soundcard_pdata mt8365_mt6357_card = {317.card_name = "mt8365-mt6357",318.card_data = &(struct mtk_platform_card_data) {319.card = &mt8365_mt6357_soc_card,320},321.soc_probe = mt8365_mt6357_dev_probe322};323324static const struct of_device_id mt8365_mt6357_dt_match[] = {325{ .compatible = "mediatek,mt8365-mt6357", .data = &mt8365_mt6357_card },326{ /* sentinel */ }327};328MODULE_DEVICE_TABLE(of, mt8365_mt6357_dt_match);329330static struct platform_driver mt8365_mt6357_driver = {331.driver = {332.name = "mt8365_mt6357",333.of_match_table = mt8365_mt6357_dt_match,334.pm = &snd_soc_pm_ops,335},336.probe = mtk_soundcard_common_probe,337};338339module_platform_driver(mt8365_mt6357_driver);340341/* Module information */342MODULE_DESCRIPTION("MT8365 EVK SoC machine driver");343MODULE_AUTHOR("Nicolas Belin <[email protected]>");344MODULE_LICENSE("GPL");345MODULE_ALIAS("platform: mt8365_mt6357");346347348