OSDN Git Service

Merge tag 'asoc-v4.2' into asoc-next
authorMark Brown <broonie@kernel.org>
Mon, 22 Jun 2015 09:24:19 +0000 (10:24 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 22 Jun 2015 09:24:19 +0000 (10:24 +0100)
ASoC: Updates for v4.2

The big thing this release has been Liam's addition of topology support
to the core.  We've also seen quite a bit of driver work and the
continuation of Lars' refactoring for component support.

 - Support for loading ASoC topology maps from firmware, intended to be
   used to allow self-describing DSP firmware images to be built which
   can map controls added by the DSP to userspace without the kernel
   needing to know about individual DSP firmwares.
 - Lots of refactoring to avoid direct access to snd_soc_codec where
   it's not needed supporting future refactoring.
 - Big refactoring and cleanup serieses for the Wolfson ADSP and TI
   TAS2552 drivers.
 - Support for TI TAS571x power amplifiers.
 - Support for Qualcomm APQ8016 and ZTE ZX296702 SoCs.
 - Support for x86 systems with RT5650 and Qualcomm Storm.

# gpg: Signature made Mon 08 Jun 2015 18:48:37 BST using RSA key ID 5D5487D0
# gpg: Oops: keyid_from_fingerprint: no pubkey
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg:                 aka "Mark Brown <broonie@debian.org>"
# gpg:                 aka "Mark Brown <broonie@kernel.org>"
# gpg:                 aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg:                 aka "Mark Brown <broonie@linaro.org>"
# gpg:                 aka "Mark Brown <Mark.Brown@linaro.org>"

1  2 
MAINTAINERS
sound/soc/codecs/wm8960.c

diff --combined MAINTAINERS
@@@ -51,9 -51,9 +51,9 @@@ trivial patch so apply some common sens
        or does something very odd once a month document it.
  
        PLEASE remember that submissions must be made under the terms
 -      of the OSDL certificate of contribution and should include a
 -      Signed-off-by: line.  The current version of this "Developer's
 -      Certificate of Origin" (DCO) is listed in the file
 +      of the Linux Foundation certificate of contribution and should
 +      include a Signed-off-by: line.  The current version of this
 +      "Developer's Certificate of Origin" (DCO) is listed in the file
        Documentation/SubmittingPatches.
  
  6.    Make sure you have the right to send any changes you make. If you
@@@ -7575,7 -7575,6 +7575,7 @@@ F:      drivers/pci/host/pci-exynos.
  
  PCI DRIVER FOR SYNOPSIS DESIGNWARE
  M:    Jingoo Han <jingoohan1@gmail.com>
 +M:    Pratyush Anand <pratyush.anand@gmail.com>
  L:    linux-pci@vger.kernel.org
  S:    Maintained
  F:    drivers/pci/host/*designware*
@@@ -7589,9 -7588,8 +7589,9 @@@ F:      Documentation/devicetree/bindings/pc
  F:    drivers/pci/host/pci-host-generic.c
  
  PCIE DRIVER FOR ST SPEAR13XX
 +M:    Pratyush Anand <pratyush.anand@gmail.com>
  L:    linux-pci@vger.kernel.org
 -S:    Orphan
 +S:    Maintained
  F:    drivers/pci/host/*spear*
  
  PCMCIA SUBSYSTEM
@@@ -9924,6 -9922,12 +9924,12 @@@ L:    netdev@vger.kernel.or
  S:    Maintained
  F:    drivers/net/ethernet/ti/netcp*
  
+ TI TAS571X FAMILY ASoC CODEC DRIVER
+ M:    Kevin Cernekee <cernekee@chromium.org>
+ L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
+ S:    Odd Fixes
+ F:    sound/soc/codecs/tas571x*
  TI TWL4030 SERIES SOC CODEC DRIVER
  M:    Peter Ujfalusi <peter.ujfalusi@ti.com>
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
@@@ -10589,7 -10593,8 +10595,7 @@@ F:   drivers/virtio/virtio_input.
  F:    include/uapi/linux/virtio_input.h
  
  VIA RHINE NETWORK DRIVER
 -M:    Roger Luethi <rl@hellgate.ch>
 -S:    Maintained
 +S:    Orphan
  F:    drivers/net/ethernet/via/via-rhine.c
  
  VIA SD/MMC CARD CONTROLLER DRIVER
@@@ -127,6 -127,8 +127,8 @@@ struct wm8960_priv 
        struct snd_soc_dapm_widget *out3;
        bool deemph;
        int playback_fs;
+       int bclk;
+       int sysclk;
        struct wm8960_data pdata;
  };
  
@@@ -245,7 -247,7 +247,7 @@@ SOC_SINGLE("PCM Playback -6dB Switch", 
  SOC_ENUM("ADC Polarity", wm8960_enum[0]),
  SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0),
  
 -SOC_ENUM("DAC Polarity", wm8960_enum[2]),
 +SOC_ENUM("DAC Polarity", wm8960_enum[1]),
  SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0,
                    wm8960_get_deemph, wm8960_put_deemph),
  
@@@ -445,7 -447,7 +447,7 @@@ static int wm8960_add_widgets(struct sn
  {
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
        struct wm8960_data *pdata = &wm8960->pdata;
-       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
        struct snd_soc_dapm_widget *w;
  
        snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets,
         * and save the result.
         */
        list_for_each_entry(w, &codec->component.card->widgets, list) {
-               if (w->dapm != &codec->dapm)
+               if (w->dapm != dapm)
                        continue;
                if (strcmp(w->name, "LOUT1 PGA") == 0)
                        wm8960->lout1 = w;
@@@ -563,6 -565,72 +565,72 @@@ static struct 
        {  8000, 5 },
  };
  
+ /* Multiply 256 for internal 256 div */
+ static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 };
+ /* Multiply 10 to eliminate decimials */
+ static const int bclk_divs[] = {
+       10, 15, 20, 30, 40, 55, 60, 80, 110,
+       120, 160, 220, 240, 320, 320, 320
+ };
+ static void wm8960_configure_clocking(struct snd_soc_codec *codec,
+               bool tx, int lrclk)
+ {
+       struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+       u16 iface1 = snd_soc_read(codec, WM8960_IFACE1);
+       u16 iface2 = snd_soc_read(codec, WM8960_IFACE2);
+       u32 sysclk;
+       int i, j;
+       if (!(iface1 & (1<<6))) {
+               dev_dbg(codec->dev,
+                       "Codec is slave mode, no need to configure clock\n");
+               return;
+       }
+       if (!wm8960->sysclk) {
+               dev_dbg(codec->dev, "No SYSCLK configured\n");
+               return;
+       }
+       if (!wm8960->bclk || !lrclk) {
+               dev_dbg(codec->dev, "No audio clocks configured\n");
+               return;
+       }
+       for (i = 0; i < ARRAY_SIZE(dac_divs); ++i) {
+               if (wm8960->sysclk == lrclk * dac_divs[i]) {
+                       for (j = 0; j < ARRAY_SIZE(bclk_divs); ++j) {
+                               sysclk = wm8960->bclk * bclk_divs[j] / 10;
+                               if (wm8960->sysclk == sysclk)
+                                       break;
+                       }
+                       if(j != ARRAY_SIZE(bclk_divs))
+                               break;
+               }
+       }
+       if (i == ARRAY_SIZE(dac_divs)) {
+               dev_err(codec->dev, "Unsupported sysclk %d\n", wm8960->sysclk);
+               return;
+       }
+       /*
+        * configure frame clock. If ADCLRC configure as GPIO pin, DACLRC
+        * pin is used as a frame clock for ADCs and DACs.
+        */
+       if (iface2 & (1<<6))
+               snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3);
+       else if (tx)
+               snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 3, i << 3);
+       else if (!tx)
+               snd_soc_update_bits(codec, WM8960_CLOCK1, 0x7 << 6, i << 6);
+       /* configure bit clock */
+       snd_soc_update_bits(codec, WM8960_CLOCK2, 0xf, j);
+ }
  static int wm8960_hw_params(struct snd_pcm_substream *substream,
                            struct snd_pcm_hw_params *params,
                            struct snd_soc_dai *dai)
        struct snd_soc_codec *codec = dai->codec;
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
        u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
+       bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
        int i;
  
+       wm8960->bclk = snd_soc_params_to_bclk(params);
+       if (params_channels(params) == 1)
+               wm8960->bclk *= 2;
        /* bit size */
        switch (params_width(params)) {
        case 16:
        case 24:
                iface |= 0x0008;
                break;
+       case 32:
+               /* right justify mode does not support 32 word length */
+               if ((iface & 0x3) != 0) {
+                       iface |= 0x000c;
+                       break;
+               }
        default:
                dev_err(codec->dev, "unsupported width %d\n",
                        params_width(params));
  
        /* set iface */
        snd_soc_write(codec, WM8960_IFACE1, iface);
+       wm8960_configure_clocking(codec, tx, params_rate(params));
        return 0;
  }
  
@@@ -627,7 -709,7 +709,7 @@@ static int wm8960_set_bias_level_out3(s
                break;
  
        case SND_SOC_BIAS_PREPARE:
-               switch (codec->dapm.bias_level) {
+               switch (snd_soc_codec_get_bias_level(codec)) {
                case SND_SOC_BIAS_STANDBY:
                        if (!IS_ERR(wm8960->mclk)) {
                                ret = clk_prepare_enable(wm8960->mclk);
                break;
  
        case SND_SOC_BIAS_STANDBY:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+               if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
                        regcache_sync(wm8960->regmap);
  
                        /* Enable anti-pop features */
                break;
        }
  
-       codec->dapm.bias_level = level;
        return 0;
  }
  
@@@ -707,7 -787,7 +787,7 @@@ static int wm8960_set_bias_level_caples
                break;
  
        case SND_SOC_BIAS_PREPARE:
-               switch (codec->dapm.bias_level) {
+               switch (snd_soc_codec_get_bias_level(codec)) {
                case SND_SOC_BIAS_STANDBY:
                        /* Enable anti pop mode */
                        snd_soc_update_bits(codec, WM8960_APOP1,
                break;
  
        case SND_SOC_BIAS_STANDBY:
-               switch (codec->dapm.bias_level) {
+               switch (snd_soc_codec_get_bias_level(codec)) {
                case SND_SOC_BIAS_PREPARE:
                        /* Disable HP discharge */
                        snd_soc_update_bits(codec, WM8960_APOP2,
                break;
        }
  
-       codec->dapm.bias_level = level;
        return 0;
  }
  
@@@ -950,11 -1028,35 +1028,35 @@@ static int wm8960_set_bias_level(struc
        return wm8960->set_bias_level(codec, level);
  }
  
+ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+                                       unsigned int freq, int dir)
+ {
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+       switch (clk_id) {
+       case WM8960_SYSCLK_MCLK:
+               snd_soc_update_bits(codec, WM8960_CLOCK1,
+                                       0x1, WM8960_SYSCLK_MCLK);
+               break;
+       case WM8960_SYSCLK_PLL:
+               snd_soc_update_bits(codec, WM8960_CLOCK1,
+                                       0x1, WM8960_SYSCLK_PLL);
+               break;
+       default:
+               return -EINVAL;
+       }
+       wm8960->sysclk = freq;
+       return 0;
+ }
  #define WM8960_RATES SNDRV_PCM_RATE_8000_48000
  
  #define WM8960_FORMATS \
        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
-       SNDRV_PCM_FMTBIT_S24_LE)
+       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
  
  static const struct snd_soc_dai_ops wm8960_dai_ops = {
        .hw_params = wm8960_hw_params,
        .set_fmt = wm8960_set_dai_fmt,
        .set_clkdiv = wm8960_set_dai_clkdiv,
        .set_pll = wm8960_set_dai_pll,
+       .set_sysclk = wm8960_set_dai_sysclk,
  };
  
  static struct snd_soc_dai_driver wm8960_dai = {