Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Oct 2012 22:07:14 +0000 (07:07 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Oct 2012 22:07:14 +0000 (07:07 +0900)
Pull sound updates from Takashi Iwai:
 "This contains pretty many small commits covering fairly large range of
  files in sound/ directory.  Partly because of additional API support
  and partly because of constantly developed ASoC and ARM stuff.

  Some highlights:

   - Introduced the helper function and documentation for exposing the
     channel map via control API, as discussed in Plumbers; most of PCI
     drivers are covered, will follow more drivers later

   - Most of drivers have been replaced with the new PM callbacks (if
     the bus is supported)

   - HD-audio controller got the support of runtime PM and the support
     of D3 clock-stop.  Also changing the power_save option in sysfs
     kicks off immediately to enable / disable the power-save mode.

   - Another significant code change in HD-audio is the rewrite of
     firmware loading code.  Other than that, most of changes in
     HD-audio are continued cleanups and standardization for the generic
     auto parser and bug fixes (HBR, device-specific fixups), in
     addition to the support of channel-map API.

   - Addition of ASoC bindings for the compressed API, used by the
     mid-x86 drivers.

   - Lots of cleanups and API refreshes for ASoC codec drivers and
     DaVinci.

   - Conversion of OMAP to dmaengine.

   - New machine driver for Wolfson Microelectronics Bells.

   - New CODEC driver for Wolfson Microelectronics WM0010.

   - Enhancements to the ux500 and wm2000 drivers

   - A new driver for DA9055 and the support for regulator bypass mode."

Fix up various arm soc header file reorg conflicts.

* tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (339 commits)
  ALSA: hda - Add new codec ALC283 ALC290 support
  ALSA: hda - avoid unneccesary indices on "Headphone Jack" controls
  ALSA: hda - fix indices on boost volume on Conexant
  ALSA: aloop - add locking to timer access
  ALSA: hda - Fix hang caused by race during suspend.
  sound: Remove unnecessary semicolon
  ALSA: hda/realtek - Fix detection of ALC271X codec
  ALSA: hda - Add inverted internal mic quirk for Lenovo IdeaPad U310
  ALSA: hda - make Realtek/Sigmatel/Conexant use the generic unsol event
  ALSA: hda - make a generic unsol event handler
  ASoC: codecs: Add DA9055 codec driver
  ASoC: eukrea-tlv320: Convert it to platform driver
  ALSA: ASoC: add DT bindings for CS4271
  ASoC: wm_hubs: Ensure volume updates are handled during class W startup
  ASoC: wm5110: Adding missing volume update bits
  ASoC: wm5110: Add OUT3R support
  ASoC: wm5110: Add AEC loopback support
  ASoC: wm5110: Rename EPOUT to HPOUT3
  ASoC: arizona: Add more clock rates
  ASoC: arizona: Add more DSP options for mixer input muxes
  ...

48 files changed:
1  2 
arch/arm/mach-davinci/davinci.h
arch/arm/mach-davinci/devices.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/include/mach/da8xx.h
arch/arm/mach-imx/mach-imx27_visstrim_m10.c
arch/arm/mach-omap2/board-am3517evm.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/twl-common.h
drivers/dma/at_hdmac.c
drivers/dma/ep93xx_dma.c
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/mmp_tdma.c
drivers/dma/omap-dma.c
drivers/dma/pl330.c
drivers/dma/tegra20-apb-dma.c
include/linux/i2c/twl.h
include/linux/platform_data/asoc-ti-mcbsp.h
include/sound/ac97_codec.h
include/sound/ad1816a.h
include/sound/pcm.h
sound/pci/oxygen/oxygen_lib.c
sound/soc/cirrus/ep93xx-ac97.c
sound/soc/cirrus/ep93xx-i2s.c
sound/soc/cirrus/ep93xx-pcm.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm5100.c
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-ssi.c
sound/soc/omap/am3517evm.c
sound/soc/omap/mcbsp.c
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-pcm.c
sound/soc/omap/zoom2.c
sound/soc/soc-core.c
sound/usb/endpoint.c

index a37fc44e29bc05b2c52d796bf4ace69cb6800601,8661b2013527f12b33e6c9d081ccea3314ba47af..12d544befcfa36554d70931fcf0048e01ab212bd
  #include <linux/davinci_emac.h>
  #include <linux/platform_device.h>
  #include <linux/spi/spi.h>
- #include <mach/asp.h>
+ #include <linux/platform_data/davinci_asp.h>
 -
 -#include <mach/keyscan.h>
 +#include <linux/platform_data/keyscan-davinci.h>
  #include <mach/hardware.h>
+ #include <mach/edma.h>
  
  #include <media/davinci/vpfe_capture.h>
  #include <media/davinci/vpif_types.h>
Simple merge
index adbde33eca015a640217ed1335671645cd874449,e47a3f0e8ac48643a2c47867ae523855c04329ca..a255434908dbcfebb1a1b8a3a946860db7e9f4bf
@@@ -26,8 -26,7 +26,7 @@@
  #include <mach/time.h>
  #include <mach/serial.h>
  #include <mach/common.h>
- #include <mach/asp.h>
 -#include <mach/spi.h>
 +#include <linux/platform_data/spi-davinci.h>
  #include <mach/gpio-davinci.h>
  
  #include "davinci.h"
index 719e22f2a37e42bd4bc11bcf28bc86f629a79adf,f473745d6e3cbe5ca940ca6694eabe00f6e41207..b680c832e0ba87758f1f29aeb502109ce2699268
@@@ -29,9 -29,8 +29,8 @@@
  #include <mach/time.h>
  #include <mach/serial.h>
  #include <mach/common.h>
- #include <mach/asp.h>
 -#include <mach/keyscan.h>
 -#include <mach/spi.h>
 +#include <linux/platform_data/keyscan-davinci.h>
 +#include <linux/platform_data/spi-davinci.h>
  #include <mach/gpio-davinci.h>
  
  #include "davinci.h"
index 33e78ae2a254d3106f97a42dcf68aa2cebc076c2,c74a6abef187f9c7e7bf7b61e0e4c81034fb58bb..c9ee723c56f35a78628dc0a4a78c08bd63a4f6c3
  
  #include <mach/serial.h>
  #include <mach/edma.h>
- #include <mach/asp.h>
 -#include <mach/i2c.h>
 -#include <mach/mmc.h>
 -#include <mach/usb.h>
  #include <mach/pm.h>
 -#include <mach/spi.h>
 +#include <linux/platform_data/i2c-davinci.h>
 +#include <linux/platform_data/mmc-davinci.h>
 +#include <linux/platform_data/usb-davinci.h>
 +#include <linux/platform_data/spi-davinci.h>
  
  extern void __iomem *da8xx_syscfg0_base;
  extern void __iomem *da8xx_syscfg1_base;
index 821d6aac411cb9e5d9d56f8ffb3100b3affa1b6b,562722959666f07078fecc1eb8f0e2fd70bd4008..141756f00ae5c8733795855bd31b994c8609a496
@@@ -32,6 -32,8 +32,7 @@@
  #include <linux/delay.h>
  #include <linux/dma-mapping.h>
  #include <linux/leds.h>
 -#include <linux/memblock.h>
+ #include <linux/platform_data/asoc-mx27vis.h>
  #include <media/soc_camera.h>
  #include <sound/tlv320aic32x4.h>
  #include <asm/mach-types.h>
@@@ -403,47 -436,14 +434,55 @@@ static const struct imx_ssi_platform_da
        .flags                  = IMX_SSI_DMA | IMX_SSI_SYN,
  };
  
 +/* coda */
 +
 +static void __init visstrim_coda_init(void)
 +{
 +      struct platform_device *pdev;
 +      int dma;
 +
 +      pdev = imx27_add_coda();
 +      dma = dma_declare_coherent_memory(&pdev->dev,
 +                                        mx2_camera_base + MX2_CAMERA_BUF_SIZE,
 +                                        mx2_camera_base + MX2_CAMERA_BUF_SIZE,
 +                                        MX2_CAMERA_BUF_SIZE,
 +                                        DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
 +      if (!(dma & DMA_MEMORY_MAP))
 +              return;
 +}
 +
 +/* DMA deinterlace */
 +static struct platform_device visstrim_deinterlace = {
 +      .name = "m2m-deinterlace",
 +      .id = 0,
 +};
 +
 +static void __init visstrim_deinterlace_init(void)
 +{
 +      int ret = -ENOMEM;
 +      struct platform_device *pdev = &visstrim_deinterlace;
 +      int dma;
 +
 +      ret = platform_device_register(pdev);
 +
 +      dma = dma_declare_coherent_memory(&pdev->dev,
 +                                        mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
 +                                        mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
 +                                        MX2_CAMERA_BUF_SIZE,
 +                                        DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
 +      if (!(dma & DMA_MEMORY_MAP))
 +              return;
 +}
 +
 +
+ /* Audio */
+ static const struct snd_mx27vis_platform_data snd_mx27vis_pdata __initconst = {
+       .amp_gain0_gpio = AMP_GAIN_0,
+       .amp_gain1_gpio = AMP_GAIN_1,
+       .amp_mutel_gpio = AMP_MUTE_SDL,
+       .amp_muter_gpio = AMP_MUTE_SDR,
+ };
  static void __init visstrim_m10_revision(void)
  {
        int exp_version = 0;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 6bcc107b9fc37facbafeac687e31f281f2a1bb57,a7d3b04807448c3bfa29cc408a09af1ea964488a..67f8540c8e07a912a87460311afc0f3a0e5c094e
@@@ -245,13 -245,10 +246,7 @@@ static int zoom_twl_gpio_setup(struct d
        return ret;
  }
  
- /* EXTMUTE callback function */
- static void zoom2_set_hs_extmute(int mute)
- {
-       gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
- }
  static struct twl4030_gpio_platform_data zoom_gpio_data = {
 -      .gpio_base      = OMAP_MAX_GPIO_LINES,
 -      .irq_base       = TWL4030_GPIO_IRQ_BASE,
 -      .irq_end        = TWL4030_GPIO_IRQ_END,
        .setup          = zoom_twl_gpio_setup,
  };
  
@@@ -277,9 -274,9 +272,9 @@@ static int __init omap_i2c_init(void
  
                codec_data->ramp_delay_value = 3;       /* 161 ms */
                codec_data->hs_extmute = 1;
-               codec_data->set_hs_extmute = zoom2_set_hs_extmute;
+               codec_data->hs_extmute_gpio = ZOOM2_HEADSET_EXTMUTE_GPIO;
        }
 -      omap_pmic_init(1, 2400, "twl5030", INT_34XX_SYS_NIRQ, &zoom_twldata);
 +      omap_pmic_init(1, 2400, "twl5030", 7 + OMAP_INTC_START, &zoom_twldata);
        omap_register_i2c_bus(2, 400, NULL, 0);
        omap_register_i2c_bus(3, 400, NULL, 0);
        return 0;
index 7d47407d6d461892cf2deb57c20a5a050335ac04,d57a3578bf039e2142ea4a89bf2aade44463eae8..37f8f948047baace501bc6ef4b09f551aa7c9cfa
  #include <linux/clk.h>
  #include <linux/err.h>
  #include <linux/io.h>
+ #include <linux/of.h>
  #include <linux/platform_device.h>
  #include <linux/slab.h>
 +#include <linux/platform_data/asoc-ti-mcbsp.h>
  
 -#include <mach/irqs.h>
  #include <plat/dma.h>
 -#include <plat/cpu.h>
 -#include <plat/mcbsp.h>
  #include <plat/omap_device.h>
  #include <linux/pm_runtime.h>
  
Simple merge
Simple merge
Simple merge
index 64256f64425285748d8be20d15fad0b5492c993a,493735b9b2c92a3871d4f48d80301a604d924552..bcfde400904ff9a6dd05e957eb1159d5fc98f771
@@@ -1118,8 -1118,9 +1118,9 @@@ fail
   * @chan: channel
   * @dma_addr: DMA mapped address of the buffer
   * @buf_len: length of the buffer (in bytes)
 - * @period_len: lenght of a single period
 + * @period_len: length of a single period
   * @dir: direction of the operation
+  * @flags: tx descriptor status flags
   * @context: operation context (ignored)
   *
   * Prepares a descriptor for cyclic DMA operation. This means that once the
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 18814127809aa031d3d5abc1ff64c5000ba1cd49,0000000000000000000000000000000000000000..c78d90b28b19f4646ad9ab113ec3e8ad2d0f8ef1
mode 100644,000000..100644
--- /dev/null
@@@ -1,62 -1,0 +1,60 @@@
-       int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src);
-       int (*mux_signal)(struct device *dev, const char *signal, const char *src);
 +/*
 + * arch/arm/plat-omap/include/mach/mcbsp.h
 + *
 + * Defines for Multi-Channel Buffered Serial Port
 + *
 + * Copyright (C) 2002 RidgeRun, Inc.
 + * Author: Steve Johnson
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 2 of the License, or
 + * (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 + *
 + */
 +#ifndef __ASM_ARCH_OMAP_MCBSP_H
 +#define __ASM_ARCH_OMAP_MCBSP_H
 +
 +#include <linux/spinlock.h>
 +#include <linux/clk.h>
 +
 +#define MCBSP_CONFIG_TYPE2    0x2
 +#define MCBSP_CONFIG_TYPE3    0x3
 +#define MCBSP_CONFIG_TYPE4    0x4
 +
 +/* Platform specific configuration */
 +struct omap_mcbsp_ops {
 +      void (*request)(unsigned int);
 +      void (*free)(unsigned int);
 +};
 +
 +struct omap_mcbsp_platform_data {
 +      struct omap_mcbsp_ops *ops;
 +      u16 buffer_size;
 +      u8 reg_size;
 +      u8 reg_step;
 +
 +      /* McBSP platform and instance specific features */
 +      bool has_wakeup; /* Wakeup capability */
 +      bool has_ccr; /* Transceiver has configuration control registers */
 +      int (*enable_st_clock)(unsigned int, bool);
 +};
 +
 +/**
 + * omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod
 + * @sidetone: name of the sidetone device
 + */
 +struct omap_mcbsp_dev_attr {
 +      const char *sidetone;
 +};
 +
 +#endif
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,bdffab33e1609c6648a0c5c3bdd33629ee852cee..c3521653cfd3fcac901fbcf076752b5b10c654e5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,435 +1,435 @@@
 -#include <mach/dma.h>
+ /*
+  * ASoC driver for Cirrus Logic EP93xx AC97 controller.
+  *
+  * Copyright (c) 2010 Mika Westerberg
+  *
+  * Based on s3c-ac97 ASoC driver by Jaswinder Singh.
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
+ #include <sound/core.h>
+ #include <sound/ac97_codec.h>
+ #include <sound/soc.h>
++#include <linux/platform_data/dma-ep93xx.h>
+ #include "ep93xx-pcm.h"
+ /*
+  * Per channel (1-4) registers.
+  */
+ #define AC97CH(n)             (((n) - 1) * 0x20)
+ #define AC97DR(n)             (AC97CH(n) + 0x0000)
+ #define AC97RXCR(n)           (AC97CH(n) + 0x0004)
+ #define AC97RXCR_REN          BIT(0)
+ #define AC97RXCR_RX3          BIT(3)
+ #define AC97RXCR_RX4          BIT(4)
+ #define AC97RXCR_CM           BIT(15)
+ #define AC97TXCR(n)           (AC97CH(n) + 0x0008)
+ #define AC97TXCR_TEN          BIT(0)
+ #define AC97TXCR_TX3          BIT(3)
+ #define AC97TXCR_TX4          BIT(4)
+ #define AC97TXCR_CM           BIT(15)
+ #define AC97SR(n)             (AC97CH(n) + 0x000c)
+ #define AC97SR_TXFE           BIT(1)
+ #define AC97SR_TXUE           BIT(6)
+ #define AC97RISR(n)           (AC97CH(n) + 0x0010)
+ #define AC97ISR(n)            (AC97CH(n) + 0x0014)
+ #define AC97IE(n)             (AC97CH(n) + 0x0018)
+ /*
+  * Global AC97 controller registers.
+  */
+ #define AC97S1DATA            0x0080
+ #define AC97S2DATA            0x0084
+ #define AC97S12DATA           0x0088
+ #define AC97RGIS              0x008c
+ #define AC97GIS                       0x0090
+ #define AC97IM                        0x0094
+ /*
+  * Common bits for RGIS, GIS and IM registers.
+  */
+ #define AC97_SLOT2RXVALID     BIT(1)
+ #define AC97_CODECREADY               BIT(5)
+ #define AC97_SLOT2TXCOMPLETE  BIT(6)
+ #define AC97EOI                       0x0098
+ #define AC97EOI_WINT          BIT(0)
+ #define AC97EOI_CODECREADY    BIT(1)
+ #define AC97GCR                       0x009c
+ #define AC97GCR_AC97IFE               BIT(0)
+ #define AC97RESET             0x00a0
+ #define AC97RESET_TIMEDRESET  BIT(0)
+ #define AC97SYNC              0x00a4
+ #define AC97SYNC_TIMEDSYNC    BIT(0)
+ #define AC97_TIMEOUT          msecs_to_jiffies(5)
+ /**
+  * struct ep93xx_ac97_info - EP93xx AC97 controller info structure
+  * @lock: mutex serializing access to the bus (slot 1 & 2 ops)
+  * @dev: pointer to the platform device dev structure
+  * @regs: mapped AC97 controller registers
+  * @done: bus ops wait here for an interrupt
+  */
+ struct ep93xx_ac97_info {
+       struct mutex            lock;
+       struct device           *dev;
+       void __iomem            *regs;
+       struct completion       done;
+ };
+ /* currently ALSA only supports a single AC97 device */
+ static struct ep93xx_ac97_info *ep93xx_ac97_info;
+ static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
+       .name           = "ac97-pcm-out",
+       .dma_port       = EP93XX_DMA_AAC1,
+ };
+ static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
+       .name           = "ac97-pcm-in",
+       .dma_port       = EP93XX_DMA_AAC1,
+ };
+ static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
+                                           unsigned reg)
+ {
+       return __raw_readl(info->regs + reg);
+ }
+ static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info,
+                                        unsigned reg, unsigned val)
+ {
+       __raw_writel(val, info->regs + reg);
+ }
+ static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97,
+                                      unsigned short reg)
+ {
+       struct ep93xx_ac97_info *info = ep93xx_ac97_info;
+       unsigned short val;
+       mutex_lock(&info->lock);
+       ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
+       ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID);
+       if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) {
+               dev_warn(info->dev, "timeout reading register %x\n", reg);
+               mutex_unlock(&info->lock);
+               return -ETIMEDOUT;
+       }
+       val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA);
+       mutex_unlock(&info->lock);
+       return val;
+ }
+ static void ep93xx_ac97_write(struct snd_ac97 *ac97,
+                             unsigned short reg,
+                             unsigned short val)
+ {
+       struct ep93xx_ac97_info *info = ep93xx_ac97_info;
+       mutex_lock(&info->lock);
+       /*
+        * Writes to the codec need to be done so that slot 2 is filled in
+        * before slot 1.
+        */
+       ep93xx_ac97_write_reg(info, AC97S2DATA, val);
+       ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
+       ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE);
+       if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
+               dev_warn(info->dev, "timeout writing register %x\n", reg);
+       mutex_unlock(&info->lock);
+ }
+ static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97)
+ {
+       struct ep93xx_ac97_info *info = ep93xx_ac97_info;
+       mutex_lock(&info->lock);
+       /*
+        * We are assuming that before this functions gets called, the codec
+        * BIT_CLK is stopped by forcing the codec into powerdown mode. We can
+        * control the SYNC signal directly via AC97SYNC register. Using
+        * TIMEDSYNC the controller will keep the SYNC high > 1us.
+        */
+       ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC);
+       ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
+       if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
+               dev_warn(info->dev, "codec warm reset timeout\n");
+       mutex_unlock(&info->lock);
+ }
+ static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97)
+ {
+       struct ep93xx_ac97_info *info = ep93xx_ac97_info;
+       mutex_lock(&info->lock);
+       /*
+        * For doing cold reset, we disable the AC97 controller interface, clear
+        * WINT and CODECREADY bits, and finally enable the interface again.
+        */
+       ep93xx_ac97_write_reg(info, AC97GCR, 0);
+       ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT);
+       ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE);
+       /*
+        * Now, assert the reset and wait for the codec to become ready.
+        */
+       ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET);
+       ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
+       if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
+               dev_warn(info->dev, "codec cold reset timeout\n");
+       /*
+        * Give the codec some time to come fully out from the reset. This way
+        * we ensure that the subsequent reads/writes will work.
+        */
+       usleep_range(15000, 20000);
+       mutex_unlock(&info->lock);
+ }
+ static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id)
+ {
+       struct ep93xx_ac97_info *info = dev_id;
+       unsigned status, mask;
+       /*
+        * Just mask out the interrupt and wake up the waiting thread.
+        * Interrupts are cleared via reading/writing to slot 1 & 2 registers by
+        * the waiting thread.
+        */
+       status = ep93xx_ac97_read_reg(info, AC97GIS);
+       mask = ep93xx_ac97_read_reg(info, AC97IM);
+       mask &= ~status;
+       ep93xx_ac97_write_reg(info, AC97IM, mask);
+       complete(&info->done);
+       return IRQ_HANDLED;
+ }
+ struct snd_ac97_bus_ops soc_ac97_ops = {
+       .read           = ep93xx_ac97_read,
+       .write          = ep93xx_ac97_write,
+       .reset          = ep93xx_ac97_cold_reset,
+       .warm_reset     = ep93xx_ac97_warm_reset,
+ };
+ EXPORT_SYMBOL_GPL(soc_ac97_ops);
+ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
+                              int cmd, struct snd_soc_dai *dai)
+ {
+       struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai);
+       unsigned v = 0;
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       /*
+                        * Enable compact mode, TX slots 3 & 4, and the TX FIFO
+                        * itself.
+                        */
+                       v |= AC97TXCR_CM;
+                       v |= AC97TXCR_TX3 | AC97TXCR_TX4;
+                       v |= AC97TXCR_TEN;
+                       ep93xx_ac97_write_reg(info, AC97TXCR(1), v);
+               } else {
+                       /*
+                        * Enable compact mode, RX slots 3 & 4, and the RX FIFO
+                        * itself.
+                        */
+                       v |= AC97RXCR_CM;
+                       v |= AC97RXCR_RX3 | AC97RXCR_RX4;
+                       v |= AC97RXCR_REN;
+                       ep93xx_ac97_write_reg(info, AC97RXCR(1), v);
+               }
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       /*
+                        * As per Cirrus EP93xx errata described below:
+                        *
+                        * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf
+                        *
+                        * we will wait for the TX FIFO to be empty before
+                        * clearing the TEN bit.
+                        */
+                       unsigned long timeout = jiffies + AC97_TIMEOUT;
+                       do {
+                               v = ep93xx_ac97_read_reg(info, AC97SR(1));
+                               if (time_after(jiffies, timeout)) {
+                                       dev_warn(info->dev, "TX timeout\n");
+                                       break;
+                               }
+                       } while (!(v & (AC97SR_TXFE | AC97SR_TXUE)));
+                       /* disable the TX FIFO */
+                       ep93xx_ac97_write_reg(info, AC97TXCR(1), 0);
+               } else {
+                       /* disable the RX FIFO */
+                       ep93xx_ac97_write_reg(info, AC97RXCR(1), 0);
+               }
+               break;
+       default:
+               dev_warn(info->dev, "unknown command %d\n", cmd);
+               return -EINVAL;
+       }
+       return 0;
+ }
+ static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+ {
+       struct ep93xx_pcm_dma_params *dma_data;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dma_data = &ep93xx_ac97_pcm_out;
+       else
+               dma_data = &ep93xx_ac97_pcm_in;
+       snd_soc_dai_set_dma_data(dai, substream, dma_data);
+       return 0;
+ }
+ static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
+       .startup        = ep93xx_ac97_startup,
+       .trigger        = ep93xx_ac97_trigger,
+ };
+ static struct snd_soc_dai_driver ep93xx_ac97_dai = {
+       .name           = "ep93xx-ac97",
+       .id             = 0,
+       .ac97_control   = 1,
+       .playback       = {
+               .stream_name    = "AC97 Playback",
+               .channels_min   = 2,
+               .channels_max   = 2,
+               .rates          = SNDRV_PCM_RATE_8000_48000,
+               .formats        = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture        = {
+               .stream_name    = "AC97 Capture",
+               .channels_min   = 2,
+               .channels_max   = 2,
+               .rates          = SNDRV_PCM_RATE_8000_48000,
+               .formats        = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops                    = &ep93xx_ac97_dai_ops,
+ };
+ static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
+ {
+       struct ep93xx_ac97_info *info;
+       struct resource *res;
+       unsigned int irq;
+       int ret;
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       info->regs = devm_request_and_ioremap(&pdev->dev, res);
+       if (!info->regs)
+               return -ENXIO;
+       irq = platform_get_irq(pdev, 0);
+       if (!irq)
+               return -ENODEV;
+       ret = devm_request_irq(&pdev->dev, irq, ep93xx_ac97_interrupt,
+                              IRQF_TRIGGER_HIGH, pdev->name, info);
+       if (ret)
+               goto fail;
+       dev_set_drvdata(&pdev->dev, info);
+       mutex_init(&info->lock);
+       init_completion(&info->done);
+       info->dev = &pdev->dev;
+       ep93xx_ac97_info = info;
+       platform_set_drvdata(pdev, info);
+       ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
+       if (ret)
+               goto fail;
+       return 0;
+ fail:
+       platform_set_drvdata(pdev, NULL);
+       ep93xx_ac97_info = NULL;
+       dev_set_drvdata(&pdev->dev, NULL);
+       return ret;
+ }
+ static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
+ {
+       struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
+       snd_soc_unregister_dai(&pdev->dev);
+       /* disable the AC97 controller */
+       ep93xx_ac97_write_reg(info, AC97GCR, 0);
+       platform_set_drvdata(pdev, NULL);
+       ep93xx_ac97_info = NULL;
+       dev_set_drvdata(&pdev->dev, NULL);
+       return 0;
+ }
+ static struct platform_driver ep93xx_ac97_driver = {
+       .probe  = ep93xx_ac97_probe,
+       .remove = __devexit_p(ep93xx_ac97_remove),
+       .driver = {
+               .name = "ep93xx-ac97",
+               .owner = THIS_MODULE,
+       },
+ };
+ module_platform_driver(ep93xx_ac97_driver);
+ MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
+ MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS("platform:ep93xx-ac97");
index 0000000000000000000000000000000000000000,8df8f6dc474fc9bdfb0a70672b8121c201f247ef..ac4a7515e7be4d5e417d17eec041b3b1151c4df0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,451 +1,451 @@@
 -#include <mach/dma.h>
+ /*
+  * linux/sound/soc/ep93xx-i2s.c
+  * EP93xx I2S driver
+  *
+  * Copyright (C) 2010 Ryan Mallon
+  *
+  * Based on the original driver by:
+  *   Copyright (C) 2007 Chase Douglas <chasedouglas@gmail>
+  *   Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  *
+  */
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/slab.h>
+ #include <linux/clk.h>
+ #include <linux/io.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+ #include <sound/initval.h>
+ #include <sound/soc.h>
+ #include <mach/hardware.h>
+ #include <mach/ep93xx-regs.h>
++#include <linux/platform_data/dma-ep93xx.h>
+ #include "ep93xx-pcm.h"
+ #define EP93XX_I2S_TXCLKCFG           0x00
+ #define EP93XX_I2S_RXCLKCFG           0x04
+ #define EP93XX_I2S_GLCTRL             0x0C
+ #define EP93XX_I2S_TXLINCTRLDATA      0x28
+ #define EP93XX_I2S_TXCTRL             0x2C
+ #define EP93XX_I2S_TXWRDLEN           0x30
+ #define EP93XX_I2S_TX0EN              0x34
+ #define EP93XX_I2S_RXLINCTRLDATA      0x58
+ #define EP93XX_I2S_RXCTRL             0x5C
+ #define EP93XX_I2S_RXWRDLEN           0x60
+ #define EP93XX_I2S_RX0EN              0x64
+ #define EP93XX_I2S_WRDLEN_16          (0 << 0)
+ #define EP93XX_I2S_WRDLEN_24          (1 << 0)
+ #define EP93XX_I2S_WRDLEN_32          (2 << 0)
+ #define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */
+ #define EP93XX_I2S_CLKCFG_LRS         (1 << 0) /* lrclk polarity */
+ #define EP93XX_I2S_CLKCFG_CKP         (1 << 1) /* Bit clock polarity */
+ #define EP93XX_I2S_CLKCFG_REL         (1 << 2) /* First bit transition */
+ #define EP93XX_I2S_CLKCFG_MASTER      (1 << 3) /* Master mode */
+ #define EP93XX_I2S_CLKCFG_NBCG                (1 << 4) /* Not bit clock gating */
+ struct ep93xx_i2s_info {
+       struct clk                      *mclk;
+       struct clk                      *sclk;
+       struct clk                      *lrclk;
+       struct ep93xx_pcm_dma_params    *dma_params;
+       void __iomem                    *regs;
+ };
+ struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = {
+       [SNDRV_PCM_STREAM_PLAYBACK] = {
+               .name           = "i2s-pcm-out",
+               .dma_port       = EP93XX_DMA_I2S1,
+       },
+       [SNDRV_PCM_STREAM_CAPTURE] = {
+               .name           = "i2s-pcm-in",
+               .dma_port       = EP93XX_DMA_I2S1,
+       },
+ };
+ static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info,
+                                       unsigned reg, unsigned val)
+ {
+       __raw_writel(val, info->regs + reg);
+ }
+ static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info,
+                                          unsigned reg)
+ {
+       return __raw_readl(info->regs + reg);
+ }
+ static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream)
+ {
+       unsigned base_reg;
+       int i;
+       if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
+           (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
+               /* Enable clocks */
+               clk_enable(info->mclk);
+               clk_enable(info->sclk);
+               clk_enable(info->lrclk);
+               /* Enable i2s */
+               ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1);
+       }
+       /* Enable fifos */
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+               base_reg = EP93XX_I2S_TX0EN;
+       else
+               base_reg = EP93XX_I2S_RX0EN;
+       for (i = 0; i < 3; i++)
+               ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1);
+ }
+ static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
+ {
+       unsigned base_reg;
+       int i;
+       /* Disable fifos */
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+               base_reg = EP93XX_I2S_TX0EN;
+       else
+               base_reg = EP93XX_I2S_RX0EN;
+       for (i = 0; i < 3; i++)
+               ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0);
+       if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
+           (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
+               /* Disable i2s */
+               ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0);
+               /* Disable clocks */
+               clk_disable(info->lrclk);
+               clk_disable(info->sclk);
+               clk_disable(info->mclk);
+       }
+ }
+ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
+                             struct snd_soc_dai *dai)
+ {
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       snd_soc_dai_set_dma_data(cpu_dai, substream,
+                                &info->dma_params[substream->stream]);
+       return 0;
+ }
+ static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+ {
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
+       ep93xx_i2s_disable(info, substream->stream);
+ }
+ static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+                                 unsigned int fmt)
+ {
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
+       unsigned int clk_cfg, lin_ctrl;
+       clk_cfg  = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
+       lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA);
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               clk_cfg |= EP93XX_I2S_CLKCFG_REL;
+               lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
+               lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
+               lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST;
+               break;
+       default:
+               return -EINVAL;
+       }
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               /* CPU is master */
+               clk_cfg |= EP93XX_I2S_CLKCFG_MASTER;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               /* Codec is master */
+               clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER;
+               break;
+       default:
+               return -EINVAL;
+       }
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               /* Negative bit clock, lrclk low on left word */
+               clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL);
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               /* Negative bit clock, lrclk low on right word */
+               clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP;
+               clk_cfg |= EP93XX_I2S_CLKCFG_REL;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               /* Positive bit clock, lrclk low on left word */
+               clk_cfg |= EP93XX_I2S_CLKCFG_CKP;
+               clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               /* Positive bit clock, lrclk low on right word */
+               clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL;
+               break;
+       }
+       /* Write new register values */
+       ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg);
+       ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg);
+       ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl);
+       ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl);
+       return 0;
+ }
+ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params,
+                               struct snd_soc_dai *dai)
+ {
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
+       unsigned word_len, div, sdiv, lrdiv;
+       int err;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               word_len = EP93XX_I2S_WRDLEN_16;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               word_len = EP93XX_I2S_WRDLEN_24;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               word_len = EP93XX_I2S_WRDLEN_32;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len);
+       else
+               ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len);
+       /*
+        * EP93xx I2S module can be setup so SCLK / LRCLK value can be
+        * 32, 64, 128. MCLK / SCLK value can be 2 and 4.
+        * We set LRCLK equal to `rate' and minimum SCLK / LRCLK 
+        * value is 64, because our sample size is 32 bit * 2 channels.
+        * I2S standard permits us to transmit more bits than
+        * the codec uses.
+        */
+       div = clk_get_rate(info->mclk) / params_rate(params);
+       sdiv = 4;
+       if (div > (256 + 512) / 2) {
+               lrdiv = 128;
+       } else {
+               lrdiv = 64;
+               if (div < (128 + 256) / 2)
+                       sdiv = 2;
+       }
+       err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
+       if (err)
+               return err;
+       err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv);
+       if (err)
+               return err;
+       ep93xx_i2s_enable(info, substream->stream);
+       return 0;
+ }
+ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
+                                unsigned int freq, int dir)
+ {
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
+       if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
+               return -EINVAL;
+       return clk_set_rate(info->mclk, freq);
+ }
+ #ifdef CONFIG_PM
+ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
+ {
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
+       if (!dai->active)
+               return 0;
+       ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
+       ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
+       return 0;
+ }
+ static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
+ {
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
+       if (!dai->active)
+               return 0;
+       ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
+       ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
+       return 0;
+ }
+ #else
+ #define ep93xx_i2s_suspend    NULL
+ #define ep93xx_i2s_resume     NULL
+ #endif
+ static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
+       .startup        = ep93xx_i2s_startup,
+       .shutdown       = ep93xx_i2s_shutdown,
+       .hw_params      = ep93xx_i2s_hw_params,
+       .set_sysclk     = ep93xx_i2s_set_sysclk,
+       .set_fmt        = ep93xx_i2s_set_dai_fmt,
+ };
+ #define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+ static struct snd_soc_dai_driver ep93xx_i2s_dai = {
+       .symmetric_rates= 1,
+       .suspend        = ep93xx_i2s_suspend,
+       .resume         = ep93xx_i2s_resume,
+       .playback       = {
+               .channels_min   = 2,
+               .channels_max   = 2,
+               .rates          = SNDRV_PCM_RATE_8000_192000,
+               .formats        = EP93XX_I2S_FORMATS,
+       },
+       .capture        = {
+                .channels_min  = 2,
+                .channels_max  = 2,
+                .rates         = SNDRV_PCM_RATE_8000_192000,
+                .formats       = EP93XX_I2S_FORMATS,
+       },
+       .ops            = &ep93xx_i2s_dai_ops,
+ };
+ static int ep93xx_i2s_probe(struct platform_device *pdev)
+ {
+       struct ep93xx_i2s_info *info;
+       struct resource *res;
+       int err;
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+       info->regs = devm_request_and_ioremap(&pdev->dev, res);
+       if (!info->regs)
+               return -ENXIO;
+       info->mclk = clk_get(&pdev->dev, "mclk");
+       if (IS_ERR(info->mclk)) {
+               err = PTR_ERR(info->mclk);
+               goto fail;
+       }
+       info->sclk = clk_get(&pdev->dev, "sclk");
+       if (IS_ERR(info->sclk)) {
+               err = PTR_ERR(info->sclk);
+               goto fail_put_mclk;
+       }
+       info->lrclk = clk_get(&pdev->dev, "lrclk");
+       if (IS_ERR(info->lrclk)) {
+               err = PTR_ERR(info->lrclk);
+               goto fail_put_sclk;
+       }
+       dev_set_drvdata(&pdev->dev, info);
+       info->dma_params = ep93xx_i2s_dma_params;
+       err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
+       if (err)
+               goto fail_put_lrclk;
+       return 0;
+ fail_put_lrclk:
+       dev_set_drvdata(&pdev->dev, NULL);
+       clk_put(info->lrclk);
+ fail_put_sclk:
+       clk_put(info->sclk);
+ fail_put_mclk:
+       clk_put(info->mclk);
+ fail:
+       return err;
+ }
+ static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
+ {
+       struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
+       snd_soc_unregister_dai(&pdev->dev);
+       dev_set_drvdata(&pdev->dev, NULL);
+       clk_put(info->lrclk);
+       clk_put(info->sclk);
+       clk_put(info->mclk);
+       return 0;
+ }
+ static struct platform_driver ep93xx_i2s_driver = {
+       .probe  = ep93xx_i2s_probe,
+       .remove = __devexit_p(ep93xx_i2s_remove),
+       .driver = {
+               .name   = "ep93xx-i2s",
+               .owner  = THIS_MODULE,
+       },
+ };
+ module_platform_driver(ep93xx_i2s_driver);
+ MODULE_ALIAS("platform:ep93xx-i2s");
+ MODULE_AUTHOR("Ryan Mallon");
+ MODULE_DESCRIPTION("EP93XX I2S driver");
+ MODULE_LICENSE("GPL");
index 0000000000000000000000000000000000000000,4eea98b42bc8389de50e64b34d9ea2e9f65f586e..665d9c94cc17ebeca825898ebac89f5c04937dd7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,242 +1,242 @@@
 -#include <mach/dma.h>
+ /*
+  * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface
+  *
+  * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+  * Copyright (C) 2006 Applied Data Systems
+  *
+  * Rewritten for the SoC audio subsystem (Based on PXA2xx code):
+  *   Copyright (c) 2008 Ryan Mallon
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/device.h>
+ #include <linux/slab.h>
+ #include <linux/dmaengine.h>
+ #include <linux/dma-mapping.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/pcm_params.h>
+ #include <sound/soc.h>
+ #include <sound/dmaengine_pcm.h>
++#include <linux/platform_data/dma-ep93xx.h>
+ #include <mach/hardware.h>
+ #include <mach/ep93xx-regs.h>
+ #include "ep93xx-pcm.h"
+ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
+       .info                   = (SNDRV_PCM_INFO_MMAP          |
+                                  SNDRV_PCM_INFO_MMAP_VALID    |
+                                  SNDRV_PCM_INFO_INTERLEAVED   |
+                                  SNDRV_PCM_INFO_BLOCK_TRANSFER),
+                                  
+       .rates                  = SNDRV_PCM_RATE_8000_192000,
+       .rate_min               = SNDRV_PCM_RATE_8000,
+       .rate_max               = SNDRV_PCM_RATE_192000,
+       
+       .formats                = (SNDRV_PCM_FMTBIT_S16_LE |
+                                  SNDRV_PCM_FMTBIT_S24_LE |
+                                  SNDRV_PCM_FMTBIT_S32_LE),
+       
+       .buffer_bytes_max       = 131072,
+       .period_bytes_min       = 32,
+       .period_bytes_max       = 32768,
+       .periods_min            = 1,
+       .periods_max            = 32,
+       .fifo_size              = 32,
+ };
+ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
+ {
+       struct ep93xx_dma_data *data = filter_param;
+       if (data->direction == ep93xx_dma_chan_direction(chan)) {
+               chan->private = data;
+               return true;
+       }
+       return false;
+ }
+ static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
+ {
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct ep93xx_pcm_dma_params *dma_params;
+       struct ep93xx_dma_data *dma_data;
+       int ret;
+       snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
+       dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
+       if (!dma_data)
+               return -ENOMEM;
+       dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
+       dma_data->port = dma_params->dma_port;
+       dma_data->name = dma_params->name;
+       dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
+       ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
+       if (ret) {
+               kfree(dma_data);
+               return ret;
+       }
+       snd_dmaengine_pcm_set_data(substream, dma_data);
+       return 0;
+ }
+ static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
+ {
+       struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
+       snd_dmaengine_pcm_close(substream);
+       kfree(dma_data);
+       return 0;
+ }
+ static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+ {
+       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+       return 0;
+ }
+ static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
+ {
+       snd_pcm_set_runtime_buffer(substream, NULL);
+       return 0;
+ }
+ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
+                          struct vm_area_struct *vma)
+ {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+                                    runtime->dma_area,
+                                    runtime->dma_addr,
+                                    runtime->dma_bytes);
+ }
+ static struct snd_pcm_ops ep93xx_pcm_ops = {
+       .open           = ep93xx_pcm_open,
+       .close          = ep93xx_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = ep93xx_pcm_hw_params,
+       .hw_free        = ep93xx_pcm_hw_free,
+       .trigger        = snd_dmaengine_pcm_trigger,
+       .pointer        = snd_dmaengine_pcm_pointer_no_residue,
+       .mmap           = ep93xx_pcm_mmap,
+ };
+ static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+ {
+       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+       struct snd_dma_buffer *buf = &substream->dma_buffer;
+       size_t size = ep93xx_pcm_hardware.buffer_bytes_max;
+       buf->dev.type = SNDRV_DMA_TYPE_DEV;
+       buf->dev.dev = pcm->card->dev;
+       buf->private_data = NULL;
+       buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+                                          &buf->addr, GFP_KERNEL);
+       buf->bytes = size;
+       return (buf->area == NULL) ? -ENOMEM : 0;
+ }
+ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+ {
+       struct snd_pcm_substream *substream;
+       struct snd_dma_buffer *buf;
+       int stream;
+       for (stream = 0; stream < 2; stream++) {                
+               substream = pcm->streams[stream].substream;
+               if (!substream)
+                       continue;
+               
+               buf = &substream->dma_buffer;
+               if (!buf->area)
+                       continue;
+               dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area,
+                                     buf->addr);
+               buf->area = NULL;
+       }
+ }
+ static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32);
+ static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
+ {
+       struct snd_card *card = rtd->card->snd_card;
+       struct snd_pcm *pcm = rtd->pcm;
+       int ret = 0;
+       if (!card->dev->dma_mask)
+               card->dev->dma_mask = &ep93xx_pcm_dmamask;
+       if (!card->dev->coherent_dma_mask)
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+               ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
+                                       SNDRV_PCM_STREAM_PLAYBACK);
+               if (ret)
+                       return ret;
+       }
+       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+               ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
+                                       SNDRV_PCM_STREAM_CAPTURE);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+ }
+ static struct snd_soc_platform_driver ep93xx_soc_platform = {
+       .ops            = &ep93xx_pcm_ops,
+       .pcm_new        = &ep93xx_pcm_new,
+       .pcm_free       = &ep93xx_pcm_free_dma_buffers,
+ };
+ static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
+ {
+       return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
+ }
+ static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
+ {
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+ }
+ static struct platform_driver ep93xx_pcm_driver = {
+       .driver = {
+                       .name = "ep93xx-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+       .probe = ep93xx_soc_platform_probe,
+       .remove = __devexit_p(ep93xx_soc_platform_remove),
+ };
+ module_platform_driver(ep93xx_pcm_driver);
+ MODULE_AUTHOR("Ryan Mallon");
+ MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS("platform:ep93xx-pcm-audio");
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index a681a9a8b8463824618a8c671d7cd12d6501006f,bc06175e636716283a71b75c4ab35a0c2191461a..afb8d4f1bedfac70eb98492ce5b4c023bb9d0752
  #include <linux/delay.h>
  #include <linux/io.h>
  #include <linux/slab.h>
+ #include <linux/pm_runtime.h>
  
 -#include <plat/mcbsp.h>
 +#include <linux/platform_data/asoc-ti-mcbsp.h>
 +
 +#include <plat/cpu.h>
  
  #include "mcbsp.h"
  
Simple merge
index 1b18627763cede8ba823b90d93fc127f105758dd,fef2f5933bb262f65f9c268da9c30d64daef3ee0..a6ee157478593f1e5eb338e51597df176308a953
@@@ -32,9 -34,7 +34,8 @@@
  #include <sound/initval.h>
  #include <sound/soc.h>
  
 -#include <plat/mcbsp.h>
 +#include <plat/cpu.h>
- #include <plat/dma.h>
 +#include <linux/platform_data/asoc-ti-mcbsp.h>
  #include "mcbsp.h"
  #include "omap-mcbsp.h"
  #include "omap-pcm.h"
Simple merge
index b309941798850d1143aaf5c4bfdf8c67a5967e09,a2636f6b836210ea8b55645e5906114535fb904f..340874ebf9ae79cb550cbfe54e81850802448e16
  #include <sound/core.h>
  #include <sound/pcm.h>
  #include <sound/pcm_params.h>
+ #include <sound/dmaengine_pcm.h>
  #include <sound/soc.h>
  
- #include <plat/dma.h>
 +#include <plat/cpu.h>
  #include "omap-pcm.h"
  
  static const struct snd_pcm_hardware omap_pcm_hardware = {
Simple merge
Simple merge
Simple merge