Path: blob/master/sound/soc/intel/boards/bytcht_nocodec.c
26493 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* bytcht_nocodec.c - ASoc Machine driver for MinnowBoard Max and Up3* to make I2S signals observable on the Low-Speed connector. Audio codec4* is not managed by ASoC/DAPM5*6* Copyright (C) 2015-2017 Intel Corp7*8* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~9*10* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~11*/1213#include <linux/module.h>14#include <sound/pcm.h>15#include <sound/pcm_params.h>16#include <sound/soc.h>17#include "../atom/sst-atom-controls.h"1819static const struct snd_soc_dapm_widget widgets[] = {20SND_SOC_DAPM_MIC("Mic", NULL),21SND_SOC_DAPM_SPK("Speaker", NULL),22};2324static const struct snd_kcontrol_new controls[] = {25SOC_DAPM_PIN_SWITCH("Mic"),26SOC_DAPM_PIN_SWITCH("Speaker"),27};2829static const struct snd_soc_dapm_route audio_map[] = {30{"ssp2 Tx", NULL, "codec_out0"},31{"ssp2 Tx", NULL, "codec_out1"},32{"codec_in0", NULL, "ssp2 Rx"},33{"codec_in1", NULL, "ssp2 Rx"},3435{"ssp2 Rx", NULL, "Mic"},36{"Speaker", NULL, "ssp2 Tx"},37};3839static int codec_fixup(struct snd_soc_pcm_runtime *rtd,40struct snd_pcm_hw_params *params)41{42struct snd_interval *rate = hw_param_interval(params,43SNDRV_PCM_HW_PARAM_RATE);44struct snd_interval *channels = hw_param_interval(params,45SNDRV_PCM_HW_PARAM_CHANNELS);46int ret;4748/* The DSP will convert the FE rate to 48k, stereo, 24bits */49rate->min = rate->max = 48000;50channels->min = channels->max = 2;5152/* set SSP2 to 24-bit */53params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);5455/*56* Default mode for SSP configuration is TDM 4 slot, override config57* with explicit setting to I2S 2ch 24-bit. The word length is set with58* dai_set_tdm_slot() since there is no other API exposed59*/60ret = snd_soc_dai_set_fmt(snd_soc_rtd_to_cpu(rtd, 0),61SND_SOC_DAIFMT_I2S |62SND_SOC_DAIFMT_NB_NF |63SND_SOC_DAIFMT_BP_FP);6465if (ret < 0) {66dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);67return ret;68}6970ret = snd_soc_dai_set_tdm_slot(snd_soc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 24);71if (ret < 0) {72dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);73return ret;74}7576return 0;77}7879static const unsigned int rates_48000[] = {8048000,81};8283static const struct snd_pcm_hw_constraint_list constraints_48000 = {84.count = ARRAY_SIZE(rates_48000),85.list = rates_48000,86};8788static int aif1_startup(struct snd_pcm_substream *substream)89{90return snd_pcm_hw_constraint_list(substream->runtime, 0,91SNDRV_PCM_HW_PARAM_RATE,92&constraints_48000);93}9495static const struct snd_soc_ops aif1_ops = {96.startup = aif1_startup,97};9899SND_SOC_DAILINK_DEF(dummy,100DAILINK_COMP_ARRAY(COMP_DUMMY()));101102SND_SOC_DAILINK_DEF(media,103DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));104105SND_SOC_DAILINK_DEF(deepbuffer,106DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));107108SND_SOC_DAILINK_DEF(ssp2_port,109DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));110111SND_SOC_DAILINK_DEF(platform,112DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));113114static struct snd_soc_dai_link dais[] = {115[MERR_DPCM_AUDIO] = {116.name = "Audio Port",117.stream_name = "Audio",118.ignore_suspend = 1,119.nonatomic = true,120.dynamic = 1,121.ops = &aif1_ops,122SND_SOC_DAILINK_REG(media, dummy, platform),123},124[MERR_DPCM_DEEP_BUFFER] = {125.name = "Deep-Buffer Audio Port",126.stream_name = "Deep-Buffer Audio",127.ignore_suspend = 1,128.nonatomic = true,129.dynamic = 1,130.playback_only = 1,131.ops = &aif1_ops,132SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),133},134/* CODEC<->CODEC link */135/* back ends */136{137.name = "SSP2-LowSpeed Connector",138.id = 0,139.no_pcm = 1,140.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF141| SND_SOC_DAIFMT_CBC_CFC,142.be_hw_params_fixup = codec_fixup,143.ignore_suspend = 1,144SND_SOC_DAILINK_REG(ssp2_port, dummy, platform),145},146};147148/* SoC card */149static struct snd_soc_card bytcht_nocodec_card = {150.name = "bytcht-nocodec",151.owner = THIS_MODULE,152.dai_link = dais,153.num_links = ARRAY_SIZE(dais),154.dapm_widgets = widgets,155.num_dapm_widgets = ARRAY_SIZE(widgets),156.dapm_routes = audio_map,157.num_dapm_routes = ARRAY_SIZE(audio_map),158.controls = controls,159.num_controls = ARRAY_SIZE(controls),160.fully_routed = true,161};162163static int snd_bytcht_nocodec_mc_probe(struct platform_device *pdev)164{165int ret_val = 0;166167/* register the soc card */168bytcht_nocodec_card.dev = &pdev->dev;169170ret_val = devm_snd_soc_register_card(&pdev->dev, &bytcht_nocodec_card);171172if (ret_val) {173dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",174ret_val);175return ret_val;176}177platform_set_drvdata(pdev, &bytcht_nocodec_card);178return ret_val;179}180181static struct platform_driver snd_bytcht_nocodec_mc_driver = {182.driver = {183.name = "bytcht_nocodec",184},185.probe = snd_bytcht_nocodec_mc_probe,186};187module_platform_driver(snd_bytcht_nocodec_mc_driver);188189MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Nocodec Machine driver");190MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>");191MODULE_LICENSE("GPL v2");192MODULE_ALIAS("platform:bytcht_nocodec");193194195