aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/at91
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/at91')
-rw-r--r--sound/soc/at91/Kconfig27
-rw-r--r--sound/soc/at91/Makefile11
-rw-r--r--sound/soc/at91/at91-pcm.c434
-rw-r--r--sound/soc/at91/at91-pcm.h72
-rw-r--r--sound/soc/at91/at91-ssc.c791
-rw-r--r--sound/soc/at91/at91-ssc.h27
-rw-r--r--sound/soc/at91/eti_b1_wm8731.c349
7 files changed, 0 insertions, 1711 deletions
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
deleted file mode 100644
index 905186502e0..00000000000
--- a/sound/soc/at91/Kconfig
+++ /dev/null
@@ -1,27 +0,0 @@
-config SND_AT91_SOC
- tristate "SoC Audio for the Atmel AT91 System-on-Chip"
- depends on ARCH_AT91
- help
- Say Y or M if you want to add support for codecs attached to
- the AT91 SSC interface. You will also need
- to select the audio interfaces to support below.
-
-config SND_AT91_SOC_SSC
- tristate
-
-config SND_AT91_SOC_ETI_B1_WM8731
- tristate "SoC Audio support for WM8731-based Endrelia ETI-B1 boards"
- depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
- select SND_AT91_SOC_SSC
- select SND_SOC_WM8731
- help
- Say Y if you want to add support for SoC audio on WM8731-based
- Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
-
-config SND_AT91_SOC_ETI_SLAVE
- bool "Run codec in slave Mode on Endrelia boards"
- depends on SND_AT91_SOC_ETI_B1_WM8731
- default n
- help
- Say Y if you want to run with the AT91 SSC generating the BCLK
- and LRC signals on Endrelia boards.
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
deleted file mode 100644
index f23da17cc32..00000000000
--- a/sound/soc/at91/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# AT91 Platform Support
-snd-soc-at91-objs := at91-pcm.o
-snd-soc-at91-ssc-objs := at91-ssc.o
-
-obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
-obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
-
-# AT91 Machine Support
-snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
-
-obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
diff --git a/sound/soc/at91/at91-pcm.c b/sound/soc/at91/at91-pcm.c
deleted file mode 100644
index d47492b2b6e..00000000000
--- a/sound/soc/at91/at91-pcm.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Mar 3, 2006
- *
- * Based on pxa2xx-pcm.c by:
- *
- * Author: Nicolas Pitre
- * Created: Nov 30, 2004
- * Copyright: (C) 2004 MontaVista Software, Inc.
- *
- * 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/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <asm/arch/hardware.h>
-#include <asm/arch/at91_ssc.h>
-
-#include "at91-pcm.h"
-
-#if 0
-#define DBG(x...) printk(KERN_INFO "at91-pcm: " x)
-#else
-#define DBG(x...)
-#endif
-
-static const struct snd_pcm_hardware at91_pcm_hardware = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .periods_min = 2,
- .periods_max = 1024,
- .buffer_bytes_max = 32 * 1024,
-};
-
-struct at91_runtime_data {
- struct at91_pcm_dma_params *params;
- dma_addr_t dma_buffer; /* physical address of dma buffer */
- dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
- size_t period_size;
- dma_addr_t period_ptr; /* physical address of next period */
- u32 pdc_xpr_save; /* PDC register save */
- u32 pdc_xcr_save;
- u32 pdc_xnpr_save;
- u32 pdc_xncr_save;
-};
-
-static void at91_pcm_dma_irq(u32 ssc_sr,
- struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- static int count = 0;
-
- count++;
-
- if (ssc_sr & params->mask->ssc_endbuf) {
-
- printk(KERN_WARNING
- "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK
- ? "underrun" : "overrun",
- params->name, ssc_sr, count);
-
- /* re-start the PDC */
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
-
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end) {
- prtd->period_ptr = prtd->dma_buffer;
- }
-
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- }
-
- if (ssc_sr & params->mask->ssc_endx) {
-
- /* Load the PDC next pointer and counter registers */
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end) {
- prtd->period_ptr = prtd->dma_buffer;
- }
- at91_ssc_write(params->ssc_base + params->pdc->xnpr,
- prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
- }
-
- snd_pcm_period_elapsed(substream);
-}
-
-static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd = runtime->private_data;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- /* this may get called several times by oss emulation
- * with different params */
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- prtd->params = rtd->dai->cpu_dai->dma_data;
- prtd->params->dma_intr_handler = at91_pcm_dma_irq;
-
- prtd->dma_buffer = runtime->dma_addr;
- prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
- prtd->period_size = params_period_bytes(params);
-
- DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
- prtd->params->name, runtime->dma_bytes, prtd->period_size);
- return 0;
-}
-
-static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
-
- if (params != NULL) {
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- prtd->params->dma_intr_handler = NULL;
- }
-
- return 0;
-}
-
-static int at91_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
-
- at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- return 0;
-}
-
-static int at91_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- int ret = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->period_ptr = prtd->dma_buffer;
-
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- prtd->period_ptr += prtd->period_size;
- at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
- at91_ssc_write(params->ssc_base + params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
-
- DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
- (unsigned long) prtd->period_ptr,
- at91_ssc_read(params->ssc_base + params->pdc->xpr),
- at91_ssc_read(params->ssc_base + params->pdc->xcr),
- at91_ssc_read(params->ssc_base + params->pdc->xnpr),
- at91_ssc_read(params->ssc_base + params->pdc->xncr));
-
- at91_ssc_write(params->ssc_base + AT91_SSC_IER,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
-
- DBG("sr=%lx imr=%lx\n",
- at91_ssc_read(params->ssc_base + AT91_SSC_SR),
- at91_ssc_read(params->ssc_base + AT91_SSC_IMR));
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
- break;
-
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- break;
-
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static snd_pcm_uframes_t at91_pcm_pointer(
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd = runtime->private_data;
- struct at91_pcm_dma_params *params = prtd->params;
- dma_addr_t ptr;
- snd_pcm_uframes_t x;
-
- ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
- x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
- if (x == runtime->buffer_size)
- x = 0;
- return x;
-}
-
-static int at91_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct at91_runtime_data *prtd;
- int ret = 0;
-
- snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware);
-
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- goto out;
-
- prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
- if (prtd == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- runtime->private_data = prtd;
-
- out:
- return ret;
-}
-
-static int at91_pcm_close(struct snd_pcm_substream *substream)
-{
- struct at91_runtime_data *prtd = substream->runtime->private_data;
-
- kfree(prtd);
- return 0;
-}
-
-static int at91_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);
-}
-
-struct snd_pcm_ops at91_pcm_ops = {
- .open = at91_pcm_open,
- .close = at91_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = at91_pcm_hw_params,
- .hw_free = at91_pcm_hw_free,
- .prepare = at91_pcm_prepare,
- .trigger = at91_pcm_trigger,
- .pointer = at91_pcm_pointer,
- .mmap = at91_pcm_mmap,
-};
-
-static int at91_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 = at91_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);
-
- DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
- (void *) buf->area,
- (void *) buf->addr,
- size);
-
- if (!buf->area)
- return -ENOMEM;
-
- buf->bytes = size;
- return 0;
-}
-
-static u64 at91_pcm_dmamask = 0xffffffff;
-
-static int at91_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
-{
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &at91_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
-
- if (dai->playback.channels_min) {
- ret = at91_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (dai->capture.channels_min) {
- ret = at91_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
- out:
- return ret;
-}
-
-static void at91_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;
- }
-}
-
-#ifdef CONFIG_PM
-static int at91_pcm_suspend(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at91_runtime_data *prtd;
- struct at91_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* disable the PDC and save the PDC registers */
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
-
- prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr);
- prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr);
- prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
- prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
-
- return 0;
-}
-
-static int at91_pcm_resume(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct at91_runtime_data *prtd;
- struct at91_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* restore the PDC registers and enable the PDC */
- at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
- at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
-
- at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
- return 0;
-}
-#else
-#define at91_pcm_suspend NULL
-#define at91_pcm_resume NULL
-#endif
-
-struct snd_soc_platform at91_soc_platform = {
- .name = "at91-audio",
- .pcm_ops = &at91_pcm_ops,
- .pcm_new = at91_pcm_new,
- .pcm_free = at91_pcm_free_dma_buffers,
- .suspend = at91_pcm_suspend,
- .resume = at91_pcm_resume,
-};
-
-EXPORT_SYMBOL_GPL(at91_soc_platform);
-
-MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
-MODULE_DESCRIPTION("Atmel AT91 PCM module");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-pcm.h b/sound/soc/at91/at91-pcm.h
deleted file mode 100644
index 58d0f00a07b..00000000000
--- a/sound/soc/at91/at91-pcm.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Mar 3, 2006
- *
- * Based on pxa2xx-pcm.h by:
- *
- * Author: Nicolas Pitre
- * Created: Nov 30, 2004
- * Copyright: MontaVista Software, Inc.
- *
- * 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.
- */
-
-#ifndef _AT91_PCM_H
-#define _AT91_PCM_H
-
-#include <asm/arch/hardware.h>
-
-struct at91_ssc_periph {
- void __iomem *base;
- u32 pid;
-};
-
-/*
- * Registers and status bits that are required by the PCM driver.
- */
-struct at91_pdc_regs {
- unsigned int xpr; /* PDC recv/trans pointer */
- unsigned int xcr; /* PDC recv/trans counter */
- unsigned int xnpr; /* PDC next recv/trans pointer */
- unsigned int xncr; /* PDC next recv/trans counter */
- unsigned int ptcr; /* PDC transfer control */
-};
-
-struct at91_ssc_mask {
- u32 ssc_enable; /* SSC recv/trans enable */
- u32 ssc_disable; /* SSC recv/trans disable */
- u32 ssc_endx; /* SSC ENDTX or ENDRX */
- u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
- u32 pdc_enable; /* PDC recv/trans enable */
- u32 pdc_disable; /* PDC recv/trans disable */
-};
-
-/*
- * This structure, shared between the PCM driver and the interface,
- * contains all information required by the PCM driver to perform the
- * PDC DMA operation. All fields except dma_intr_handler() are initialized
- * by the interface. The dms_intr_handler() pointer is set by the PCM
- * driver and called by the interface SSC interrupt handler if it is
- * non-NULL.
- */
-struct at91_pcm_dma_params {
- char *name; /* stream identifier */
- int pdc_xfer_size; /* PDC counter increment in bytes */
- void __iomem *ssc_base; /* SSC base address */
- struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
- struct at91_ssc_mask *mask;/* SSC & PDC status bits */
- struct snd_pcm_substream *substream;
- void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
-};
-
-extern struct snd_soc_platform at91_soc_platform;
-
-#define at91_ssc_read(a) ((unsigned long) __raw_readl(a))
-#define at91_ssc_write(a,v) __raw_writel((v),(a))
-
-#endif /* _AT91_PCM_H */
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
deleted file mode 100644
index 090e607f869..00000000000
--- a/sound/soc/at91/at91-ssc.c
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- *
- * Based on pxa2xx Platform drivers by
- * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- *
- * 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.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/atmel_pdc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-#include <asm/arch/hardware.h>
-#include <asm/arch/at91_pmc.h>
-#include <asm/arch/at91_ssc.h>
-
-#include "at91-pcm.h"
-#include "at91-ssc.h"
-
-#if 0
-#define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x)
-#else
-#define DBG(x...)
-#endif
-
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
-#define NUM_SSC_DEVICES 1
-#else
-#define NUM_SSC_DEVICES 3
-#endif
-
-
-/*
- * SSC PDC registers required by the PCM DMA engine.
- */
-static struct at91_pdc_regs pdc_tx_reg = {
- .xpr = ATMEL_PDC_TPR,
- .xcr = ATMEL_PDC_TCR,
- .xnpr = ATMEL_PDC_TNPR,
- .xncr = ATMEL_PDC_TNCR,
-};
-
-static struct at91_pdc_regs pdc_rx_reg = {
- .xpr = ATMEL_PDC_RPR,
- .xcr = ATMEL_PDC_RCR,
- .xnpr = ATMEL_PDC_RNPR,
- .xncr = ATMEL_PDC_RNCR,
-};
-
-/*
- * SSC & PDC status bits for transmit and receive.
- */
-static struct at91_ssc_mask ssc_tx_mask = {
- .ssc_enable = AT91_SSC_TXEN,
- .ssc_disable = AT91_SSC_TXDIS,
- .ssc_endx = AT91_SSC_ENDTX,
- .ssc_endbuf = AT91_SSC_TXBUFE,
- .pdc_enable = ATMEL_PDC_TXTEN,
- .pdc_disable = ATMEL_PDC_TXTDIS,
-};
-
-static struct at91_ssc_mask ssc_rx_mask = {
- .ssc_enable = AT91_SSC_RXEN,
- .ssc_disable = AT91_SSC_RXDIS,
- .ssc_endx = AT91_SSC_ENDRX,
- .ssc_endbuf = AT91_SSC_RXBUFF,
- .pdc_enable = ATMEL_PDC_RXTEN,
- .pdc_disable = ATMEL_PDC_RXTDIS,
-};
-
-
-/*
- * DMA parameters.
- */
-static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
- {{
- .name = "SSC0 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC0 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
-#if NUM_SSC_DEVICES == 3
- {{
- .name = "SSC1 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC1 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
- {{
- .name = "SSC2 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC2 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- }},
-#endif
-};
-
-struct at91_ssc_state {
- u32 ssc_cmr;
- u32 ssc_rcmr;
- u32 ssc_rfmr;
- u32 ssc_tcmr;
- u32 ssc_tfmr;
- u32 ssc_sr;
- u32 ssc_imr;
-};
-
-static struct at91_ssc_info {
- char *name;
- struct at91_ssc_periph ssc;
- spinlock_t lock; /* lock for dir_mask */
- unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
- unsigned short initialized; /* 1=SSC has been initialized */
- unsigned short daifmt;
- unsigned short cmr_div;
- unsigned short tcmr_period;
- unsigned short rcmr_period;
- struct at91_pcm_dma_params *dma_params[2];
- struct at91_ssc_state ssc_state;
-
-} ssc_info[NUM_SSC_DEVICES] = {
- {
- .name = "ssc0",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
-#if NUM_SSC_DEVICES == 3
- {
- .name = "ssc1",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
- {
- .name = "ssc2",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
- .dir_mask = 0,
- .initialized = 0,
- },
-#endif
-};
-
-static unsigned int at91_ssc_sysclk;
-
-/*
- * SSC interrupt handler. Passes PDC interrupts to the DMA
- * interrupt handler in the PCM driver.
- */
-static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id)
-{
- struct at91_ssc_info *ssc_p = dev_id;
- struct at91_pcm_dma_params *dma_params;
- u32 ssc_sr;
- int i;
-
- ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
- & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
-
- /*
- * Loop through the substreams attached to this SSC. If
- * a DMA-related interrupt occurred on that substream, call
- * the DMA interrupt handler function, if one has been
- * registered in the dma_params structure by the PCM driver.
- */
- for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
- dma_params = ssc_p->dma_params[i];
-
- if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
- (ssc_sr &
- (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
-
- dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
- }
-
- return IRQ_HANDLED;
-}
-
-/*
- * Startup. Only that one substream allowed in each direction.
- */
-static int at91_ssc_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- int dir_mask;
-
- DBG("ssc_startup: SSC_SR=0x%08lx\n",
- at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
- dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
-
- spin_lock_irq(&ssc_p->lock);
- if (ssc_p->dir_mask & dir_mask) {
- spin_unlock_irq(&ssc_p->lock);
- return -EBUSY;
- }
- ssc_p->dir_mask |= dir_mask;
- spin_unlock_irq(&ssc_p->lock);
-
- return 0;
-}
-
-/*
- * Shutdown. Clear DMA parameters and shutdown the SSC if there
- * are no other substreams open.
- */
-static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at91_pcm_dma_params *dma_params;
- int dir, dir_mask;
-
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
- dma_params = ssc_p->dma_params[dir];
-
- if (dma_params != NULL) {
- at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
- dma_params->mask->ssc_disable);
- DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
- at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
-
- dma_params->ssc_base = NULL;
- dma_params->substream = NULL;
- ssc_p->dma_params[dir] = NULL;
- }
-
- dir_mask = 1 << dir;
-
- spin_lock_irq(&ssc_p->lock);
- ssc_p->dir_mask &= ~dir_mask;
- if (!ssc_p->dir_mask) {
- /* Shutdown the SSC clock. */
- DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
-
- if (ssc_p->initialized) {
- free_irq(ssc_p->ssc.pid, ssc_p);
- ssc_p->initialized = 0;
- }
-
- /* Reset the SSC */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
-
- /* Clear the SSC dividers */
- ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
- }
- spin_unlock_irq(&ssc_p->lock);
-}
-
-/*
- * Record the SSC system clock rate.
- */
-static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
- int clk_id, unsigned int freq, int dir)
-{
- /*
- * The only clock supplied to the SSC is the AT91 master clock,
- * which is only used if the SSC is generating BCLK and/or
- * LRC clocks.
- */
- switch (clk_id) {
- case AT91_SYSCLK_MCK:
- at91_ssc_sysclk = freq;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Record the DAI format for use in hw_params().
- */
-static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
- unsigned int fmt)
-{
- struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- ssc_p->daifmt = fmt;
- return 0;
-}
-
-/*
- * Record SSC clock dividers for use in hw_params().
- */
-static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
- int div_id, int div)
-{
- struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- switch (div_id) {
- case AT91SSC_CMR_DIV:
- /*
- * The same master clock divider is used for both
- * transmit and receive, so if a value has already
- * been set, it must match this value.
- */
- if (ssc_p->cmr_div == 0)
- ssc_p->cmr_div = div;
- else
- if (div != ssc_p->cmr_div)
- return -EBUSY;
- break;
-
- case AT91SSC_TCMR_PERIOD:
- ssc_p->tcmr_period = div;
- break;
-
- case AT91SSC_RCMR_PERIOD:
- ssc_p->rcmr_period = div;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Configure the SSC.
- */
-static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- int id = rtd->dai->cpu_dai->id;
- struct at91_ssc_info *ssc_p = &ssc_info[id];
- struct at91_pcm_dma_params *dma_params;
- int dir, channels, bits;
- u32 tfmr, rfmr, tcmr, rcmr;
- int start_event;
- int ret;
-
- /*
- * Currently, there is only one set of dma params for
- * each direction. If more are added, this code will
- * have to be changed to select the proper set.
- */
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
-
- dma_params = &ssc_dma_params[id][dir];
- dma_params->ssc_base = ssc_p->ssc.base;
- dma_params->substream = substream;
-
- ssc_p->dma_params[dir] = dma_params;
-
- /*
- * The cpu_dai->dma_data field is only used to communicate the
- * appropriate DMA parameters to the pcm driver hw_params()
- * function. It should not be used for other purposes
- * as it is common to all substreams.
- */
- rtd->dai->cpu_dai->dma_data = dma_params;
-
- channels = params_channels(params);
-
- /*
- * Determine sample size in bits and the PDC increment.
- */
- switch(params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
- bits = 8;
- dma_params->pdc_xfer_size = 1;
- break;
- case SNDRV_PCM_FORMAT_S16_LE:
- bits = 16;
- dma_params->pdc_xfer_size = 2;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- bits = 24;
- dma_params->pdc_xfer_size = 4;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- bits = 32;
- dma_params->pdc_xfer_size = 4;
- break;
- default:
- printk(KERN_WARNING "at91-ssc: unsupported PCM format");
- return -EINVAL;
- }
-
- /*
- * The SSC only supports up to 16-bit samples in I2S format, due
- * to the size of the Frame Mode Register FSLEN field.
- */
- if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
- && bits > 16) {
- printk(KERN_WARNING
- "at91-ssc: sample size %d is too large for I2S\n", bits);
- return -EINVAL;
- }
-
- /*
- * Compute SSC register settings.
- */
- switch (ssc_p->daifmt
- & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * I2S format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line.
- */
- rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
- | (((bits - 1) << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
- | (((bits - 1) << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
- break;
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
- /*
- * I2S format, CODEC supplies BCLK and LRC clocks.
- *
- * The SSC transmit clock is obtained from the BCLK signal on
- * on the TK line, and the SSC receive clock is generated from the
- * transmit clock.
- *
- * For single channel data, one sample is transferred on the falling
- * edge of the LRC clock. For two channel data, one sample is
- * transferred on both edges of the LRC clock.
- */
- start_event = channels == 1
- ? AT91_SSC_START_FALLING_RF
- : AT91_SSC_START_EDGE_RF;
-
- rcmr = (( 0 << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( start_event ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (( 0 << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( 0 << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( start_event ) & AT91_SSC_START)
- | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (( 0 << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
- break;
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output on the SSC TK line.
- */
- rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_LOOP)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
- tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
- | (( 1 << 16) & AT91_SSC_STTDLY)
- | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
- | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
- | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
- | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
-
- tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
- | (( 0 << 23) & AT91_SSC_FSDEN)
- | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
- | (( 0 << 16) & AT91_SSC_FSLEN)
- | (((channels - 1) << 8) & AT91_SSC_DATNB)
- | (( 1 << 7) & AT91_SSC_MSBF)
- | (( 0 << 5) & AT91_SSC_DATDEF)
- | (((bits - 1) << 0) & AT91_SSC_DATALEN);
-
-
-
- break;
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
- default:
- printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n",
- ssc_p->daifmt);
- return -EINVAL;
- break;
- }
- DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
-
- if (!ssc_p->initialized) {
-
- /* Enable PMC peripheral clock for this SSC */
- DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
-
- /* Reset the SSC and its PDC registers */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
-
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
- at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
-
- if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt,
- 0, ssc_p->name, ssc_p)) < 0) {
- printk(KERN_WARNING "at91-ssc: request_irq failure\n");
-
- DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
- at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
- return ret;
- }
-
- ssc_p->initialized = 1;
- }
-
- /* set SSC clock mode register */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
-
- /* set receive clock mode and format */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
-
- /* set transmit clock mode and format */
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
-
- DBG("hw_params: SSC initialized\n");
- return 0;
-}
-
-
-static int at91_ssc_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct at91_pcm_dma_params *dma_params;
- int dir;
-
- dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
- dma_params = ssc_p->dma_params[dir];
-
- at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
- dma_params->mask->ssc_enable);
-
- DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
- at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
- return 0;
-}
-
-
-#ifdef CONFIG_PM
-static int at91_ssc_suspend(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at91_ssc_info *ssc_p;
-
- if(!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* Save the status register before disabling transmit and receive. */
- ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
- AT91_SSC_TXDIS | AT91_SSC_RXDIS);
-
- /* Save the current interrupt mask, then disable unmasked interrupts. */
- ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
-
- ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
- ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
- ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
- ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
- ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
-
- return 0;
-}
-
-static int at91_ssc_resume(struct platform_device *pdev,
- struct snd_soc_dai *cpu_dai)
-{
- struct at91_ssc_info *ssc_p;
-
- if(!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr);
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr);
-
- at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
- ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
- ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
-
- return 0;
-}
-
-#else
-#define at91_ssc_suspend NULL
-#define at91_ssc_resume NULL
-#endif
-
-#define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
- SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
- SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
- SNDRV_PCM_RATE_96000)
-
-#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-
-struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
- { .name = "at91-ssc0",
- .id = 0,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[0].ssc,
- },
-#if NUM_SSC_DEVICES == 3
- { .name = "at91-ssc1",
- .id = 1,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[1].ssc,
- },
- { .name = "at91-ssc2",
- .id = 2,
- .type = SND_SOC_DAI_PCM,
- .suspend = at91_ssc_suspend,
- .resume = at91_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = AT91_SSC_RATES,
- .formats = AT91_SSC_FORMATS,},
- .ops = {
- .startup = at91_ssc_startup,
- .shutdown = at91_ssc_shutdown,
- .prepare = at91_ssc_prepare,
- .hw_params = at91_ssc_hw_params,},
- .dai_ops = {
- .set_sysclk = at91_ssc_set_dai_sysclk,
- .set_fmt = at91_ssc_set_dai_fmt,
- .set_clkdiv = at91_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[2].ssc,
- },
-#endif
-};
-
-EXPORT_SYMBOL_GPL(at91_ssc_dai);
-
-/* Module information */
-MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
-MODULE_DESCRIPTION("AT91 SSC ASoC Interface");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-ssc.h b/sound/soc/at91/at91-ssc.h
deleted file mode 100644
index 6b7bf382d06..00000000000
--- a/sound/soc/at91/at91-ssc.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Jan 9, 2007
- *
- * 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.
- */
-
-#ifndef _AT91_SSC_H
-#define _AT91_SSC_H
-
-/* SSC system clock ids */
-#define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
-
-/* SSC divider ids */
-#define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */
-#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
-#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
-
-extern struct snd_soc_dai at91_ssc_dai[];
-
-#endif /* _AT91_SSC_H */
-
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
deleted file mode 100644
index d532de95424..00000000000
--- a/sound/soc/at91/eti_b1_wm8731.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * eti_b1_wm8731 -- SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
- *
- * Author: Frank Mandarino <fmandarino@endrelia.com>
- * Endrelia Technologies Inc.
- * Created: Mar 29, 2006
- *
- * Based on corgi.c by:
- *
- * Copyright 2005 Wolfson Microelectronics PLC.
- * Copyright 2005 Openedhand Ltd.
- *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- * Richard Purdie <richard@openedhand.com>
- *
- * 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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <asm/hardware.h>
-#include <asm/arch/gpio.h>
-
-#include "../codecs/wm8731.h"
-#include "at91-pcm.h"
-#include "at91-ssc.h"
-
-#if 0
-#define DBG(x...) printk(KERN_INFO "eti_b1_wm8731: " x)
-#else
-#define DBG(x...)
-#endif
-
-static struct clk *pck1_clk;
-static struct clk *pllb_clk;
-
-
-static int eti_b1_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret;
-
- /* cpu clock is the AT91 master clock sent to the SSC */
- ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
- 60000000, SND_SOC_CLOCK_IN);
- if (ret < 0)
- return ret;
-
- /* codec system clock is supplied by PCK1, set to 12MHz */
- ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
- 12000000, SND_SOC_CLOCK_IN);
- if (ret < 0)
- return ret;
-
- /* Start PCK1 clock. */
- clk_enable(pck1_clk);
- DBG("pck1 started\n");
-
- return 0;
-}
-
-static void eti_b1_shutdown(struct snd_pcm_substream *substream)
-{
- /* Stop PCK1 clock. */
- clk_disable(pck1_clk);
- DBG("pck1 stopped\n");
-}
-
-static int eti_b1_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret;
-
-#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
- unsigned int rate;
- int cmr_div, period;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /*
- * The SSC clock dividers depend on the sample rate. The CMR.DIV
- * field divides the system master clock MCK to drive the SSC TK
- * signal which provides the codec BCLK. The TCMR.PERIOD and
- * RCMR.PERIOD fields further divide the BCLK signal to drive
- * the SSC TF and RF signals which provide the codec DACLRC and
- * ADCLRC clocks.
- *
- * The dividers were determined through trial and error, where a
- * CMR.DIV value is chosen such that the resulting BCLK value is
- * divisible, or almost divisible, by (2 * sample rate), and then
- * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
- */
- rate = params_rate(params);
-
- switch (rate) {
- case 8000:
- cmr_div = 25; /* BCLK = 60MHz/(2*25) = 1.2MHz */
- period = 74; /* LRC = BCLK/(2*(74+1)) = 8000Hz */
- break;
- case 32000:
- cmr_div = 7; /* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
- period = 66; /* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
- break;
- case 48000:
- cmr_div = 13; /* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
- period = 23; /* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
- break;
- default:
- printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
- return -EINVAL;
- }
-
- /* set the MCK divider for BCLK */
- ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
- if (ret < 0)
- return ret;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* set the BCLK divider for DACLRC */
- ret = snd_soc_dai_set_clkdiv(cpu_dai,
- AT91SSC_TCMR_PERIOD, period);
- } else {
- /* set the BCLK divider for ADCLRC */
- ret = snd_soc_dai_set_clkdiv(cpu_dai,
- AT91SSC_RCMR_PERIOD, period);
- }
- if (ret < 0)
- return ret;
-
-#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
- /*
- * Codec in Master Mode.
- */
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
-#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
-
- return 0;
-}
-
-static struct snd_soc_ops eti_b1_ops = {
- .startup = eti_b1_startup,
- .hw_params = eti_b1_hw_params,
- .shutdown = eti_b1_shutdown,
-};
-
-
-static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
- SND_SOC_DAPM_MIC("Int Mic", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
-
- /* speaker connected to LHPOUT */
- {"Ext Spk", NULL, "LHPOUT"},
-
- /* mic is connected to Mic Jack, with WM8731 Mic Bias */
- {"MICIN", NULL, "Mic Bias"},
- {"Mic Bias", NULL, "Int Mic"},
-};
-
-/*
- * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
- */
-static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
-{
- DBG("eti_b1_wm8731_init() called\n");
-
- /* Add specific widgets */
- snd_soc_dapm_new_controls(codec, eti_b1_dapm_widgets,
- ARRAY_SIZE(eti_b1_dapm_widgets));
-
- /* Set up specific audio path interconnects */
- snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon));
-
- /* not connected */
- snd_soc_dapm_disable_pin(codec, "RLINEIN");
- snd_soc_dapm_disable_pin(codec, "LLINEIN");
-
- /* always connected */
- snd_soc_dapm_enable_pin(codec, "Int Mic");
- snd_soc_dapm_enable_pin(codec, "Ext Spk");
-
- snd_soc_dapm_sync(codec);
-
- return 0;
-}
-
-static struct snd_soc_dai_link eti_b1_dai = {
- .name = "WM8731",
- .stream_name = "WM8731 PCM",
- .cpu_dai = &at91_ssc_dai[1],
- .codec_dai = &wm8731_dai,
- .init = eti_b1_wm8731_init,
- .ops = &eti_b1_ops,
-};
-
-static struct snd_soc_machine snd_soc_machine_eti_b1 = {
- .name = "ETI_B1_WM8731",
- .dai_link = &eti_b1_dai,
- .num_links = 1,
-};
-
-static struct wm8731_setup_data eti_b1_wm8731_setup = {
- .i2c_address = 0x1a,
-};
-
-static struct snd_soc_device eti_b1_snd_devdata = {
- .machine = &snd_soc_machine_eti_b1,
- .platform = &at91_soc_platform,
- .codec_dev = &soc_codec_dev_wm8731,
- .codec_data = &eti_b1_wm8731_setup,
-};
-
-static struct platform_device *eti_b1_snd_device;
-
-static int __init eti_b1_init(void)
-{
- int ret;
- struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-
- if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
- DBG("SSC1 memory region is busy\n");
- return -EBUSY;
- }
-
- ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
- if (!ssc->base) {
- DBG("SSC1 memory ioremap failed\n");
- ret = -ENOMEM;
- goto fail_release_mem;
- }
-
- ssc->pid = AT91RM9200_ID_SSC1;
-
- eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
- if (!eti_b1_snd_device) {
- DBG("platform device allocation failed\n");
- ret = -ENOMEM;
- goto fail_io_unmap;
- }
-
- platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
- eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
-
- ret = platform_device_add(eti_b1_snd_device);
- if (ret) {
- DBG("platform device add failed\n");
- platform_device_put(eti_b1_snd_device);
- goto fail_io_unmap;
- }
-
- at91_set_A_periph(AT91_PIN_PB6, 0); /* TF1 */
- at91_set_A_periph(AT91_PIN_PB7, 0); /* TK1 */
- at91_set_A_periph(AT91_PIN_PB8, 0); /* TD1 */
- at91_set_A_periph(AT91_PIN_PB9, 0); /* RD1 */
-/* at91_set_A_periph(AT91_PIN_PB10, 0);*/ /* RK1 */
- at91_set_A_periph(AT91_PIN_PB11, 0); /* RF1 */
-
- /*
- * Set PCK1 parent to PLLB and its rate to 12 Mhz.
- */
- pllb_clk = clk_get(NULL, "pllb");
- pck1_clk = clk_get(NULL, "pck1");
-
- clk_set_parent(pck1_clk, pllb_clk);
- clk_set_rate(pck1_clk, 12000000);
-
- DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
-
- /* assign the GPIO pin to PCK1 */
- at91_set_B_periph(AT91_PIN_PA24, 0);
-
-#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
- printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
-#else
- printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
-#endif
- return ret;
-
-fail_io_unmap:
- iounmap(ssc->base);
-fail_release_mem:
- release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
- return ret;
-}
-
-static void __exit eti_b1_exit(void)
-{
- struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-
- clk_put(pck1_clk);
- clk_put(pllb_clk);
-
- platform_device_unregister(eti_b1_snd_device);
-
- iounmap(ssc->base);
- release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
-}
-
-module_init(eti_b1_init);
-module_exit(eti_b1_exit);
-
-/* Module information */
-MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
-MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
-MODULE_LICENSE("GPL");