root/sound/soc/intel/boards/bytcht_nocodec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. codec_fixup
  2. aif1_startup
  3. snd_bytcht_nocodec_mc_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  bytcht_nocodec.c - ASoc Machine driver for MinnowBoard Max and Up
   4  *  to make I2S signals observable on the Low-Speed connector. Audio codec
   5  *  is not managed by ASoC/DAPM
   6  *
   7  *  Copyright (C) 2015-2017 Intel Corp
   8  *
   9  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10  *
  11  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  12  */
  13 
  14 #include <linux/module.h>
  15 #include <sound/pcm.h>
  16 #include <sound/pcm_params.h>
  17 #include <sound/soc.h>
  18 #include "../atom/sst-atom-controls.h"
  19 
  20 static const struct snd_soc_dapm_widget widgets[] = {
  21         SND_SOC_DAPM_MIC("Mic", NULL),
  22         SND_SOC_DAPM_SPK("Speaker", NULL),
  23 };
  24 
  25 static const struct snd_kcontrol_new controls[] = {
  26         SOC_DAPM_PIN_SWITCH("Mic"),
  27         SOC_DAPM_PIN_SWITCH("Speaker"),
  28 };
  29 
  30 static const struct snd_soc_dapm_route audio_map[] = {
  31         {"ssp2 Tx", NULL, "codec_out0"},
  32         {"ssp2 Tx", NULL, "codec_out1"},
  33         {"codec_in0", NULL, "ssp2 Rx"},
  34         {"codec_in1", NULL, "ssp2 Rx"},
  35 
  36         {"ssp2 Rx", NULL, "Mic"},
  37         {"Speaker", NULL, "ssp2 Tx"},
  38 };
  39 
  40 static int codec_fixup(struct snd_soc_pcm_runtime *rtd,
  41                             struct snd_pcm_hw_params *params)
  42 {
  43         struct snd_interval *rate = hw_param_interval(params,
  44                         SNDRV_PCM_HW_PARAM_RATE);
  45         struct snd_interval *channels = hw_param_interval(params,
  46                                                 SNDRV_PCM_HW_PARAM_CHANNELS);
  47         int ret;
  48 
  49         /* The DSP will convert the FE rate to 48k, stereo, 24bits */
  50         rate->min = rate->max = 48000;
  51         channels->min = channels->max = 2;
  52 
  53         /* set SSP2 to 24-bit */
  54         params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
  55 
  56         /*
  57          * Default mode for SSP configuration is TDM 4 slot, override config
  58          * with explicit setting to I2S 2ch 24-bit. The word length is set with
  59          * dai_set_tdm_slot() since there is no other API exposed
  60          */
  61         ret = snd_soc_dai_set_fmt(rtd->cpu_dai,
  62                                   SND_SOC_DAIFMT_I2S     |
  63                                   SND_SOC_DAIFMT_NB_NF   |
  64                                   SND_SOC_DAIFMT_CBS_CFS);
  65 
  66         if (ret < 0) {
  67                 dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret);
  68                 return ret;
  69         }
  70 
  71         ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24);
  72         if (ret < 0) {
  73                 dev_err(rtd->dev, "can't set I2S config, err %d\n", ret);
  74                 return ret;
  75         }
  76 
  77         return 0;
  78 }
  79 
  80 static const unsigned int rates_48000[] = {
  81         48000,
  82 };
  83 
  84 static const struct snd_pcm_hw_constraint_list constraints_48000 = {
  85         .count = ARRAY_SIZE(rates_48000),
  86         .list  = rates_48000,
  87 };
  88 
  89 static int aif1_startup(struct snd_pcm_substream *substream)
  90 {
  91         return snd_pcm_hw_constraint_list(substream->runtime, 0,
  92                         SNDRV_PCM_HW_PARAM_RATE,
  93                         &constraints_48000);
  94 }
  95 
  96 static struct snd_soc_ops aif1_ops = {
  97         .startup = aif1_startup,
  98 };
  99 
 100 SND_SOC_DAILINK_DEF(dummy,
 101         DAILINK_COMP_ARRAY(COMP_DUMMY()));
 102 
 103 SND_SOC_DAILINK_DEF(media,
 104         DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
 105 
 106 SND_SOC_DAILINK_DEF(deepbuffer,
 107         DAILINK_COMP_ARRAY(COMP_CPU("deepbuffer-cpu-dai")));
 108 
 109 SND_SOC_DAILINK_DEF(ssp2_port,
 110         DAILINK_COMP_ARRAY(COMP_CPU("ssp2-port")));
 111 
 112 SND_SOC_DAILINK_DEF(platform,
 113         DAILINK_COMP_ARRAY(COMP_PLATFORM("sst-mfld-platform")));
 114 
 115 static struct snd_soc_dai_link dais[] = {
 116         [MERR_DPCM_AUDIO] = {
 117                 .name = "Audio Port",
 118                 .stream_name = "Audio",
 119                 .ignore_suspend = 1,
 120                 .nonatomic = true,
 121                 .dynamic = 1,
 122                 .dpcm_playback = 1,
 123                 .dpcm_capture = 1,
 124                 .ops = &aif1_ops,
 125                 SND_SOC_DAILINK_REG(media, dummy, platform),
 126         },
 127         [MERR_DPCM_DEEP_BUFFER] = {
 128                 .name = "Deep-Buffer Audio Port",
 129                 .stream_name = "Deep-Buffer Audio",
 130                 .ignore_suspend = 1,
 131                 .nonatomic = true,
 132                 .dynamic = 1,
 133                 .dpcm_playback = 1,
 134                 .ops = &aif1_ops,
 135                 SND_SOC_DAILINK_REG(deepbuffer, dummy, platform),
 136         },
 137         /* CODEC<->CODEC link */
 138         /* back ends */
 139         {
 140                 .name = "SSP2-LowSpeed Connector",
 141                 .id = 0,
 142                 .no_pcm = 1,
 143                 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
 144                                                 | SND_SOC_DAIFMT_CBS_CFS,
 145                 .be_hw_params_fixup = codec_fixup,
 146                 .ignore_suspend = 1,
 147                 .nonatomic = true,
 148                 .dpcm_playback = 1,
 149                 .dpcm_capture = 1,
 150                 SND_SOC_DAILINK_REG(ssp2_port, dummy, platform),
 151         },
 152 };
 153 
 154 /* SoC card */
 155 static struct snd_soc_card bytcht_nocodec_card = {
 156         .name = "bytcht-nocodec",
 157         .owner = THIS_MODULE,
 158         .dai_link = dais,
 159         .num_links = ARRAY_SIZE(dais),
 160         .dapm_widgets = widgets,
 161         .num_dapm_widgets = ARRAY_SIZE(widgets),
 162         .dapm_routes = audio_map,
 163         .num_dapm_routes = ARRAY_SIZE(audio_map),
 164         .controls = controls,
 165         .num_controls = ARRAY_SIZE(controls),
 166         .fully_routed = true,
 167 };
 168 
 169 static int snd_bytcht_nocodec_mc_probe(struct platform_device *pdev)
 170 {
 171         int ret_val = 0;
 172 
 173         /* register the soc card */
 174         bytcht_nocodec_card.dev = &pdev->dev;
 175 
 176         ret_val = devm_snd_soc_register_card(&pdev->dev, &bytcht_nocodec_card);
 177 
 178         if (ret_val) {
 179                 dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
 180                         ret_val);
 181                 return ret_val;
 182         }
 183         platform_set_drvdata(pdev, &bytcht_nocodec_card);
 184         return ret_val;
 185 }
 186 
 187 static struct platform_driver snd_bytcht_nocodec_mc_driver = {
 188         .driver = {
 189                 .name = "bytcht_nocodec",
 190         },
 191         .probe = snd_bytcht_nocodec_mc_probe,
 192 };
 193 module_platform_driver(snd_bytcht_nocodec_mc_driver);
 194 
 195 MODULE_DESCRIPTION("ASoC Intel(R) Baytrail/Cherrytrail Nocodec Machine driver");
 196 MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>");
 197 MODULE_LICENSE("GPL v2");
 198 MODULE_ALIAS("platform:bytcht_nocodec");

/* [<][>][^][v][top][bottom][index][help] */