root/sound/soc/samsung/smdk_wm8580.c

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

DEFINITIONS

This source file includes following definitions.
  1. smdk_hw_params
  2. smdk_wm8580_init_paiftx
  3. smdk_audio_init
  4. smdk_audio_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 //
   3 // Copyright (c) 2009 Samsung Electronics Co. Ltd
   4 // Author: Jaswinder Singh <jassisinghbrar@gmail.com>
   5 
   6 #include <linux/module.h>
   7 #include <sound/soc.h>
   8 #include <sound/pcm_params.h>
   9 
  10 #include "../codecs/wm8580.h"
  11 #include "i2s.h"
  12 
  13 /*
  14  * Default CFG switch settings to use this driver:
  15  *
  16  *   SMDK6410: Set CFG1 1-3 Off, CFG2 1-4 On
  17  */
  18 
  19 /* SMDK has a 12MHZ crystal attached to WM8580 */
  20 #define SMDK_WM8580_FREQ 12000000
  21 
  22 static int smdk_hw_params(struct snd_pcm_substream *substream,
  23         struct snd_pcm_hw_params *params)
  24 {
  25         struct snd_soc_pcm_runtime *rtd = substream->private_data;
  26         struct snd_soc_dai *codec_dai = rtd->codec_dai;
  27         unsigned int pll_out;
  28         int rfs, ret;
  29 
  30         switch (params_width(params)) {
  31         case 8:
  32         case 16:
  33                 break;
  34         default:
  35                 return -EINVAL;
  36         }
  37 
  38         /* The Fvco for WM8580 PLLs must fall within [90,100]MHz.
  39          * This criterion can't be met if we request PLL output
  40          * as {8000x256, 64000x256, 11025x256}Hz.
  41          * As a wayout, we rather change rfs to a minimum value that
  42          * results in (params_rate(params) * rfs), and itself, acceptable
  43          * to both - the CODEC and the CPU.
  44          */
  45         switch (params_rate(params)) {
  46         case 16000:
  47         case 22050:
  48         case 32000:
  49         case 44100:
  50         case 48000:
  51         case 88200:
  52         case 96000:
  53                 rfs = 256;
  54                 break;
  55         case 64000:
  56                 rfs = 384;
  57                 break;
  58         case 8000:
  59         case 11025:
  60                 rfs = 512;
  61                 break;
  62         default:
  63                 return -EINVAL;
  64         }
  65         pll_out = params_rate(params) * rfs;
  66 
  67         /* Set WM8580 to drive MCLK from its PLLA */
  68         ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,
  69                                         WM8580_CLKSRC_PLLA);
  70         if (ret < 0)
  71                 return ret;
  72 
  73         ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
  74                                         SMDK_WM8580_FREQ, pll_out);
  75         if (ret < 0)
  76                 return ret;
  77 
  78         ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA,
  79                                      pll_out, SND_SOC_CLOCK_IN);
  80         if (ret < 0)
  81                 return ret;
  82 
  83         return 0;
  84 }
  85 
  86 /*
  87  * SMDK WM8580 DAI operations.
  88  */
  89 static struct snd_soc_ops smdk_ops = {
  90         .hw_params = smdk_hw_params,
  91 };
  92 
  93 /* SMDK Playback widgets */
  94 static const struct snd_soc_dapm_widget smdk_wm8580_dapm_widgets[] = {
  95         SND_SOC_DAPM_HP("Front", NULL),
  96         SND_SOC_DAPM_HP("Center+Sub", NULL),
  97         SND_SOC_DAPM_HP("Rear", NULL),
  98 
  99         SND_SOC_DAPM_MIC("MicIn", NULL),
 100         SND_SOC_DAPM_LINE("LineIn", NULL),
 101 };
 102 
 103 /* SMDK-PAIFTX connections */
 104 static const struct snd_soc_dapm_route smdk_wm8580_audio_map[] = {
 105         /* MicIn feeds AINL */
 106         {"AINL", NULL, "MicIn"},
 107 
 108         /* LineIn feeds AINL/R */
 109         {"AINL", NULL, "LineIn"},
 110         {"AINR", NULL, "LineIn"},
 111 
 112         /* Front Left/Right are fed VOUT1L/R */
 113         {"Front", NULL, "VOUT1L"},
 114         {"Front", NULL, "VOUT1R"},
 115 
 116         /* Center/Sub are fed VOUT2L/R */
 117         {"Center+Sub", NULL, "VOUT2L"},
 118         {"Center+Sub", NULL, "VOUT2R"},
 119 
 120         /* Rear Left/Right are fed VOUT3L/R */
 121         {"Rear", NULL, "VOUT3L"},
 122         {"Rear", NULL, "VOUT3R"},
 123 };
 124 
 125 static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
 126 {
 127         /* Enabling the microphone requires the fitting of a 0R
 128          * resistor to connect the line from the microphone jack.
 129          */
 130         snd_soc_dapm_disable_pin(&rtd->card->dapm, "MicIn");
 131 
 132         return 0;
 133 }
 134 
 135 enum {
 136         PRI_PLAYBACK = 0,
 137         PRI_CAPTURE,
 138 };
 139 
 140 #define SMDK_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
 141         SND_SOC_DAIFMT_CBM_CFM)
 142 
 143 SND_SOC_DAILINK_DEFS(paif_rx,
 144         DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.2")),
 145         DAILINK_COMP_ARRAY(COMP_CODEC("wm8580.0-001b", "wm8580-hifi-playback")),
 146         DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
 147 
 148 SND_SOC_DAILINK_DEFS(paif_tx,
 149         DAILINK_COMP_ARRAY(COMP_CPU("samsung-i2s.2")),
 150         DAILINK_COMP_ARRAY(COMP_CODEC("wm8580.0-001b", "wm8580-hifi-capture")),
 151         DAILINK_COMP_ARRAY(COMP_PLATFORM("samsung-i2s.0")));
 152 
 153 static struct snd_soc_dai_link smdk_dai[] = {
 154         [PRI_PLAYBACK] = { /* Primary Playback i/f */
 155                 .name = "WM8580 PAIF RX",
 156                 .stream_name = "Playback",
 157                 .dai_fmt = SMDK_DAI_FMT,
 158                 .ops = &smdk_ops,
 159                 SND_SOC_DAILINK_REG(paif_rx),
 160         },
 161         [PRI_CAPTURE] = { /* Primary Capture i/f */
 162                 .name = "WM8580 PAIF TX",
 163                 .stream_name = "Capture",
 164                 .dai_fmt = SMDK_DAI_FMT,
 165                 .init = smdk_wm8580_init_paiftx,
 166                 .ops = &smdk_ops,
 167                 SND_SOC_DAILINK_REG(paif_tx),
 168         },
 169 };
 170 
 171 static struct snd_soc_card smdk = {
 172         .name = "SMDK-I2S",
 173         .owner = THIS_MODULE,
 174         .dai_link = smdk_dai,
 175         .num_links = ARRAY_SIZE(smdk_dai),
 176 
 177         .dapm_widgets = smdk_wm8580_dapm_widgets,
 178         .num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets),
 179         .dapm_routes = smdk_wm8580_audio_map,
 180         .num_dapm_routes = ARRAY_SIZE(smdk_wm8580_audio_map),
 181 };
 182 
 183 static struct platform_device *smdk_snd_device;
 184 
 185 static int __init smdk_audio_init(void)
 186 {
 187         int ret;
 188 
 189         smdk_snd_device = platform_device_alloc("soc-audio", -1);
 190         if (!smdk_snd_device)
 191                 return -ENOMEM;
 192 
 193         platform_set_drvdata(smdk_snd_device, &smdk);
 194         ret = platform_device_add(smdk_snd_device);
 195 
 196         if (ret)
 197                 platform_device_put(smdk_snd_device);
 198 
 199         return ret;
 200 }
 201 module_init(smdk_audio_init);
 202 
 203 static void __exit smdk_audio_exit(void)
 204 {
 205         platform_device_unregister(smdk_snd_device);
 206 }
 207 module_exit(smdk_audio_exit);
 208 
 209 MODULE_AUTHOR("Jaswinder Singh, jassisinghbrar@gmail.com");
 210 MODULE_DESCRIPTION("ALSA SoC SMDK WM8580");
 211 MODULE_LICENSE("GPL");

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