Commit 0ed275eff31029c39355828cb48c46c0a006e2f8

Authored by Alexander Shiyan
Committed by Mark Brown
1 parent 3d721a34e6

ASoC: Rename ep93xx soc directory to cirrus

This patch is to rename the directory "ep93xx" in "cirrus".
Name more accurately reflects the manufacturer and allows to add
drivers not only for architecture ep93xx in this directory.
Patch not contain any functional changes.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 20 changed files with 1573 additions and 1573 deletions Side-by-side Diff

... ... @@ -33,9 +33,9 @@
33 33 source "sound/soc/atmel/Kconfig"
34 34 source "sound/soc/au1x/Kconfig"
35 35 source "sound/soc/blackfin/Kconfig"
  36 +source "sound/soc/cirrus/Kconfig"
36 37 source "sound/soc/davinci/Kconfig"
37 38 source "sound/soc/dwc/Kconfig"
38   -source "sound/soc/ep93xx/Kconfig"
39 39 source "sound/soc/fsl/Kconfig"
40 40 source "sound/soc/jz4740/Kconfig"
41 41 source "sound/soc/nuc900/Kconfig"
... ... @@ -10,9 +10,9 @@
10 10 obj-$(CONFIG_SND_SOC) += atmel/
11 11 obj-$(CONFIG_SND_SOC) += au1x/
12 12 obj-$(CONFIG_SND_SOC) += blackfin/
  13 +obj-$(CONFIG_SND_SOC) += cirrus/
13 14 obj-$(CONFIG_SND_SOC) += davinci/
14 15 obj-$(CONFIG_SND_SOC) += dwc/
15   -obj-$(CONFIG_SND_SOC) += ep93xx/
16 16 obj-$(CONFIG_SND_SOC) += fsl/
17 17 obj-$(CONFIG_SND_SOC) += jz4740/
18 18 obj-$(CONFIG_SND_SOC) += mid-x86/
sound/soc/cirrus/Kconfig
  1 +config SND_EP93XX_SOC
  2 + tristate "SoC Audio support for the Cirrus Logic EP93xx series"
  3 + depends on ARCH_EP93XX && SND_SOC
  4 + select SND_SOC_DMAENGINE_PCM
  5 + help
  6 + Say Y or M if you want to add support for codecs attached to
  7 + the EP93xx I2S or AC97 interfaces.
  8 +
  9 +config SND_EP93XX_SOC_I2S
  10 + tristate
  11 +
  12 +config SND_EP93XX_SOC_AC97
  13 + tristate
  14 + select AC97_BUS
  15 + select SND_SOC_AC97_BUS
  16 +
  17 +config SND_EP93XX_SOC_SNAPPERCL15
  18 + tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
  19 + depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
  20 + select SND_EP93XX_SOC_I2S
  21 + select SND_SOC_TLV320AIC23
  22 + help
  23 + Say Y or M here if you want to add support for I2S audio on the
  24 + Bluewater Systems Snapper CL15 module.
  25 +
  26 +config SND_EP93XX_SOC_SIMONE
  27 + tristate "SoC Audio support for Simplemachines Sim.One board"
  28 + depends on SND_EP93XX_SOC && MACH_SIM_ONE
  29 + select SND_EP93XX_SOC_AC97
  30 + select SND_SOC_AC97_CODEC
  31 + help
  32 + Say Y or M here if you want to add support for AC97 audio on the
  33 + Simplemachines Sim.One board.
  34 +
  35 +config SND_EP93XX_SOC_EDB93XX
  36 + tristate "SoC Audio support for Cirrus Logic EDB93xx boards"
  37 + depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A)
  38 + select SND_EP93XX_SOC_I2S
  39 + select SND_SOC_CS4271
  40 + help
  41 + Say Y or M here if you want to add support for I2S audio on the
  42 + Cirrus Logic EDB93xx boards.
sound/soc/cirrus/Makefile
  1 +# EP93xx Platform Support
  2 +snd-soc-ep93xx-objs := ep93xx-pcm.o
  3 +snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o
  4 +snd-soc-ep93xx-ac97-objs := ep93xx-ac97.o
  5 +
  6 +obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o
  7 +obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o
  8 +obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o
  9 +
  10 +# EP93XX Machine Support
  11 +snd-soc-snappercl15-objs := snappercl15.o
  12 +snd-soc-simone-objs := simone.o
  13 +snd-soc-edb93xx-objs := edb93xx.o
  14 +
  15 +obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o
  16 +obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o
  17 +obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o
sound/soc/cirrus/edb93xx.c
  1 +/*
  2 + * SoC audio for EDB93xx
  3 + *
  4 + * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License
  8 + * as published by the Free Software Foundation; either version 2
  9 + * of the License, or (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * This driver support CS4271 codec being master or slave, working
  17 + * in control port mode, connected either via SPI or I2C.
  18 + * The data format accepted is I2S or left-justified.
  19 + * DAPM support not implemented.
  20 + */
  21 +
  22 +#include <linux/platform_device.h>
  23 +#include <linux/gpio.h>
  24 +#include <linux/module.h>
  25 +#include <sound/core.h>
  26 +#include <sound/pcm.h>
  27 +#include <sound/soc.h>
  28 +#include <asm/mach-types.h>
  29 +#include <mach/hardware.h>
  30 +#include "ep93xx-pcm.h"
  31 +
  32 +static int edb93xx_hw_params(struct snd_pcm_substream *substream,
  33 + struct snd_pcm_hw_params *params)
  34 +{
  35 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  36 + struct snd_soc_dai *codec_dai = rtd->codec_dai;
  37 + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  38 + int err;
  39 + unsigned int mclk_rate;
  40 + unsigned int rate = params_rate(params);
  41 +
  42 + /*
  43 + * According to CS4271 datasheet we use MCLK/LRCK=256 for
  44 + * rates below 50kHz and 128 for higher sample rates
  45 + */
  46 + if (rate < 50000)
  47 + mclk_rate = rate * 64 * 4;
  48 + else
  49 + mclk_rate = rate * 64 * 2;
  50 +
  51 + err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate,
  52 + SND_SOC_CLOCK_IN);
  53 + if (err)
  54 + return err;
  55 +
  56 + return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate,
  57 + SND_SOC_CLOCK_OUT);
  58 +}
  59 +
  60 +static struct snd_soc_ops edb93xx_ops = {
  61 + .hw_params = edb93xx_hw_params,
  62 +};
  63 +
  64 +static struct snd_soc_dai_link edb93xx_dai = {
  65 + .name = "CS4271",
  66 + .stream_name = "CS4271 HiFi",
  67 + .platform_name = "ep93xx-pcm-audio",
  68 + .cpu_dai_name = "ep93xx-i2s",
  69 + .codec_name = "spi0.0",
  70 + .codec_dai_name = "cs4271-hifi",
  71 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
  72 + SND_SOC_DAIFMT_CBS_CFS,
  73 + .ops = &edb93xx_ops,
  74 +};
  75 +
  76 +static struct snd_soc_card snd_soc_edb93xx = {
  77 + .name = "EDB93XX",
  78 + .owner = THIS_MODULE,
  79 + .dai_link = &edb93xx_dai,
  80 + .num_links = 1,
  81 +};
  82 +
  83 +static int __devinit edb93xx_probe(struct platform_device *pdev)
  84 +{
  85 + struct snd_soc_card *card = &snd_soc_edb93xx;
  86 + int ret;
  87 +
  88 + ret = ep93xx_i2s_acquire();
  89 + if (ret)
  90 + return ret;
  91 +
  92 + card->dev = &pdev->dev;
  93 +
  94 + ret = snd_soc_register_card(card);
  95 + if (ret) {
  96 + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
  97 + ret);
  98 + ep93xx_i2s_release();
  99 + }
  100 +
  101 + return ret;
  102 +}
  103 +
  104 +static int __devexit edb93xx_remove(struct platform_device *pdev)
  105 +{
  106 + struct snd_soc_card *card = platform_get_drvdata(pdev);
  107 +
  108 + snd_soc_unregister_card(card);
  109 + ep93xx_i2s_release();
  110 +
  111 + return 0;
  112 +}
  113 +
  114 +static struct platform_driver edb93xx_driver = {
  115 + .driver = {
  116 + .name = "edb93xx-audio",
  117 + .owner = THIS_MODULE,
  118 + },
  119 + .probe = edb93xx_probe,
  120 + .remove = __devexit_p(edb93xx_remove),
  121 +};
  122 +
  123 +module_platform_driver(edb93xx_driver);
  124 +
  125 +MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
  126 +MODULE_DESCRIPTION("ALSA SoC EDB93xx");
  127 +MODULE_LICENSE("GPL");
  128 +MODULE_ALIAS("platform:edb93xx-audio");
sound/soc/cirrus/ep93xx-ac97.c
  1 +/*
  2 + * ASoC driver for Cirrus Logic EP93xx AC97 controller.
  3 + *
  4 + * Copyright (c) 2010 Mika Westerberg
  5 + *
  6 + * Based on s3c-ac97 ASoC driver by Jaswinder Singh.
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +
  13 +#include <linux/delay.h>
  14 +#include <linux/io.h>
  15 +#include <linux/init.h>
  16 +#include <linux/module.h>
  17 +#include <linux/platform_device.h>
  18 +#include <linux/slab.h>
  19 +
  20 +#include <sound/core.h>
  21 +#include <sound/ac97_codec.h>
  22 +#include <sound/soc.h>
  23 +
  24 +#include <mach/dma.h>
  25 +#include "ep93xx-pcm.h"
  26 +
  27 +/*
  28 + * Per channel (1-4) registers.
  29 + */
  30 +#define AC97CH(n) (((n) - 1) * 0x20)
  31 +
  32 +#define AC97DR(n) (AC97CH(n) + 0x0000)
  33 +
  34 +#define AC97RXCR(n) (AC97CH(n) + 0x0004)
  35 +#define AC97RXCR_REN BIT(0)
  36 +#define AC97RXCR_RX3 BIT(3)
  37 +#define AC97RXCR_RX4 BIT(4)
  38 +#define AC97RXCR_CM BIT(15)
  39 +
  40 +#define AC97TXCR(n) (AC97CH(n) + 0x0008)
  41 +#define AC97TXCR_TEN BIT(0)
  42 +#define AC97TXCR_TX3 BIT(3)
  43 +#define AC97TXCR_TX4 BIT(4)
  44 +#define AC97TXCR_CM BIT(15)
  45 +
  46 +#define AC97SR(n) (AC97CH(n) + 0x000c)
  47 +#define AC97SR_TXFE BIT(1)
  48 +#define AC97SR_TXUE BIT(6)
  49 +
  50 +#define AC97RISR(n) (AC97CH(n) + 0x0010)
  51 +#define AC97ISR(n) (AC97CH(n) + 0x0014)
  52 +#define AC97IE(n) (AC97CH(n) + 0x0018)
  53 +
  54 +/*
  55 + * Global AC97 controller registers.
  56 + */
  57 +#define AC97S1DATA 0x0080
  58 +#define AC97S2DATA 0x0084
  59 +#define AC97S12DATA 0x0088
  60 +
  61 +#define AC97RGIS 0x008c
  62 +#define AC97GIS 0x0090
  63 +#define AC97IM 0x0094
  64 +/*
  65 + * Common bits for RGIS, GIS and IM registers.
  66 + */
  67 +#define AC97_SLOT2RXVALID BIT(1)
  68 +#define AC97_CODECREADY BIT(5)
  69 +#define AC97_SLOT2TXCOMPLETE BIT(6)
  70 +
  71 +#define AC97EOI 0x0098
  72 +#define AC97EOI_WINT BIT(0)
  73 +#define AC97EOI_CODECREADY BIT(1)
  74 +
  75 +#define AC97GCR 0x009c
  76 +#define AC97GCR_AC97IFE BIT(0)
  77 +
  78 +#define AC97RESET 0x00a0
  79 +#define AC97RESET_TIMEDRESET BIT(0)
  80 +
  81 +#define AC97SYNC 0x00a4
  82 +#define AC97SYNC_TIMEDSYNC BIT(0)
  83 +
  84 +#define AC97_TIMEOUT msecs_to_jiffies(5)
  85 +
  86 +/**
  87 + * struct ep93xx_ac97_info - EP93xx AC97 controller info structure
  88 + * @lock: mutex serializing access to the bus (slot 1 & 2 ops)
  89 + * @dev: pointer to the platform device dev structure
  90 + * @regs: mapped AC97 controller registers
  91 + * @done: bus ops wait here for an interrupt
  92 + */
  93 +struct ep93xx_ac97_info {
  94 + struct mutex lock;
  95 + struct device *dev;
  96 + void __iomem *regs;
  97 + struct completion done;
  98 +};
  99 +
  100 +/* currently ALSA only supports a single AC97 device */
  101 +static struct ep93xx_ac97_info *ep93xx_ac97_info;
  102 +
  103 +static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
  104 + .name = "ac97-pcm-out",
  105 + .dma_port = EP93XX_DMA_AAC1,
  106 +};
  107 +
  108 +static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
  109 + .name = "ac97-pcm-in",
  110 + .dma_port = EP93XX_DMA_AAC1,
  111 +};
  112 +
  113 +static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
  114 + unsigned reg)
  115 +{
  116 + return __raw_readl(info->regs + reg);
  117 +}
  118 +
  119 +static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info,
  120 + unsigned reg, unsigned val)
  121 +{
  122 + __raw_writel(val, info->regs + reg);
  123 +}
  124 +
  125 +static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97,
  126 + unsigned short reg)
  127 +{
  128 + struct ep93xx_ac97_info *info = ep93xx_ac97_info;
  129 + unsigned short val;
  130 +
  131 + mutex_lock(&info->lock);
  132 +
  133 + ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
  134 + ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID);
  135 + if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) {
  136 + dev_warn(info->dev, "timeout reading register %x\n", reg);
  137 + mutex_unlock(&info->lock);
  138 + return -ETIMEDOUT;
  139 + }
  140 + val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA);
  141 +
  142 + mutex_unlock(&info->lock);
  143 + return val;
  144 +}
  145 +
  146 +static void ep93xx_ac97_write(struct snd_ac97 *ac97,
  147 + unsigned short reg,
  148 + unsigned short val)
  149 +{
  150 + struct ep93xx_ac97_info *info = ep93xx_ac97_info;
  151 +
  152 + mutex_lock(&info->lock);
  153 +
  154 + /*
  155 + * Writes to the codec need to be done so that slot 2 is filled in
  156 + * before slot 1.
  157 + */
  158 + ep93xx_ac97_write_reg(info, AC97S2DATA, val);
  159 + ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
  160 +
  161 + ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE);
  162 + if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
  163 + dev_warn(info->dev, "timeout writing register %x\n", reg);
  164 +
  165 + mutex_unlock(&info->lock);
  166 +}
  167 +
  168 +static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97)
  169 +{
  170 + struct ep93xx_ac97_info *info = ep93xx_ac97_info;
  171 +
  172 + mutex_lock(&info->lock);
  173 +
  174 + /*
  175 + * We are assuming that before this functions gets called, the codec
  176 + * BIT_CLK is stopped by forcing the codec into powerdown mode. We can
  177 + * control the SYNC signal directly via AC97SYNC register. Using
  178 + * TIMEDSYNC the controller will keep the SYNC high > 1us.
  179 + */
  180 + ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC);
  181 + ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
  182 + if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
  183 + dev_warn(info->dev, "codec warm reset timeout\n");
  184 +
  185 + mutex_unlock(&info->lock);
  186 +}
  187 +
  188 +static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97)
  189 +{
  190 + struct ep93xx_ac97_info *info = ep93xx_ac97_info;
  191 +
  192 + mutex_lock(&info->lock);
  193 +
  194 + /*
  195 + * For doing cold reset, we disable the AC97 controller interface, clear
  196 + * WINT and CODECREADY bits, and finally enable the interface again.
  197 + */
  198 + ep93xx_ac97_write_reg(info, AC97GCR, 0);
  199 + ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT);
  200 + ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE);
  201 +
  202 + /*
  203 + * Now, assert the reset and wait for the codec to become ready.
  204 + */
  205 + ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET);
  206 + ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
  207 + if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
  208 + dev_warn(info->dev, "codec cold reset timeout\n");
  209 +
  210 + /*
  211 + * Give the codec some time to come fully out from the reset. This way
  212 + * we ensure that the subsequent reads/writes will work.
  213 + */
  214 + usleep_range(15000, 20000);
  215 +
  216 + mutex_unlock(&info->lock);
  217 +}
  218 +
  219 +static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id)
  220 +{
  221 + struct ep93xx_ac97_info *info = dev_id;
  222 + unsigned status, mask;
  223 +
  224 + /*
  225 + * Just mask out the interrupt and wake up the waiting thread.
  226 + * Interrupts are cleared via reading/writing to slot 1 & 2 registers by
  227 + * the waiting thread.
  228 + */
  229 + status = ep93xx_ac97_read_reg(info, AC97GIS);
  230 + mask = ep93xx_ac97_read_reg(info, AC97IM);
  231 + mask &= ~status;
  232 + ep93xx_ac97_write_reg(info, AC97IM, mask);
  233 +
  234 + complete(&info->done);
  235 + return IRQ_HANDLED;
  236 +}
  237 +
  238 +struct snd_ac97_bus_ops soc_ac97_ops = {
  239 + .read = ep93xx_ac97_read,
  240 + .write = ep93xx_ac97_write,
  241 + .reset = ep93xx_ac97_cold_reset,
  242 + .warm_reset = ep93xx_ac97_warm_reset,
  243 +};
  244 +EXPORT_SYMBOL_GPL(soc_ac97_ops);
  245 +
  246 +static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
  247 + int cmd, struct snd_soc_dai *dai)
  248 +{
  249 + struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai);
  250 + unsigned v = 0;
  251 +
  252 + switch (cmd) {
  253 + case SNDRV_PCM_TRIGGER_START:
  254 + case SNDRV_PCM_TRIGGER_RESUME:
  255 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  256 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  257 + /*
  258 + * Enable compact mode, TX slots 3 & 4, and the TX FIFO
  259 + * itself.
  260 + */
  261 + v |= AC97TXCR_CM;
  262 + v |= AC97TXCR_TX3 | AC97TXCR_TX4;
  263 + v |= AC97TXCR_TEN;
  264 + ep93xx_ac97_write_reg(info, AC97TXCR(1), v);
  265 + } else {
  266 + /*
  267 + * Enable compact mode, RX slots 3 & 4, and the RX FIFO
  268 + * itself.
  269 + */
  270 + v |= AC97RXCR_CM;
  271 + v |= AC97RXCR_RX3 | AC97RXCR_RX4;
  272 + v |= AC97RXCR_REN;
  273 + ep93xx_ac97_write_reg(info, AC97RXCR(1), v);
  274 + }
  275 + break;
  276 +
  277 + case SNDRV_PCM_TRIGGER_STOP:
  278 + case SNDRV_PCM_TRIGGER_SUSPEND:
  279 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  280 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  281 + /*
  282 + * As per Cirrus EP93xx errata described below:
  283 + *
  284 + * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf
  285 + *
  286 + * we will wait for the TX FIFO to be empty before
  287 + * clearing the TEN bit.
  288 + */
  289 + unsigned long timeout = jiffies + AC97_TIMEOUT;
  290 +
  291 + do {
  292 + v = ep93xx_ac97_read_reg(info, AC97SR(1));
  293 + if (time_after(jiffies, timeout)) {
  294 + dev_warn(info->dev, "TX timeout\n");
  295 + break;
  296 + }
  297 + } while (!(v & (AC97SR_TXFE | AC97SR_TXUE)));
  298 +
  299 + /* disable the TX FIFO */
  300 + ep93xx_ac97_write_reg(info, AC97TXCR(1), 0);
  301 + } else {
  302 + /* disable the RX FIFO */
  303 + ep93xx_ac97_write_reg(info, AC97RXCR(1), 0);
  304 + }
  305 + break;
  306 +
  307 + default:
  308 + dev_warn(info->dev, "unknown command %d\n", cmd);
  309 + return -EINVAL;
  310 + }
  311 +
  312 + return 0;
  313 +}
  314 +
  315 +static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
  316 + struct snd_soc_dai *dai)
  317 +{
  318 + struct ep93xx_pcm_dma_params *dma_data;
  319 +
  320 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  321 + dma_data = &ep93xx_ac97_pcm_out;
  322 + else
  323 + dma_data = &ep93xx_ac97_pcm_in;
  324 +
  325 + snd_soc_dai_set_dma_data(dai, substream, dma_data);
  326 + return 0;
  327 +}
  328 +
  329 +static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
  330 + .startup = ep93xx_ac97_startup,
  331 + .trigger = ep93xx_ac97_trigger,
  332 +};
  333 +
  334 +static struct snd_soc_dai_driver ep93xx_ac97_dai = {
  335 + .name = "ep93xx-ac97",
  336 + .id = 0,
  337 + .ac97_control = 1,
  338 + .playback = {
  339 + .stream_name = "AC97 Playback",
  340 + .channels_min = 2,
  341 + .channels_max = 2,
  342 + .rates = SNDRV_PCM_RATE_8000_48000,
  343 + .formats = SNDRV_PCM_FMTBIT_S16_LE,
  344 + },
  345 + .capture = {
  346 + .stream_name = "AC97 Capture",
  347 + .channels_min = 2,
  348 + .channels_max = 2,
  349 + .rates = SNDRV_PCM_RATE_8000_48000,
  350 + .formats = SNDRV_PCM_FMTBIT_S16_LE,
  351 + },
  352 + .ops = &ep93xx_ac97_dai_ops,
  353 +};
  354 +
  355 +static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
  356 +{
  357 + struct ep93xx_ac97_info *info;
  358 + struct resource *res;
  359 + unsigned int irq;
  360 + int ret;
  361 +
  362 + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
  363 + if (!info)
  364 + return -ENOMEM;
  365 +
  366 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  367 + if (!res)
  368 + return -ENODEV;
  369 +
  370 + info->regs = devm_request_and_ioremap(&pdev->dev, res);
  371 + if (!info->regs)
  372 + return -ENXIO;
  373 +
  374 + irq = platform_get_irq(pdev, 0);
  375 + if (!irq)
  376 + return -ENODEV;
  377 +
  378 + ret = devm_request_irq(&pdev->dev, irq, ep93xx_ac97_interrupt,
  379 + IRQF_TRIGGER_HIGH, pdev->name, info);
  380 + if (ret)
  381 + goto fail;
  382 +
  383 + dev_set_drvdata(&pdev->dev, info);
  384 +
  385 + mutex_init(&info->lock);
  386 + init_completion(&info->done);
  387 + info->dev = &pdev->dev;
  388 +
  389 + ep93xx_ac97_info = info;
  390 + platform_set_drvdata(pdev, info);
  391 +
  392 + ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
  393 + if (ret)
  394 + goto fail;
  395 +
  396 + return 0;
  397 +
  398 +fail:
  399 + platform_set_drvdata(pdev, NULL);
  400 + ep93xx_ac97_info = NULL;
  401 + dev_set_drvdata(&pdev->dev, NULL);
  402 + return ret;
  403 +}
  404 +
  405 +static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
  406 +{
  407 + struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
  408 +
  409 + snd_soc_unregister_dai(&pdev->dev);
  410 +
  411 + /* disable the AC97 controller */
  412 + ep93xx_ac97_write_reg(info, AC97GCR, 0);
  413 +
  414 + platform_set_drvdata(pdev, NULL);
  415 + ep93xx_ac97_info = NULL;
  416 + dev_set_drvdata(&pdev->dev, NULL);
  417 +
  418 + return 0;
  419 +}
  420 +
  421 +static struct platform_driver ep93xx_ac97_driver = {
  422 + .probe = ep93xx_ac97_probe,
  423 + .remove = __devexit_p(ep93xx_ac97_remove),
  424 + .driver = {
  425 + .name = "ep93xx-ac97",
  426 + .owner = THIS_MODULE,
  427 + },
  428 +};
  429 +
  430 +module_platform_driver(ep93xx_ac97_driver);
  431 +
  432 +MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
  433 +MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
  434 +MODULE_LICENSE("GPL");
  435 +MODULE_ALIAS("platform:ep93xx-ac97");
sound/soc/cirrus/ep93xx-i2s.c
  1 +/*
  2 + * linux/sound/soc/ep93xx-i2s.c
  3 + * EP93xx I2S driver
  4 + *
  5 + * Copyright (C) 2010 Ryan Mallon
  6 + *
  7 + * Based on the original driver by:
  8 + * Copyright (C) 2007 Chase Douglas <chasedouglas@gmail>
  9 + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
  10 + *
  11 + * This program is free software; you can redistribute it and/or modify
  12 + * it under the terms of the GNU General Public License version 2 as
  13 + * published by the Free Software Foundation.
  14 + *
  15 + */
  16 +
  17 +#include <linux/module.h>
  18 +#include <linux/init.h>
  19 +#include <linux/slab.h>
  20 +#include <linux/clk.h>
  21 +#include <linux/io.h>
  22 +
  23 +#include <sound/core.h>
  24 +#include <sound/pcm.h>
  25 +#include <sound/pcm_params.h>
  26 +#include <sound/initval.h>
  27 +#include <sound/soc.h>
  28 +
  29 +#include <mach/hardware.h>
  30 +#include <mach/ep93xx-regs.h>
  31 +#include <mach/dma.h>
  32 +
  33 +#include "ep93xx-pcm.h"
  34 +
  35 +#define EP93XX_I2S_TXCLKCFG 0x00
  36 +#define EP93XX_I2S_RXCLKCFG 0x04
  37 +#define EP93XX_I2S_GLCTRL 0x0C
  38 +
  39 +#define EP93XX_I2S_TXLINCTRLDATA 0x28
  40 +#define EP93XX_I2S_TXCTRL 0x2C
  41 +#define EP93XX_I2S_TXWRDLEN 0x30
  42 +#define EP93XX_I2S_TX0EN 0x34
  43 +
  44 +#define EP93XX_I2S_RXLINCTRLDATA 0x58
  45 +#define EP93XX_I2S_RXCTRL 0x5C
  46 +#define EP93XX_I2S_RXWRDLEN 0x60
  47 +#define EP93XX_I2S_RX0EN 0x64
  48 +
  49 +#define EP93XX_I2S_WRDLEN_16 (0 << 0)
  50 +#define EP93XX_I2S_WRDLEN_24 (1 << 0)
  51 +#define EP93XX_I2S_WRDLEN_32 (2 << 0)
  52 +
  53 +#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */
  54 +
  55 +#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */
  56 +#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */
  57 +#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */
  58 +#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */
  59 +#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */
  60 +
  61 +struct ep93xx_i2s_info {
  62 + struct clk *mclk;
  63 + struct clk *sclk;
  64 + struct clk *lrclk;
  65 + struct ep93xx_pcm_dma_params *dma_params;
  66 + void __iomem *regs;
  67 +};
  68 +
  69 +struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = {
  70 + [SNDRV_PCM_STREAM_PLAYBACK] = {
  71 + .name = "i2s-pcm-out",
  72 + .dma_port = EP93XX_DMA_I2S1,
  73 + },
  74 + [SNDRV_PCM_STREAM_CAPTURE] = {
  75 + .name = "i2s-pcm-in",
  76 + .dma_port = EP93XX_DMA_I2S1,
  77 + },
  78 +};
  79 +
  80 +static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info,
  81 + unsigned reg, unsigned val)
  82 +{
  83 + __raw_writel(val, info->regs + reg);
  84 +}
  85 +
  86 +static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info,
  87 + unsigned reg)
  88 +{
  89 + return __raw_readl(info->regs + reg);
  90 +}
  91 +
  92 +static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream)
  93 +{
  94 + unsigned base_reg;
  95 + int i;
  96 +
  97 + if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
  98 + (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
  99 + /* Enable clocks */
  100 + clk_enable(info->mclk);
  101 + clk_enable(info->sclk);
  102 + clk_enable(info->lrclk);
  103 +
  104 + /* Enable i2s */
  105 + ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1);
  106 + }
  107 +
  108 + /* Enable fifos */
  109 + if (stream == SNDRV_PCM_STREAM_PLAYBACK)
  110 + base_reg = EP93XX_I2S_TX0EN;
  111 + else
  112 + base_reg = EP93XX_I2S_RX0EN;
  113 + for (i = 0; i < 3; i++)
  114 + ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1);
  115 +}
  116 +
  117 +static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
  118 +{
  119 + unsigned base_reg;
  120 + int i;
  121 +
  122 + /* Disable fifos */
  123 + if (stream == SNDRV_PCM_STREAM_PLAYBACK)
  124 + base_reg = EP93XX_I2S_TX0EN;
  125 + else
  126 + base_reg = EP93XX_I2S_RX0EN;
  127 + for (i = 0; i < 3; i++)
  128 + ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0);
  129 +
  130 + if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
  131 + (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
  132 + /* Disable i2s */
  133 + ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0);
  134 +
  135 + /* Disable clocks */
  136 + clk_disable(info->lrclk);
  137 + clk_disable(info->sclk);
  138 + clk_disable(info->mclk);
  139 + }
  140 +}
  141 +
  142 +static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
  143 + struct snd_soc_dai *dai)
  144 +{
  145 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  146 + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
  147 + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  148 +
  149 + snd_soc_dai_set_dma_data(cpu_dai, substream,
  150 + &info->dma_params[substream->stream]);
  151 + return 0;
  152 +}
  153 +
  154 +static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
  155 + struct snd_soc_dai *dai)
  156 +{
  157 + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
  158 +
  159 + ep93xx_i2s_disable(info, substream->stream);
  160 +}
  161 +
  162 +static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
  163 + unsigned int fmt)
  164 +{
  165 + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
  166 + unsigned int clk_cfg, lin_ctrl;
  167 +
  168 + clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
  169 + lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA);
  170 +
  171 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  172 + case SND_SOC_DAIFMT_I2S:
  173 + clk_cfg |= EP93XX_I2S_CLKCFG_REL;
  174 + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
  175 + break;
  176 +
  177 + case SND_SOC_DAIFMT_LEFT_J:
  178 + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
  179 + lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
  180 + break;
  181 +
  182 + case SND_SOC_DAIFMT_RIGHT_J:
  183 + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
  184 + lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST;
  185 + break;
  186 +
  187 + default:
  188 + return -EINVAL;
  189 + }
  190 +
  191 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  192 + case SND_SOC_DAIFMT_CBS_CFS:
  193 + /* CPU is master */
  194 + clk_cfg |= EP93XX_I2S_CLKCFG_MASTER;
  195 + break;
  196 +
  197 + case SND_SOC_DAIFMT_CBM_CFM:
  198 + /* Codec is master */
  199 + clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER;
  200 + break;
  201 +
  202 + default:
  203 + return -EINVAL;
  204 + }
  205 +
  206 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  207 + case SND_SOC_DAIFMT_NB_NF:
  208 + /* Negative bit clock, lrclk low on left word */
  209 + clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL);
  210 + break;
  211 +
  212 + case SND_SOC_DAIFMT_NB_IF:
  213 + /* Negative bit clock, lrclk low on right word */
  214 + clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP;
  215 + clk_cfg |= EP93XX_I2S_CLKCFG_REL;
  216 + break;
  217 +
  218 + case SND_SOC_DAIFMT_IB_NF:
  219 + /* Positive bit clock, lrclk low on left word */
  220 + clk_cfg |= EP93XX_I2S_CLKCFG_CKP;
  221 + clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
  222 + break;
  223 +
  224 + case SND_SOC_DAIFMT_IB_IF:
  225 + /* Positive bit clock, lrclk low on right word */
  226 + clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL;
  227 + break;
  228 + }
  229 +
  230 + /* Write new register values */
  231 + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg);
  232 + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg);
  233 + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl);
  234 + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl);
  235 + return 0;
  236 +}
  237 +
  238 +static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
  239 + struct snd_pcm_hw_params *params,
  240 + struct snd_soc_dai *dai)
  241 +{
  242 + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
  243 + unsigned word_len, div, sdiv, lrdiv;
  244 + int err;
  245 +
  246 + switch (params_format(params)) {
  247 + case SNDRV_PCM_FORMAT_S16_LE:
  248 + word_len = EP93XX_I2S_WRDLEN_16;
  249 + break;
  250 +
  251 + case SNDRV_PCM_FORMAT_S24_LE:
  252 + word_len = EP93XX_I2S_WRDLEN_24;
  253 + break;
  254 +
  255 + case SNDRV_PCM_FORMAT_S32_LE:
  256 + word_len = EP93XX_I2S_WRDLEN_32;
  257 + break;
  258 +
  259 + default:
  260 + return -EINVAL;
  261 + }
  262 +
  263 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  264 + ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len);
  265 + else
  266 + ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len);
  267 +
  268 + /*
  269 + * EP93xx I2S module can be setup so SCLK / LRCLK value can be
  270 + * 32, 64, 128. MCLK / SCLK value can be 2 and 4.
  271 + * We set LRCLK equal to `rate' and minimum SCLK / LRCLK
  272 + * value is 64, because our sample size is 32 bit * 2 channels.
  273 + * I2S standard permits us to transmit more bits than
  274 + * the codec uses.
  275 + */
  276 + div = clk_get_rate(info->mclk) / params_rate(params);
  277 + sdiv = 4;
  278 + if (div > (256 + 512) / 2) {
  279 + lrdiv = 128;
  280 + } else {
  281 + lrdiv = 64;
  282 + if (div < (128 + 256) / 2)
  283 + sdiv = 2;
  284 + }
  285 +
  286 + err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
  287 + if (err)
  288 + return err;
  289 +
  290 + err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv);
  291 + if (err)
  292 + return err;
  293 +
  294 + ep93xx_i2s_enable(info, substream->stream);
  295 + return 0;
  296 +}
  297 +
  298 +static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
  299 + unsigned int freq, int dir)
  300 +{
  301 + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
  302 +
  303 + if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
  304 + return -EINVAL;
  305 +
  306 + return clk_set_rate(info->mclk, freq);
  307 +}
  308 +
  309 +#ifdef CONFIG_PM
  310 +static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
  311 +{
  312 + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
  313 +
  314 + if (!dai->active)
  315 + return 0;
  316 +
  317 + ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
  318 + ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
  319 +
  320 + return 0;
  321 +}
  322 +
  323 +static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
  324 +{
  325 + struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
  326 +
  327 + if (!dai->active)
  328 + return 0;
  329 +
  330 + ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
  331 + ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
  332 +
  333 + return 0;
  334 +}
  335 +#else
  336 +#define ep93xx_i2s_suspend NULL
  337 +#define ep93xx_i2s_resume NULL
  338 +#endif
  339 +
  340 +static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
  341 + .startup = ep93xx_i2s_startup,
  342 + .shutdown = ep93xx_i2s_shutdown,
  343 + .hw_params = ep93xx_i2s_hw_params,
  344 + .set_sysclk = ep93xx_i2s_set_sysclk,
  345 + .set_fmt = ep93xx_i2s_set_dai_fmt,
  346 +};
  347 +
  348 +#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
  349 +
  350 +static struct snd_soc_dai_driver ep93xx_i2s_dai = {
  351 + .symmetric_rates= 1,
  352 + .suspend = ep93xx_i2s_suspend,
  353 + .resume = ep93xx_i2s_resume,
  354 + .playback = {
  355 + .channels_min = 2,
  356 + .channels_max = 2,
  357 + .rates = SNDRV_PCM_RATE_8000_192000,
  358 + .formats = EP93XX_I2S_FORMATS,
  359 + },
  360 + .capture = {
  361 + .channels_min = 2,
  362 + .channels_max = 2,
  363 + .rates = SNDRV_PCM_RATE_8000_192000,
  364 + .formats = EP93XX_I2S_FORMATS,
  365 + },
  366 + .ops = &ep93xx_i2s_dai_ops,
  367 +};
  368 +
  369 +static int ep93xx_i2s_probe(struct platform_device *pdev)
  370 +{
  371 + struct ep93xx_i2s_info *info;
  372 + struct resource *res;
  373 + int err;
  374 +
  375 + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
  376 + if (!info)
  377 + return -ENOMEM;
  378 +
  379 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  380 + if (!res)
  381 + return -ENODEV;
  382 +
  383 + info->regs = devm_request_and_ioremap(&pdev->dev, res);
  384 + if (!info->regs)
  385 + return -ENXIO;
  386 +
  387 + info->mclk = clk_get(&pdev->dev, "mclk");
  388 + if (IS_ERR(info->mclk)) {
  389 + err = PTR_ERR(info->mclk);
  390 + goto fail;
  391 + }
  392 +
  393 + info->sclk = clk_get(&pdev->dev, "sclk");
  394 + if (IS_ERR(info->sclk)) {
  395 + err = PTR_ERR(info->sclk);
  396 + goto fail_put_mclk;
  397 + }
  398 +
  399 + info->lrclk = clk_get(&pdev->dev, "lrclk");
  400 + if (IS_ERR(info->lrclk)) {
  401 + err = PTR_ERR(info->lrclk);
  402 + goto fail_put_sclk;
  403 + }
  404 +
  405 + dev_set_drvdata(&pdev->dev, info);
  406 + info->dma_params = ep93xx_i2s_dma_params;
  407 +
  408 + err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
  409 + if (err)
  410 + goto fail_put_lrclk;
  411 +
  412 + return 0;
  413 +
  414 +fail_put_lrclk:
  415 + dev_set_drvdata(&pdev->dev, NULL);
  416 + clk_put(info->lrclk);
  417 +fail_put_sclk:
  418 + clk_put(info->sclk);
  419 +fail_put_mclk:
  420 + clk_put(info->mclk);
  421 +fail:
  422 + return err;
  423 +}
  424 +
  425 +static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
  426 +{
  427 + struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
  428 +
  429 + snd_soc_unregister_dai(&pdev->dev);
  430 + dev_set_drvdata(&pdev->dev, NULL);
  431 + clk_put(info->lrclk);
  432 + clk_put(info->sclk);
  433 + clk_put(info->mclk);
  434 + return 0;
  435 +}
  436 +
  437 +static struct platform_driver ep93xx_i2s_driver = {
  438 + .probe = ep93xx_i2s_probe,
  439 + .remove = __devexit_p(ep93xx_i2s_remove),
  440 + .driver = {
  441 + .name = "ep93xx-i2s",
  442 + .owner = THIS_MODULE,
  443 + },
  444 +};
  445 +
  446 +module_platform_driver(ep93xx_i2s_driver);
  447 +
  448 +MODULE_ALIAS("platform:ep93xx-i2s");
  449 +MODULE_AUTHOR("Ryan Mallon");
  450 +MODULE_DESCRIPTION("EP93XX I2S driver");
  451 +MODULE_LICENSE("GPL");
sound/soc/cirrus/ep93xx-pcm.c
  1 +/*
  2 + * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface
  3 + *
  4 + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
  5 + * Copyright (C) 2006 Applied Data Systems
  6 + *
  7 + * Rewritten for the SoC audio subsystem (Based on PXA2xx code):
  8 + * Copyright (c) 2008 Ryan Mallon
  9 + *
  10 + * This program is free software; you can redistribute it and/or modify
  11 + * it under the terms of the GNU General Public License version 2 as
  12 + * published by the Free Software Foundation.
  13 + */
  14 +
  15 +#include <linux/module.h>
  16 +#include <linux/init.h>
  17 +#include <linux/device.h>
  18 +#include <linux/slab.h>
  19 +#include <linux/dmaengine.h>
  20 +#include <linux/dma-mapping.h>
  21 +
  22 +#include <sound/core.h>
  23 +#include <sound/pcm.h>
  24 +#include <sound/pcm_params.h>
  25 +#include <sound/soc.h>
  26 +#include <sound/dmaengine_pcm.h>
  27 +
  28 +#include <mach/dma.h>
  29 +#include <mach/hardware.h>
  30 +#include <mach/ep93xx-regs.h>
  31 +
  32 +#include "ep93xx-pcm.h"
  33 +
  34 +static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
  35 + .info = (SNDRV_PCM_INFO_MMAP |
  36 + SNDRV_PCM_INFO_MMAP_VALID |
  37 + SNDRV_PCM_INFO_INTERLEAVED |
  38 + SNDRV_PCM_INFO_BLOCK_TRANSFER),
  39 +
  40 + .rates = SNDRV_PCM_RATE_8000_192000,
  41 + .rate_min = SNDRV_PCM_RATE_8000,
  42 + .rate_max = SNDRV_PCM_RATE_192000,
  43 +
  44 + .formats = (SNDRV_PCM_FMTBIT_S16_LE |
  45 + SNDRV_PCM_FMTBIT_S24_LE |
  46 + SNDRV_PCM_FMTBIT_S32_LE),
  47 +
  48 + .buffer_bytes_max = 131072,
  49 + .period_bytes_min = 32,
  50 + .period_bytes_max = 32768,
  51 + .periods_min = 1,
  52 + .periods_max = 32,
  53 + .fifo_size = 32,
  54 +};
  55 +
  56 +static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
  57 +{
  58 + struct ep93xx_dma_data *data = filter_param;
  59 +
  60 + if (data->direction == ep93xx_dma_chan_direction(chan)) {
  61 + chan->private = data;
  62 + return true;
  63 + }
  64 +
  65 + return false;
  66 +}
  67 +
  68 +static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
  69 +{
  70 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  71 + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  72 + struct ep93xx_pcm_dma_params *dma_params;
  73 + struct ep93xx_dma_data *dma_data;
  74 + int ret;
  75 +
  76 + snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
  77 +
  78 + dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
  79 + if (!dma_data)
  80 + return -ENOMEM;
  81 +
  82 + dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
  83 + dma_data->port = dma_params->dma_port;
  84 + dma_data->name = dma_params->name;
  85 + dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
  86 +
  87 + ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
  88 + if (ret) {
  89 + kfree(dma_data);
  90 + return ret;
  91 + }
  92 +
  93 + snd_dmaengine_pcm_set_data(substream, dma_data);
  94 +
  95 + return 0;
  96 +}
  97 +
  98 +static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
  99 +{
  100 + struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
  101 +
  102 + snd_dmaengine_pcm_close(substream);
  103 + kfree(dma_data);
  104 + return 0;
  105 +}
  106 +
  107 +static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
  108 + struct snd_pcm_hw_params *params)
  109 +{
  110 + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
  111 +
  112 + return 0;
  113 +}
  114 +
  115 +static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
  116 +{
  117 + snd_pcm_set_runtime_buffer(substream, NULL);
  118 + return 0;
  119 +}
  120 +
  121 +static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
  122 + struct vm_area_struct *vma)
  123 +{
  124 + struct snd_pcm_runtime *runtime = substream->runtime;
  125 +
  126 + return dma_mmap_writecombine(substream->pcm->card->dev, vma,
  127 + runtime->dma_area,
  128 + runtime->dma_addr,
  129 + runtime->dma_bytes);
  130 +}
  131 +
  132 +static struct snd_pcm_ops ep93xx_pcm_ops = {
  133 + .open = ep93xx_pcm_open,
  134 + .close = ep93xx_pcm_close,
  135 + .ioctl = snd_pcm_lib_ioctl,
  136 + .hw_params = ep93xx_pcm_hw_params,
  137 + .hw_free = ep93xx_pcm_hw_free,
  138 + .trigger = snd_dmaengine_pcm_trigger,
  139 + .pointer = snd_dmaengine_pcm_pointer_no_residue,
  140 + .mmap = ep93xx_pcm_mmap,
  141 +};
  142 +
  143 +static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
  144 +{
  145 + struct snd_pcm_substream *substream = pcm->streams[stream].substream;
  146 + struct snd_dma_buffer *buf = &substream->dma_buffer;
  147 + size_t size = ep93xx_pcm_hardware.buffer_bytes_max;
  148 +
  149 + buf->dev.type = SNDRV_DMA_TYPE_DEV;
  150 + buf->dev.dev = pcm->card->dev;
  151 + buf->private_data = NULL;
  152 + buf->area = dma_alloc_writecombine(pcm->card->dev, size,
  153 + &buf->addr, GFP_KERNEL);
  154 + buf->bytes = size;
  155 +
  156 + return (buf->area == NULL) ? -ENOMEM : 0;
  157 +}
  158 +
  159 +static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
  160 +{
  161 + struct snd_pcm_substream *substream;
  162 + struct snd_dma_buffer *buf;
  163 + int stream;
  164 +
  165 + for (stream = 0; stream < 2; stream++) {
  166 + substream = pcm->streams[stream].substream;
  167 + if (!substream)
  168 + continue;
  169 +
  170 + buf = &substream->dma_buffer;
  171 + if (!buf->area)
  172 + continue;
  173 +
  174 + dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area,
  175 + buf->addr);
  176 + buf->area = NULL;
  177 + }
  178 +}
  179 +
  180 +static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32);
  181 +
  182 +static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
  183 +{
  184 + struct snd_card *card = rtd->card->snd_card;
  185 + struct snd_pcm *pcm = rtd->pcm;
  186 + int ret = 0;
  187 +
  188 + if (!card->dev->dma_mask)
  189 + card->dev->dma_mask = &ep93xx_pcm_dmamask;
  190 + if (!card->dev->coherent_dma_mask)
  191 + card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
  192 +
  193 + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
  194 + ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
  195 + SNDRV_PCM_STREAM_PLAYBACK);
  196 + if (ret)
  197 + return ret;
  198 + }
  199 +
  200 + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
  201 + ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
  202 + SNDRV_PCM_STREAM_CAPTURE);
  203 + if (ret)
  204 + return ret;
  205 + }
  206 +
  207 + return 0;
  208 +}
  209 +
  210 +static struct snd_soc_platform_driver ep93xx_soc_platform = {
  211 + .ops = &ep93xx_pcm_ops,
  212 + .pcm_new = &ep93xx_pcm_new,
  213 + .pcm_free = &ep93xx_pcm_free_dma_buffers,
  214 +};
  215 +
  216 +static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
  217 +{
  218 + return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
  219 +}
  220 +
  221 +static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
  222 +{
  223 + snd_soc_unregister_platform(&pdev->dev);
  224 + return 0;
  225 +}
  226 +
  227 +static struct platform_driver ep93xx_pcm_driver = {
  228 + .driver = {
  229 + .name = "ep93xx-pcm-audio",
  230 + .owner = THIS_MODULE,
  231 + },
  232 +
  233 + .probe = ep93xx_soc_platform_probe,
  234 + .remove = __devexit_p(ep93xx_soc_platform_remove),
  235 +};
  236 +
  237 +module_platform_driver(ep93xx_pcm_driver);
  238 +
  239 +MODULE_AUTHOR("Ryan Mallon");
  240 +MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
  241 +MODULE_LICENSE("GPL");
  242 +MODULE_ALIAS("platform:ep93xx-pcm-audio");
sound/soc/cirrus/ep93xx-pcm.h
  1 +/*
  2 + * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface
  3 + *
  4 + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
  5 + * Copyright (C) 2006 Applied Data Systems
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License version 2 as
  9 + * published by the Free Software Foundation.
  10 + */
  11 +
  12 +#ifndef _EP93XX_SND_SOC_PCM_H
  13 +#define _EP93XX_SND_SOC_PCM_H
  14 +
  15 +struct ep93xx_pcm_dma_params {
  16 + char *name;
  17 + int dma_port;
  18 +};
  19 +
  20 +#endif /* _EP93XX_SND_SOC_PCM_H */
sound/soc/cirrus/simone.c
  1 +/*
  2 + * simone.c -- ASoC audio for Simplemachines Sim.One board
  3 + *
  4 + * Copyright (c) 2010 Mika Westerberg
  5 + *
  6 + * Based on snappercl15 machine driver by Ryan Mallon.
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +
  13 +#include <linux/init.h>
  14 +#include <linux/module.h>
  15 +#include <linux/platform_device.h>
  16 +
  17 +#include <sound/core.h>
  18 +#include <sound/pcm.h>
  19 +#include <sound/soc.h>
  20 +
  21 +#include <asm/mach-types.h>
  22 +#include <mach/hardware.h>
  23 +
  24 +#include "ep93xx-pcm.h"
  25 +
  26 +static struct snd_soc_dai_link simone_dai = {
  27 + .name = "AC97",
  28 + .stream_name = "AC97 HiFi",
  29 + .cpu_dai_name = "ep93xx-ac97",
  30 + .codec_dai_name = "ac97-hifi",
  31 + .codec_name = "ac97-codec",
  32 + .platform_name = "ep93xx-pcm-audio",
  33 +};
  34 +
  35 +static struct snd_soc_card snd_soc_simone = {
  36 + .name = "Sim.One",
  37 + .owner = THIS_MODULE,
  38 + .dai_link = &simone_dai,
  39 + .num_links = 1,
  40 +};
  41 +
  42 +static struct platform_device *simone_snd_ac97_device;
  43 +
  44 +static int __devinit simone_probe(struct platform_device *pdev)
  45 +{
  46 + struct snd_soc_card *card = &snd_soc_simone;
  47 + int ret;
  48 +
  49 + simone_snd_ac97_device = platform_device_register_simple("ac97-codec",
  50 + -1, NULL, 0);
  51 + if (IS_ERR(simone_snd_ac97_device))
  52 + return PTR_ERR(simone_snd_ac97_device);
  53 +
  54 + card->dev = &pdev->dev;
  55 +
  56 + ret = snd_soc_register_card(card);
  57 + if (ret) {
  58 + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
  59 + ret);
  60 + platform_device_unregister(simone_snd_ac97_device);
  61 + }
  62 +
  63 + return ret;
  64 +}
  65 +
  66 +static int __devexit simone_remove(struct platform_device *pdev)
  67 +{
  68 + struct snd_soc_card *card = platform_get_drvdata(pdev);
  69 +
  70 + snd_soc_unregister_card(card);
  71 + platform_device_unregister(simone_snd_ac97_device);
  72 +
  73 + return 0;
  74 +}
  75 +
  76 +static struct platform_driver simone_driver = {
  77 + .driver = {
  78 + .name = "simone-audio",
  79 + .owner = THIS_MODULE,
  80 + },
  81 + .probe = simone_probe,
  82 + .remove = __devexit_p(simone_remove),
  83 +};
  84 +
  85 +module_platform_driver(simone_driver);
  86 +
  87 +MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
  88 +MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
  89 +MODULE_LICENSE("GPL");
  90 +MODULE_ALIAS("platform:simone-audio");
sound/soc/cirrus/snappercl15.c
  1 +/*
  2 + * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module
  3 + *
  4 + * Copyright (C) 2008 Bluewater Systems Ltd
  5 + * Author: Ryan Mallon
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify it
  8 + * under the terms of the GNU General Public License as published by the
  9 + * Free Software Foundation; either version 2 of the License, or (at your
  10 + * option) any later version.
  11 + *
  12 + */
  13 +
  14 +#include <linux/platform_device.h>
  15 +#include <linux/module.h>
  16 +#include <sound/core.h>
  17 +#include <sound/pcm.h>
  18 +#include <sound/soc.h>
  19 +
  20 +#include <asm/mach-types.h>
  21 +#include <mach/hardware.h>
  22 +
  23 +#include "../codecs/tlv320aic23.h"
  24 +#include "ep93xx-pcm.h"
  25 +
  26 +#define CODEC_CLOCK 5644800
  27 +
  28 +static int snappercl15_hw_params(struct snd_pcm_substream *substream,
  29 + struct snd_pcm_hw_params *params)
  30 +{
  31 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
  32 + struct snd_soc_dai *codec_dai = rtd->codec_dai;
  33 + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  34 + int err;
  35 +
  36 + err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK,
  37 + SND_SOC_CLOCK_IN);
  38 + if (err)
  39 + return err;
  40 +
  41 + err = snd_soc_dai_set_sysclk(cpu_dai, 0, CODEC_CLOCK,
  42 + SND_SOC_CLOCK_OUT);
  43 + if (err)
  44 + return err;
  45 +
  46 + return 0;
  47 +}
  48 +
  49 +static struct snd_soc_ops snappercl15_ops = {
  50 + .hw_params = snappercl15_hw_params,
  51 +};
  52 +
  53 +static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
  54 + SND_SOC_DAPM_HP("Headphone Jack", NULL),
  55 + SND_SOC_DAPM_LINE("Line In", NULL),
  56 + SND_SOC_DAPM_MIC("Mic Jack", NULL),
  57 +};
  58 +
  59 +static const struct snd_soc_dapm_route audio_map[] = {
  60 + {"Headphone Jack", NULL, "LHPOUT"},
  61 + {"Headphone Jack", NULL, "RHPOUT"},
  62 +
  63 + {"LLINEIN", NULL, "Line In"},
  64 + {"RLINEIN", NULL, "Line In"},
  65 +
  66 + {"MICIN", NULL, "Mic Jack"},
  67 +};
  68 +
  69 +static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
  70 +{
  71 + struct snd_soc_codec *codec = rtd->codec;
  72 + struct snd_soc_dapm_context *dapm = &codec->dapm;
  73 +
  74 + snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
  75 + ARRAY_SIZE(tlv320aic23_dapm_widgets));
  76 +
  77 + snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
  78 + return 0;
  79 +}
  80 +
  81 +static struct snd_soc_dai_link snappercl15_dai = {
  82 + .name = "tlv320aic23",
  83 + .stream_name = "AIC23",
  84 + .cpu_dai_name = "ep93xx-i2s",
  85 + .codec_dai_name = "tlv320aic23-hifi",
  86 + .codec_name = "tlv320aic23-codec.0-001a",
  87 + .platform_name = "ep93xx-pcm-audio",
  88 + .init = snappercl15_tlv320aic23_init,
  89 + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
  90 + SND_SOC_DAIFMT_CBS_CFS,
  91 + .ops = &snappercl15_ops,
  92 +};
  93 +
  94 +static struct snd_soc_card snd_soc_snappercl15 = {
  95 + .name = "Snapper CL15",
  96 + .owner = THIS_MODULE,
  97 + .dai_link = &snappercl15_dai,
  98 + .num_links = 1,
  99 +};
  100 +
  101 +static int __devinit snappercl15_probe(struct platform_device *pdev)
  102 +{
  103 + struct snd_soc_card *card = &snd_soc_snappercl15;
  104 + int ret;
  105 +
  106 + ret = ep93xx_i2s_acquire();
  107 + if (ret)
  108 + return ret;
  109 +
  110 + card->dev = &pdev->dev;
  111 +
  112 + ret = snd_soc_register_card(card);
  113 + if (ret) {
  114 + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
  115 + ret);
  116 + ep93xx_i2s_release();
  117 + }
  118 +
  119 + return ret;
  120 +}
  121 +
  122 +static int __devexit snappercl15_remove(struct platform_device *pdev)
  123 +{
  124 + struct snd_soc_card *card = platform_get_drvdata(pdev);
  125 +
  126 + snd_soc_unregister_card(card);
  127 + ep93xx_i2s_release();
  128 +
  129 + return 0;
  130 +}
  131 +
  132 +static struct platform_driver snappercl15_driver = {
  133 + .driver = {
  134 + .name = "snappercl15-audio",
  135 + .owner = THIS_MODULE,
  136 + },
  137 + .probe = snappercl15_probe,
  138 + .remove = __devexit_p(snappercl15_remove),
  139 +};
  140 +
  141 +module_platform_driver(snappercl15_driver);
  142 +
  143 +MODULE_AUTHOR("Ryan Mallon");
  144 +MODULE_DESCRIPTION("ALSA SoC Snapper CL15");
  145 +MODULE_LICENSE("GPL");
  146 +MODULE_ALIAS("platform:snappercl15-audio");
sound/soc/ep93xx/Kconfig
1   -config SND_EP93XX_SOC
2   - tristate "SoC Audio support for the Cirrus Logic EP93xx series"
3   - depends on ARCH_EP93XX && SND_SOC
4   - select SND_SOC_DMAENGINE_PCM
5   - help
6   - Say Y or M if you want to add support for codecs attached to
7   - the EP93xx I2S or AC97 interfaces.
8   -
9   -config SND_EP93XX_SOC_I2S
10   - tristate
11   -
12   -config SND_EP93XX_SOC_AC97
13   - tristate
14   - select AC97_BUS
15   - select SND_SOC_AC97_BUS
16   -
17   -config SND_EP93XX_SOC_SNAPPERCL15
18   - tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
19   - depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
20   - select SND_EP93XX_SOC_I2S
21   - select SND_SOC_TLV320AIC23
22   - help
23   - Say Y or M here if you want to add support for I2S audio on the
24   - Bluewater Systems Snapper CL15 module.
25   -
26   -config SND_EP93XX_SOC_SIMONE
27   - tristate "SoC Audio support for Simplemachines Sim.One board"
28   - depends on SND_EP93XX_SOC && MACH_SIM_ONE
29   - select SND_EP93XX_SOC_AC97
30   - select SND_SOC_AC97_CODEC
31   - help
32   - Say Y or M here if you want to add support for AC97 audio on the
33   - Simplemachines Sim.One board.
34   -
35   -config SND_EP93XX_SOC_EDB93XX
36   - tristate "SoC Audio support for Cirrus Logic EDB93xx boards"
37   - depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A)
38   - select SND_EP93XX_SOC_I2S
39   - select SND_SOC_CS4271
40   - help
41   - Say Y or M here if you want to add support for I2S audio on the
42   - Cirrus Logic EDB93xx boards.
sound/soc/ep93xx/Makefile
1   -# EP93xx Platform Support
2   -snd-soc-ep93xx-objs := ep93xx-pcm.o
3   -snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o
4   -snd-soc-ep93xx-ac97-objs := ep93xx-ac97.o
5   -
6   -obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o
7   -obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o
8   -obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o
9   -
10   -# EP93XX Machine Support
11   -snd-soc-snappercl15-objs := snappercl15.o
12   -snd-soc-simone-objs := simone.o
13   -snd-soc-edb93xx-objs := edb93xx.o
14   -
15   -obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o
16   -obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o
17   -obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o
sound/soc/ep93xx/edb93xx.c
1   -/*
2   - * SoC audio for EDB93xx
3   - *
4   - * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
5   - *
6   - * This program is free software; you can redistribute it and/or
7   - * modify it under the terms of the GNU General Public License
8   - * as published by the Free Software Foundation; either version 2
9   - * of the License, or (at your option) any later version.
10   - *
11   - * This program is distributed in the hope that it will be useful,
12   - * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14   - * GNU General Public License for more details.
15   - *
16   - * This driver support CS4271 codec being master or slave, working
17   - * in control port mode, connected either via SPI or I2C.
18   - * The data format accepted is I2S or left-justified.
19   - * DAPM support not implemented.
20   - */
21   -
22   -#include <linux/platform_device.h>
23   -#include <linux/gpio.h>
24   -#include <linux/module.h>
25   -#include <sound/core.h>
26   -#include <sound/pcm.h>
27   -#include <sound/soc.h>
28   -#include <asm/mach-types.h>
29   -#include <mach/hardware.h>
30   -#include "ep93xx-pcm.h"
31   -
32   -static int edb93xx_hw_params(struct snd_pcm_substream *substream,
33   - struct snd_pcm_hw_params *params)
34   -{
35   - struct snd_soc_pcm_runtime *rtd = substream->private_data;
36   - struct snd_soc_dai *codec_dai = rtd->codec_dai;
37   - struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
38   - int err;
39   - unsigned int mclk_rate;
40   - unsigned int rate = params_rate(params);
41   -
42   - /*
43   - * According to CS4271 datasheet we use MCLK/LRCK=256 for
44   - * rates below 50kHz and 128 for higher sample rates
45   - */
46   - if (rate < 50000)
47   - mclk_rate = rate * 64 * 4;
48   - else
49   - mclk_rate = rate * 64 * 2;
50   -
51   - err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate,
52   - SND_SOC_CLOCK_IN);
53   - if (err)
54   - return err;
55   -
56   - return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate,
57   - SND_SOC_CLOCK_OUT);
58   -}
59   -
60   -static struct snd_soc_ops edb93xx_ops = {
61   - .hw_params = edb93xx_hw_params,
62   -};
63   -
64   -static struct snd_soc_dai_link edb93xx_dai = {
65   - .name = "CS4271",
66   - .stream_name = "CS4271 HiFi",
67   - .platform_name = "ep93xx-pcm-audio",
68   - .cpu_dai_name = "ep93xx-i2s",
69   - .codec_name = "spi0.0",
70   - .codec_dai_name = "cs4271-hifi",
71   - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
72   - SND_SOC_DAIFMT_CBS_CFS,
73   - .ops = &edb93xx_ops,
74   -};
75   -
76   -static struct snd_soc_card snd_soc_edb93xx = {
77   - .name = "EDB93XX",
78   - .owner = THIS_MODULE,
79   - .dai_link = &edb93xx_dai,
80   - .num_links = 1,
81   -};
82   -
83   -static int __devinit edb93xx_probe(struct platform_device *pdev)
84   -{
85   - struct snd_soc_card *card = &snd_soc_edb93xx;
86   - int ret;
87   -
88   - ret = ep93xx_i2s_acquire();
89   - if (ret)
90   - return ret;
91   -
92   - card->dev = &pdev->dev;
93   -
94   - ret = snd_soc_register_card(card);
95   - if (ret) {
96   - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
97   - ret);
98   - ep93xx_i2s_release();
99   - }
100   -
101   - return ret;
102   -}
103   -
104   -static int __devexit edb93xx_remove(struct platform_device *pdev)
105   -{
106   - struct snd_soc_card *card = platform_get_drvdata(pdev);
107   -
108   - snd_soc_unregister_card(card);
109   - ep93xx_i2s_release();
110   -
111   - return 0;
112   -}
113   -
114   -static struct platform_driver edb93xx_driver = {
115   - .driver = {
116   - .name = "edb93xx-audio",
117   - .owner = THIS_MODULE,
118   - },
119   - .probe = edb93xx_probe,
120   - .remove = __devexit_p(edb93xx_remove),
121   -};
122   -
123   -module_platform_driver(edb93xx_driver);
124   -
125   -MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
126   -MODULE_DESCRIPTION("ALSA SoC EDB93xx");
127   -MODULE_LICENSE("GPL");
128   -MODULE_ALIAS("platform:edb93xx-audio");
sound/soc/ep93xx/ep93xx-ac97.c
1   -/*
2   - * ASoC driver for Cirrus Logic EP93xx AC97 controller.
3   - *
4   - * Copyright (c) 2010 Mika Westerberg
5   - *
6   - * Based on s3c-ac97 ASoC driver by Jaswinder Singh.
7   - *
8   - * This program is free software; you can redistribute it and/or modify
9   - * it under the terms of the GNU General Public License version 2 as
10   - * published by the Free Software Foundation.
11   - */
12   -
13   -#include <linux/delay.h>
14   -#include <linux/io.h>
15   -#include <linux/init.h>
16   -#include <linux/module.h>
17   -#include <linux/platform_device.h>
18   -#include <linux/slab.h>
19   -
20   -#include <sound/core.h>
21   -#include <sound/ac97_codec.h>
22   -#include <sound/soc.h>
23   -
24   -#include <mach/dma.h>
25   -#include "ep93xx-pcm.h"
26   -
27   -/*
28   - * Per channel (1-4) registers.
29   - */
30   -#define AC97CH(n) (((n) - 1) * 0x20)
31   -
32   -#define AC97DR(n) (AC97CH(n) + 0x0000)
33   -
34   -#define AC97RXCR(n) (AC97CH(n) + 0x0004)
35   -#define AC97RXCR_REN BIT(0)
36   -#define AC97RXCR_RX3 BIT(3)
37   -#define AC97RXCR_RX4 BIT(4)
38   -#define AC97RXCR_CM BIT(15)
39   -
40   -#define AC97TXCR(n) (AC97CH(n) + 0x0008)
41   -#define AC97TXCR_TEN BIT(0)
42   -#define AC97TXCR_TX3 BIT(3)
43   -#define AC97TXCR_TX4 BIT(4)
44   -#define AC97TXCR_CM BIT(15)
45   -
46   -#define AC97SR(n) (AC97CH(n) + 0x000c)
47   -#define AC97SR_TXFE BIT(1)
48   -#define AC97SR_TXUE BIT(6)
49   -
50   -#define AC97RISR(n) (AC97CH(n) + 0x0010)
51   -#define AC97ISR(n) (AC97CH(n) + 0x0014)
52   -#define AC97IE(n) (AC97CH(n) + 0x0018)
53   -
54   -/*
55   - * Global AC97 controller registers.
56   - */
57   -#define AC97S1DATA 0x0080
58   -#define AC97S2DATA 0x0084
59   -#define AC97S12DATA 0x0088
60   -
61   -#define AC97RGIS 0x008c
62   -#define AC97GIS 0x0090
63   -#define AC97IM 0x0094
64   -/*
65   - * Common bits for RGIS, GIS and IM registers.
66   - */
67   -#define AC97_SLOT2RXVALID BIT(1)
68   -#define AC97_CODECREADY BIT(5)
69   -#define AC97_SLOT2TXCOMPLETE BIT(6)
70   -
71   -#define AC97EOI 0x0098
72   -#define AC97EOI_WINT BIT(0)
73   -#define AC97EOI_CODECREADY BIT(1)
74   -
75   -#define AC97GCR 0x009c
76   -#define AC97GCR_AC97IFE BIT(0)
77   -
78   -#define AC97RESET 0x00a0
79   -#define AC97RESET_TIMEDRESET BIT(0)
80   -
81   -#define AC97SYNC 0x00a4
82   -#define AC97SYNC_TIMEDSYNC BIT(0)
83   -
84   -#define AC97_TIMEOUT msecs_to_jiffies(5)
85   -
86   -/**
87   - * struct ep93xx_ac97_info - EP93xx AC97 controller info structure
88   - * @lock: mutex serializing access to the bus (slot 1 & 2 ops)
89   - * @dev: pointer to the platform device dev structure
90   - * @regs: mapped AC97 controller registers
91   - * @done: bus ops wait here for an interrupt
92   - */
93   -struct ep93xx_ac97_info {
94   - struct mutex lock;
95   - struct device *dev;
96   - void __iomem *regs;
97   - struct completion done;
98   -};
99   -
100   -/* currently ALSA only supports a single AC97 device */
101   -static struct ep93xx_ac97_info *ep93xx_ac97_info;
102   -
103   -static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
104   - .name = "ac97-pcm-out",
105   - .dma_port = EP93XX_DMA_AAC1,
106   -};
107   -
108   -static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
109   - .name = "ac97-pcm-in",
110   - .dma_port = EP93XX_DMA_AAC1,
111   -};
112   -
113   -static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
114   - unsigned reg)
115   -{
116   - return __raw_readl(info->regs + reg);
117   -}
118   -
119   -static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info,
120   - unsigned reg, unsigned val)
121   -{
122   - __raw_writel(val, info->regs + reg);
123   -}
124   -
125   -static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97,
126   - unsigned short reg)
127   -{
128   - struct ep93xx_ac97_info *info = ep93xx_ac97_info;
129   - unsigned short val;
130   -
131   - mutex_lock(&info->lock);
132   -
133   - ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
134   - ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID);
135   - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) {
136   - dev_warn(info->dev, "timeout reading register %x\n", reg);
137   - mutex_unlock(&info->lock);
138   - return -ETIMEDOUT;
139   - }
140   - val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA);
141   -
142   - mutex_unlock(&info->lock);
143   - return val;
144   -}
145   -
146   -static void ep93xx_ac97_write(struct snd_ac97 *ac97,
147   - unsigned short reg,
148   - unsigned short val)
149   -{
150   - struct ep93xx_ac97_info *info = ep93xx_ac97_info;
151   -
152   - mutex_lock(&info->lock);
153   -
154   - /*
155   - * Writes to the codec need to be done so that slot 2 is filled in
156   - * before slot 1.
157   - */
158   - ep93xx_ac97_write_reg(info, AC97S2DATA, val);
159   - ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
160   -
161   - ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE);
162   - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
163   - dev_warn(info->dev, "timeout writing register %x\n", reg);
164   -
165   - mutex_unlock(&info->lock);
166   -}
167   -
168   -static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97)
169   -{
170   - struct ep93xx_ac97_info *info = ep93xx_ac97_info;
171   -
172   - mutex_lock(&info->lock);
173   -
174   - /*
175   - * We are assuming that before this functions gets called, the codec
176   - * BIT_CLK is stopped by forcing the codec into powerdown mode. We can
177   - * control the SYNC signal directly via AC97SYNC register. Using
178   - * TIMEDSYNC the controller will keep the SYNC high > 1us.
179   - */
180   - ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC);
181   - ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
182   - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
183   - dev_warn(info->dev, "codec warm reset timeout\n");
184   -
185   - mutex_unlock(&info->lock);
186   -}
187   -
188   -static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97)
189   -{
190   - struct ep93xx_ac97_info *info = ep93xx_ac97_info;
191   -
192   - mutex_lock(&info->lock);
193   -
194   - /*
195   - * For doing cold reset, we disable the AC97 controller interface, clear
196   - * WINT and CODECREADY bits, and finally enable the interface again.
197   - */
198   - ep93xx_ac97_write_reg(info, AC97GCR, 0);
199   - ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT);
200   - ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE);
201   -
202   - /*
203   - * Now, assert the reset and wait for the codec to become ready.
204   - */
205   - ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET);
206   - ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
207   - if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
208   - dev_warn(info->dev, "codec cold reset timeout\n");
209   -
210   - /*
211   - * Give the codec some time to come fully out from the reset. This way
212   - * we ensure that the subsequent reads/writes will work.
213   - */
214   - usleep_range(15000, 20000);
215   -
216   - mutex_unlock(&info->lock);
217   -}
218   -
219   -static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id)
220   -{
221   - struct ep93xx_ac97_info *info = dev_id;
222   - unsigned status, mask;
223   -
224   - /*
225   - * Just mask out the interrupt and wake up the waiting thread.
226   - * Interrupts are cleared via reading/writing to slot 1 & 2 registers by
227   - * the waiting thread.
228   - */
229   - status = ep93xx_ac97_read_reg(info, AC97GIS);
230   - mask = ep93xx_ac97_read_reg(info, AC97IM);
231   - mask &= ~status;
232   - ep93xx_ac97_write_reg(info, AC97IM, mask);
233   -
234   - complete(&info->done);
235   - return IRQ_HANDLED;
236   -}
237   -
238   -struct snd_ac97_bus_ops soc_ac97_ops = {
239   - .read = ep93xx_ac97_read,
240   - .write = ep93xx_ac97_write,
241   - .reset = ep93xx_ac97_cold_reset,
242   - .warm_reset = ep93xx_ac97_warm_reset,
243   -};
244   -EXPORT_SYMBOL_GPL(soc_ac97_ops);
245   -
246   -static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
247   - int cmd, struct snd_soc_dai *dai)
248   -{
249   - struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai);
250   - unsigned v = 0;
251   -
252   - switch (cmd) {
253   - case SNDRV_PCM_TRIGGER_START:
254   - case SNDRV_PCM_TRIGGER_RESUME:
255   - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
256   - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
257   - /*
258   - * Enable compact mode, TX slots 3 & 4, and the TX FIFO
259   - * itself.
260   - */
261   - v |= AC97TXCR_CM;
262   - v |= AC97TXCR_TX3 | AC97TXCR_TX4;
263   - v |= AC97TXCR_TEN;
264   - ep93xx_ac97_write_reg(info, AC97TXCR(1), v);
265   - } else {
266   - /*
267   - * Enable compact mode, RX slots 3 & 4, and the RX FIFO
268   - * itself.
269   - */
270   - v |= AC97RXCR_CM;
271   - v |= AC97RXCR_RX3 | AC97RXCR_RX4;
272   - v |= AC97RXCR_REN;
273   - ep93xx_ac97_write_reg(info, AC97RXCR(1), v);
274   - }
275   - break;
276   -
277   - case SNDRV_PCM_TRIGGER_STOP:
278   - case SNDRV_PCM_TRIGGER_SUSPEND:
279   - case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
280   - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
281   - /*
282   - * As per Cirrus EP93xx errata described below:
283   - *
284   - * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf
285   - *
286   - * we will wait for the TX FIFO to be empty before
287   - * clearing the TEN bit.
288   - */
289   - unsigned long timeout = jiffies + AC97_TIMEOUT;
290   -
291   - do {
292   - v = ep93xx_ac97_read_reg(info, AC97SR(1));
293   - if (time_after(jiffies, timeout)) {
294   - dev_warn(info->dev, "TX timeout\n");
295   - break;
296   - }
297   - } while (!(v & (AC97SR_TXFE | AC97SR_TXUE)));
298   -
299   - /* disable the TX FIFO */
300   - ep93xx_ac97_write_reg(info, AC97TXCR(1), 0);
301   - } else {
302   - /* disable the RX FIFO */
303   - ep93xx_ac97_write_reg(info, AC97RXCR(1), 0);
304   - }
305   - break;
306   -
307   - default:
308   - dev_warn(info->dev, "unknown command %d\n", cmd);
309   - return -EINVAL;
310   - }
311   -
312   - return 0;
313   -}
314   -
315   -static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
316   - struct snd_soc_dai *dai)
317   -{
318   - struct ep93xx_pcm_dma_params *dma_data;
319   -
320   - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
321   - dma_data = &ep93xx_ac97_pcm_out;
322   - else
323   - dma_data = &ep93xx_ac97_pcm_in;
324   -
325   - snd_soc_dai_set_dma_data(dai, substream, dma_data);
326   - return 0;
327   -}
328   -
329   -static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
330   - .startup = ep93xx_ac97_startup,
331   - .trigger = ep93xx_ac97_trigger,
332   -};
333   -
334   -static struct snd_soc_dai_driver ep93xx_ac97_dai = {
335   - .name = "ep93xx-ac97",
336   - .id = 0,
337   - .ac97_control = 1,
338   - .playback = {
339   - .stream_name = "AC97 Playback",
340   - .channels_min = 2,
341   - .channels_max = 2,
342   - .rates = SNDRV_PCM_RATE_8000_48000,
343   - .formats = SNDRV_PCM_FMTBIT_S16_LE,
344   - },
345   - .capture = {
346   - .stream_name = "AC97 Capture",
347   - .channels_min = 2,
348   - .channels_max = 2,
349   - .rates = SNDRV_PCM_RATE_8000_48000,
350   - .formats = SNDRV_PCM_FMTBIT_S16_LE,
351   - },
352   - .ops = &ep93xx_ac97_dai_ops,
353   -};
354   -
355   -static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
356   -{
357   - struct ep93xx_ac97_info *info;
358   - struct resource *res;
359   - unsigned int irq;
360   - int ret;
361   -
362   - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
363   - if (!info)
364   - return -ENOMEM;
365   -
366   - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
367   - if (!res)
368   - return -ENODEV;
369   -
370   - info->regs = devm_request_and_ioremap(&pdev->dev, res);
371   - if (!info->regs)
372   - return -ENXIO;
373   -
374   - irq = platform_get_irq(pdev, 0);
375   - if (!irq)
376   - return -ENODEV;
377   -
378   - ret = devm_request_irq(&pdev->dev, irq, ep93xx_ac97_interrupt,
379   - IRQF_TRIGGER_HIGH, pdev->name, info);
380   - if (ret)
381   - goto fail;
382   -
383   - dev_set_drvdata(&pdev->dev, info);
384   -
385   - mutex_init(&info->lock);
386   - init_completion(&info->done);
387   - info->dev = &pdev->dev;
388   -
389   - ep93xx_ac97_info = info;
390   - platform_set_drvdata(pdev, info);
391   -
392   - ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
393   - if (ret)
394   - goto fail;
395   -
396   - return 0;
397   -
398   -fail:
399   - platform_set_drvdata(pdev, NULL);
400   - ep93xx_ac97_info = NULL;
401   - dev_set_drvdata(&pdev->dev, NULL);
402   - return ret;
403   -}
404   -
405   -static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
406   -{
407   - struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
408   -
409   - snd_soc_unregister_dai(&pdev->dev);
410   -
411   - /* disable the AC97 controller */
412   - ep93xx_ac97_write_reg(info, AC97GCR, 0);
413   -
414   - platform_set_drvdata(pdev, NULL);
415   - ep93xx_ac97_info = NULL;
416   - dev_set_drvdata(&pdev->dev, NULL);
417   -
418   - return 0;
419   -}
420   -
421   -static struct platform_driver ep93xx_ac97_driver = {
422   - .probe = ep93xx_ac97_probe,
423   - .remove = __devexit_p(ep93xx_ac97_remove),
424   - .driver = {
425   - .name = "ep93xx-ac97",
426   - .owner = THIS_MODULE,
427   - },
428   -};
429   -
430   -module_platform_driver(ep93xx_ac97_driver);
431   -
432   -MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
433   -MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
434   -MODULE_LICENSE("GPL");
435   -MODULE_ALIAS("platform:ep93xx-ac97");
sound/soc/ep93xx/ep93xx-i2s.c
1   -/*
2   - * linux/sound/soc/ep93xx-i2s.c
3   - * EP93xx I2S driver
4   - *
5   - * Copyright (C) 2010 Ryan Mallon
6   - *
7   - * Based on the original driver by:
8   - * Copyright (C) 2007 Chase Douglas <chasedouglas@gmail>
9   - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
10   - *
11   - * This program is free software; you can redistribute it and/or modify
12   - * it under the terms of the GNU General Public License version 2 as
13   - * published by the Free Software Foundation.
14   - *
15   - */
16   -
17   -#include <linux/module.h>
18   -#include <linux/init.h>
19   -#include <linux/slab.h>
20   -#include <linux/clk.h>
21   -#include <linux/io.h>
22   -
23   -#include <sound/core.h>
24   -#include <sound/pcm.h>
25   -#include <sound/pcm_params.h>
26   -#include <sound/initval.h>
27   -#include <sound/soc.h>
28   -
29   -#include <mach/hardware.h>
30   -#include <mach/ep93xx-regs.h>
31   -#include <mach/dma.h>
32   -
33   -#include "ep93xx-pcm.h"
34   -
35   -#define EP93XX_I2S_TXCLKCFG 0x00
36   -#define EP93XX_I2S_RXCLKCFG 0x04
37   -#define EP93XX_I2S_GLCTRL 0x0C
38   -
39   -#define EP93XX_I2S_TXLINCTRLDATA 0x28
40   -#define EP93XX_I2S_TXCTRL 0x2C
41   -#define EP93XX_I2S_TXWRDLEN 0x30
42   -#define EP93XX_I2S_TX0EN 0x34
43   -
44   -#define EP93XX_I2S_RXLINCTRLDATA 0x58
45   -#define EP93XX_I2S_RXCTRL 0x5C
46   -#define EP93XX_I2S_RXWRDLEN 0x60
47   -#define EP93XX_I2S_RX0EN 0x64
48   -
49   -#define EP93XX_I2S_WRDLEN_16 (0 << 0)
50   -#define EP93XX_I2S_WRDLEN_24 (1 << 0)
51   -#define EP93XX_I2S_WRDLEN_32 (2 << 0)
52   -
53   -#define EP93XX_I2S_LINCTRLDATA_R_JUST (1 << 2) /* Right justify */
54   -
55   -#define EP93XX_I2S_CLKCFG_LRS (1 << 0) /* lrclk polarity */
56   -#define EP93XX_I2S_CLKCFG_CKP (1 << 1) /* Bit clock polarity */
57   -#define EP93XX_I2S_CLKCFG_REL (1 << 2) /* First bit transition */
58   -#define EP93XX_I2S_CLKCFG_MASTER (1 << 3) /* Master mode */
59   -#define EP93XX_I2S_CLKCFG_NBCG (1 << 4) /* Not bit clock gating */
60   -
61   -struct ep93xx_i2s_info {
62   - struct clk *mclk;
63   - struct clk *sclk;
64   - struct clk *lrclk;
65   - struct ep93xx_pcm_dma_params *dma_params;
66   - void __iomem *regs;
67   -};
68   -
69   -struct ep93xx_pcm_dma_params ep93xx_i2s_dma_params[] = {
70   - [SNDRV_PCM_STREAM_PLAYBACK] = {
71   - .name = "i2s-pcm-out",
72   - .dma_port = EP93XX_DMA_I2S1,
73   - },
74   - [SNDRV_PCM_STREAM_CAPTURE] = {
75   - .name = "i2s-pcm-in",
76   - .dma_port = EP93XX_DMA_I2S1,
77   - },
78   -};
79   -
80   -static inline void ep93xx_i2s_write_reg(struct ep93xx_i2s_info *info,
81   - unsigned reg, unsigned val)
82   -{
83   - __raw_writel(val, info->regs + reg);
84   -}
85   -
86   -static inline unsigned ep93xx_i2s_read_reg(struct ep93xx_i2s_info *info,
87   - unsigned reg)
88   -{
89   - return __raw_readl(info->regs + reg);
90   -}
91   -
92   -static void ep93xx_i2s_enable(struct ep93xx_i2s_info *info, int stream)
93   -{
94   - unsigned base_reg;
95   - int i;
96   -
97   - if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
98   - (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
99   - /* Enable clocks */
100   - clk_enable(info->mclk);
101   - clk_enable(info->sclk);
102   - clk_enable(info->lrclk);
103   -
104   - /* Enable i2s */
105   - ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 1);
106   - }
107   -
108   - /* Enable fifos */
109   - if (stream == SNDRV_PCM_STREAM_PLAYBACK)
110   - base_reg = EP93XX_I2S_TX0EN;
111   - else
112   - base_reg = EP93XX_I2S_RX0EN;
113   - for (i = 0; i < 3; i++)
114   - ep93xx_i2s_write_reg(info, base_reg + (i * 4), 1);
115   -}
116   -
117   -static void ep93xx_i2s_disable(struct ep93xx_i2s_info *info, int stream)
118   -{
119   - unsigned base_reg;
120   - int i;
121   -
122   - /* Disable fifos */
123   - if (stream == SNDRV_PCM_STREAM_PLAYBACK)
124   - base_reg = EP93XX_I2S_TX0EN;
125   - else
126   - base_reg = EP93XX_I2S_RX0EN;
127   - for (i = 0; i < 3; i++)
128   - ep93xx_i2s_write_reg(info, base_reg + (i * 4), 0);
129   -
130   - if ((ep93xx_i2s_read_reg(info, EP93XX_I2S_TX0EN) & 0x1) == 0 &&
131   - (ep93xx_i2s_read_reg(info, EP93XX_I2S_RX0EN) & 0x1) == 0) {
132   - /* Disable i2s */
133   - ep93xx_i2s_write_reg(info, EP93XX_I2S_GLCTRL, 0);
134   -
135   - /* Disable clocks */
136   - clk_disable(info->lrclk);
137   - clk_disable(info->sclk);
138   - clk_disable(info->mclk);
139   - }
140   -}
141   -
142   -static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
143   - struct snd_soc_dai *dai)
144   -{
145   - struct snd_soc_pcm_runtime *rtd = substream->private_data;
146   - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
147   - struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
148   -
149   - snd_soc_dai_set_dma_data(cpu_dai, substream,
150   - &info->dma_params[substream->stream]);
151   - return 0;
152   -}
153   -
154   -static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
155   - struct snd_soc_dai *dai)
156   -{
157   - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
158   -
159   - ep93xx_i2s_disable(info, substream->stream);
160   -}
161   -
162   -static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
163   - unsigned int fmt)
164   -{
165   - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
166   - unsigned int clk_cfg, lin_ctrl;
167   -
168   - clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
169   - lin_ctrl = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXLINCTRLDATA);
170   -
171   - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
172   - case SND_SOC_DAIFMT_I2S:
173   - clk_cfg |= EP93XX_I2S_CLKCFG_REL;
174   - lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
175   - break;
176   -
177   - case SND_SOC_DAIFMT_LEFT_J:
178   - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
179   - lin_ctrl &= ~EP93XX_I2S_LINCTRLDATA_R_JUST;
180   - break;
181   -
182   - case SND_SOC_DAIFMT_RIGHT_J:
183   - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
184   - lin_ctrl |= EP93XX_I2S_LINCTRLDATA_R_JUST;
185   - break;
186   -
187   - default:
188   - return -EINVAL;
189   - }
190   -
191   - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
192   - case SND_SOC_DAIFMT_CBS_CFS:
193   - /* CPU is master */
194   - clk_cfg |= EP93XX_I2S_CLKCFG_MASTER;
195   - break;
196   -
197   - case SND_SOC_DAIFMT_CBM_CFM:
198   - /* Codec is master */
199   - clk_cfg &= ~EP93XX_I2S_CLKCFG_MASTER;
200   - break;
201   -
202   - default:
203   - return -EINVAL;
204   - }
205   -
206   - switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
207   - case SND_SOC_DAIFMT_NB_NF:
208   - /* Negative bit clock, lrclk low on left word */
209   - clk_cfg &= ~(EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL);
210   - break;
211   -
212   - case SND_SOC_DAIFMT_NB_IF:
213   - /* Negative bit clock, lrclk low on right word */
214   - clk_cfg &= ~EP93XX_I2S_CLKCFG_CKP;
215   - clk_cfg |= EP93XX_I2S_CLKCFG_REL;
216   - break;
217   -
218   - case SND_SOC_DAIFMT_IB_NF:
219   - /* Positive bit clock, lrclk low on left word */
220   - clk_cfg |= EP93XX_I2S_CLKCFG_CKP;
221   - clk_cfg &= ~EP93XX_I2S_CLKCFG_REL;
222   - break;
223   -
224   - case SND_SOC_DAIFMT_IB_IF:
225   - /* Positive bit clock, lrclk low on right word */
226   - clk_cfg |= EP93XX_I2S_CLKCFG_CKP | EP93XX_I2S_CLKCFG_REL;
227   - break;
228   - }
229   -
230   - /* Write new register values */
231   - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXCLKCFG, clk_cfg);
232   - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXCLKCFG, clk_cfg);
233   - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXLINCTRLDATA, lin_ctrl);
234   - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXLINCTRLDATA, lin_ctrl);
235   - return 0;
236   -}
237   -
238   -static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
239   - struct snd_pcm_hw_params *params,
240   - struct snd_soc_dai *dai)
241   -{
242   - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
243   - unsigned word_len, div, sdiv, lrdiv;
244   - int err;
245   -
246   - switch (params_format(params)) {
247   - case SNDRV_PCM_FORMAT_S16_LE:
248   - word_len = EP93XX_I2S_WRDLEN_16;
249   - break;
250   -
251   - case SNDRV_PCM_FORMAT_S24_LE:
252   - word_len = EP93XX_I2S_WRDLEN_24;
253   - break;
254   -
255   - case SNDRV_PCM_FORMAT_S32_LE:
256   - word_len = EP93XX_I2S_WRDLEN_32;
257   - break;
258   -
259   - default:
260   - return -EINVAL;
261   - }
262   -
263   - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
264   - ep93xx_i2s_write_reg(info, EP93XX_I2S_TXWRDLEN, word_len);
265   - else
266   - ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len);
267   -
268   - /*
269   - * EP93xx I2S module can be setup so SCLK / LRCLK value can be
270   - * 32, 64, 128. MCLK / SCLK value can be 2 and 4.
271   - * We set LRCLK equal to `rate' and minimum SCLK / LRCLK
272   - * value is 64, because our sample size is 32 bit * 2 channels.
273   - * I2S standard permits us to transmit more bits than
274   - * the codec uses.
275   - */
276   - div = clk_get_rate(info->mclk) / params_rate(params);
277   - sdiv = 4;
278   - if (div > (256 + 512) / 2) {
279   - lrdiv = 128;
280   - } else {
281   - lrdiv = 64;
282   - if (div < (128 + 256) / 2)
283   - sdiv = 2;
284   - }
285   -
286   - err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
287   - if (err)
288   - return err;
289   -
290   - err = clk_set_rate(info->lrclk, clk_get_rate(info->sclk) / lrdiv);
291   - if (err)
292   - return err;
293   -
294   - ep93xx_i2s_enable(info, substream->stream);
295   - return 0;
296   -}
297   -
298   -static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
299   - unsigned int freq, int dir)
300   -{
301   - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
302   -
303   - if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
304   - return -EINVAL;
305   -
306   - return clk_set_rate(info->mclk, freq);
307   -}
308   -
309   -#ifdef CONFIG_PM
310   -static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
311   -{
312   - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
313   -
314   - if (!dai->active)
315   - return 0;
316   -
317   - ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
318   - ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
319   -
320   - return 0;
321   -}
322   -
323   -static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
324   -{
325   - struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
326   -
327   - if (!dai->active)
328   - return 0;
329   -
330   - ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
331   - ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
332   -
333   - return 0;
334   -}
335   -#else
336   -#define ep93xx_i2s_suspend NULL
337   -#define ep93xx_i2s_resume NULL
338   -#endif
339   -
340   -static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
341   - .startup = ep93xx_i2s_startup,
342   - .shutdown = ep93xx_i2s_shutdown,
343   - .hw_params = ep93xx_i2s_hw_params,
344   - .set_sysclk = ep93xx_i2s_set_sysclk,
345   - .set_fmt = ep93xx_i2s_set_dai_fmt,
346   -};
347   -
348   -#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
349   -
350   -static struct snd_soc_dai_driver ep93xx_i2s_dai = {
351   - .symmetric_rates= 1,
352   - .suspend = ep93xx_i2s_suspend,
353   - .resume = ep93xx_i2s_resume,
354   - .playback = {
355   - .channels_min = 2,
356   - .channels_max = 2,
357   - .rates = SNDRV_PCM_RATE_8000_192000,
358   - .formats = EP93XX_I2S_FORMATS,
359   - },
360   - .capture = {
361   - .channels_min = 2,
362   - .channels_max = 2,
363   - .rates = SNDRV_PCM_RATE_8000_192000,
364   - .formats = EP93XX_I2S_FORMATS,
365   - },
366   - .ops = &ep93xx_i2s_dai_ops,
367   -};
368   -
369   -static int ep93xx_i2s_probe(struct platform_device *pdev)
370   -{
371   - struct ep93xx_i2s_info *info;
372   - struct resource *res;
373   - int err;
374   -
375   - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
376   - if (!info)
377   - return -ENOMEM;
378   -
379   - res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
380   - if (!res)
381   - return -ENODEV;
382   -
383   - info->regs = devm_request_and_ioremap(&pdev->dev, res);
384   - if (!info->regs)
385   - return -ENXIO;
386   -
387   - info->mclk = clk_get(&pdev->dev, "mclk");
388   - if (IS_ERR(info->mclk)) {
389   - err = PTR_ERR(info->mclk);
390   - goto fail;
391   - }
392   -
393   - info->sclk = clk_get(&pdev->dev, "sclk");
394   - if (IS_ERR(info->sclk)) {
395   - err = PTR_ERR(info->sclk);
396   - goto fail_put_mclk;
397   - }
398   -
399   - info->lrclk = clk_get(&pdev->dev, "lrclk");
400   - if (IS_ERR(info->lrclk)) {
401   - err = PTR_ERR(info->lrclk);
402   - goto fail_put_sclk;
403   - }
404   -
405   - dev_set_drvdata(&pdev->dev, info);
406   - info->dma_params = ep93xx_i2s_dma_params;
407   -
408   - err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
409   - if (err)
410   - goto fail_put_lrclk;
411   -
412   - return 0;
413   -
414   -fail_put_lrclk:
415   - dev_set_drvdata(&pdev->dev, NULL);
416   - clk_put(info->lrclk);
417   -fail_put_sclk:
418   - clk_put(info->sclk);
419   -fail_put_mclk:
420   - clk_put(info->mclk);
421   -fail:
422   - return err;
423   -}
424   -
425   -static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
426   -{
427   - struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
428   -
429   - snd_soc_unregister_dai(&pdev->dev);
430   - dev_set_drvdata(&pdev->dev, NULL);
431   - clk_put(info->lrclk);
432   - clk_put(info->sclk);
433   - clk_put(info->mclk);
434   - return 0;
435   -}
436   -
437   -static struct platform_driver ep93xx_i2s_driver = {
438   - .probe = ep93xx_i2s_probe,
439   - .remove = __devexit_p(ep93xx_i2s_remove),
440   - .driver = {
441   - .name = "ep93xx-i2s",
442   - .owner = THIS_MODULE,
443   - },
444   -};
445   -
446   -module_platform_driver(ep93xx_i2s_driver);
447   -
448   -MODULE_ALIAS("platform:ep93xx-i2s");
449   -MODULE_AUTHOR("Ryan Mallon");
450   -MODULE_DESCRIPTION("EP93XX I2S driver");
451   -MODULE_LICENSE("GPL");
sound/soc/ep93xx/ep93xx-pcm.c
1   -/*
2   - * linux/sound/arm/ep93xx-pcm.c - EP93xx ALSA PCM interface
3   - *
4   - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
5   - * Copyright (C) 2006 Applied Data Systems
6   - *
7   - * Rewritten for the SoC audio subsystem (Based on PXA2xx code):
8   - * Copyright (c) 2008 Ryan Mallon
9   - *
10   - * This program is free software; you can redistribute it and/or modify
11   - * it under the terms of the GNU General Public License version 2 as
12   - * published by the Free Software Foundation.
13   - */
14   -
15   -#include <linux/module.h>
16   -#include <linux/init.h>
17   -#include <linux/device.h>
18   -#include <linux/slab.h>
19   -#include <linux/dmaengine.h>
20   -#include <linux/dma-mapping.h>
21   -
22   -#include <sound/core.h>
23   -#include <sound/pcm.h>
24   -#include <sound/pcm_params.h>
25   -#include <sound/soc.h>
26   -#include <sound/dmaengine_pcm.h>
27   -
28   -#include <mach/dma.h>
29   -#include <mach/hardware.h>
30   -#include <mach/ep93xx-regs.h>
31   -
32   -#include "ep93xx-pcm.h"
33   -
34   -static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
35   - .info = (SNDRV_PCM_INFO_MMAP |
36   - SNDRV_PCM_INFO_MMAP_VALID |
37   - SNDRV_PCM_INFO_INTERLEAVED |
38   - SNDRV_PCM_INFO_BLOCK_TRANSFER),
39   -
40   - .rates = SNDRV_PCM_RATE_8000_192000,
41   - .rate_min = SNDRV_PCM_RATE_8000,
42   - .rate_max = SNDRV_PCM_RATE_192000,
43   -
44   - .formats = (SNDRV_PCM_FMTBIT_S16_LE |
45   - SNDRV_PCM_FMTBIT_S24_LE |
46   - SNDRV_PCM_FMTBIT_S32_LE),
47   -
48   - .buffer_bytes_max = 131072,
49   - .period_bytes_min = 32,
50   - .period_bytes_max = 32768,
51   - .periods_min = 1,
52   - .periods_max = 32,
53   - .fifo_size = 32,
54   -};
55   -
56   -static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
57   -{
58   - struct ep93xx_dma_data *data = filter_param;
59   -
60   - if (data->direction == ep93xx_dma_chan_direction(chan)) {
61   - chan->private = data;
62   - return true;
63   - }
64   -
65   - return false;
66   -}
67   -
68   -static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
69   -{
70   - struct snd_soc_pcm_runtime *rtd = substream->private_data;
71   - struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
72   - struct ep93xx_pcm_dma_params *dma_params;
73   - struct ep93xx_dma_data *dma_data;
74   - int ret;
75   -
76   - snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
77   -
78   - dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
79   - if (!dma_data)
80   - return -ENOMEM;
81   -
82   - dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
83   - dma_data->port = dma_params->dma_port;
84   - dma_data->name = dma_params->name;
85   - dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
86   -
87   - ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
88   - if (ret) {
89   - kfree(dma_data);
90   - return ret;
91   - }
92   -
93   - snd_dmaengine_pcm_set_data(substream, dma_data);
94   -
95   - return 0;
96   -}
97   -
98   -static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
99   -{
100   - struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
101   -
102   - snd_dmaengine_pcm_close(substream);
103   - kfree(dma_data);
104   - return 0;
105   -}
106   -
107   -static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
108   - struct snd_pcm_hw_params *params)
109   -{
110   - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
111   -
112   - return 0;
113   -}
114   -
115   -static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
116   -{
117   - snd_pcm_set_runtime_buffer(substream, NULL);
118   - return 0;
119   -}
120   -
121   -static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
122   - struct vm_area_struct *vma)
123   -{
124   - struct snd_pcm_runtime *runtime = substream->runtime;
125   -
126   - return dma_mmap_writecombine(substream->pcm->card->dev, vma,
127   - runtime->dma_area,
128   - runtime->dma_addr,
129   - runtime->dma_bytes);
130   -}
131   -
132   -static struct snd_pcm_ops ep93xx_pcm_ops = {
133   - .open = ep93xx_pcm_open,
134   - .close = ep93xx_pcm_close,
135   - .ioctl = snd_pcm_lib_ioctl,
136   - .hw_params = ep93xx_pcm_hw_params,
137   - .hw_free = ep93xx_pcm_hw_free,
138   - .trigger = snd_dmaengine_pcm_trigger,
139   - .pointer = snd_dmaengine_pcm_pointer_no_residue,
140   - .mmap = ep93xx_pcm_mmap,
141   -};
142   -
143   -static int ep93xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
144   -{
145   - struct snd_pcm_substream *substream = pcm->streams[stream].substream;
146   - struct snd_dma_buffer *buf = &substream->dma_buffer;
147   - size_t size = ep93xx_pcm_hardware.buffer_bytes_max;
148   -
149   - buf->dev.type = SNDRV_DMA_TYPE_DEV;
150   - buf->dev.dev = pcm->card->dev;
151   - buf->private_data = NULL;
152   - buf->area = dma_alloc_writecombine(pcm->card->dev, size,
153   - &buf->addr, GFP_KERNEL);
154   - buf->bytes = size;
155   -
156   - return (buf->area == NULL) ? -ENOMEM : 0;
157   -}
158   -
159   -static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
160   -{
161   - struct snd_pcm_substream *substream;
162   - struct snd_dma_buffer *buf;
163   - int stream;
164   -
165   - for (stream = 0; stream < 2; stream++) {
166   - substream = pcm->streams[stream].substream;
167   - if (!substream)
168   - continue;
169   -
170   - buf = &substream->dma_buffer;
171   - if (!buf->area)
172   - continue;
173   -
174   - dma_free_writecombine(pcm->card->dev, buf->bytes, buf->area,
175   - buf->addr);
176   - buf->area = NULL;
177   - }
178   -}
179   -
180   -static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32);
181   -
182   -static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
183   -{
184   - struct snd_card *card = rtd->card->snd_card;
185   - struct snd_pcm *pcm = rtd->pcm;
186   - int ret = 0;
187   -
188   - if (!card->dev->dma_mask)
189   - card->dev->dma_mask = &ep93xx_pcm_dmamask;
190   - if (!card->dev->coherent_dma_mask)
191   - card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
192   -
193   - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
194   - ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
195   - SNDRV_PCM_STREAM_PLAYBACK);
196   - if (ret)
197   - return ret;
198   - }
199   -
200   - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
201   - ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
202   - SNDRV_PCM_STREAM_CAPTURE);
203   - if (ret)
204   - return ret;
205   - }
206   -
207   - return 0;
208   -}
209   -
210   -static struct snd_soc_platform_driver ep93xx_soc_platform = {
211   - .ops = &ep93xx_pcm_ops,
212   - .pcm_new = &ep93xx_pcm_new,
213   - .pcm_free = &ep93xx_pcm_free_dma_buffers,
214   -};
215   -
216   -static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
217   -{
218   - return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
219   -}
220   -
221   -static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
222   -{
223   - snd_soc_unregister_platform(&pdev->dev);
224   - return 0;
225   -}
226   -
227   -static struct platform_driver ep93xx_pcm_driver = {
228   - .driver = {
229   - .name = "ep93xx-pcm-audio",
230   - .owner = THIS_MODULE,
231   - },
232   -
233   - .probe = ep93xx_soc_platform_probe,
234   - .remove = __devexit_p(ep93xx_soc_platform_remove),
235   -};
236   -
237   -module_platform_driver(ep93xx_pcm_driver);
238   -
239   -MODULE_AUTHOR("Ryan Mallon");
240   -MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
241   -MODULE_LICENSE("GPL");
242   -MODULE_ALIAS("platform:ep93xx-pcm-audio");
sound/soc/ep93xx/ep93xx-pcm.h
1   -/*
2   - * sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface
3   - *
4   - * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
5   - * Copyright (C) 2006 Applied Data Systems
6   - *
7   - * This program is free software; you can redistribute it and/or modify
8   - * it under the terms of the GNU General Public License version 2 as
9   - * published by the Free Software Foundation.
10   - */
11   -
12   -#ifndef _EP93XX_SND_SOC_PCM_H
13   -#define _EP93XX_SND_SOC_PCM_H
14   -
15   -struct ep93xx_pcm_dma_params {
16   - char *name;
17   - int dma_port;
18   -};
19   -
20   -#endif /* _EP93XX_SND_SOC_PCM_H */
sound/soc/ep93xx/simone.c
1   -/*
2   - * simone.c -- ASoC audio for Simplemachines Sim.One board
3   - *
4   - * Copyright (c) 2010 Mika Westerberg
5   - *
6   - * Based on snappercl15 machine driver by Ryan Mallon.
7   - *
8   - * This program is free software; you can redistribute it and/or modify
9   - * it under the terms of the GNU General Public License version 2 as
10   - * published by the Free Software Foundation.
11   - */
12   -
13   -#include <linux/init.h>
14   -#include <linux/module.h>
15   -#include <linux/platform_device.h>
16   -
17   -#include <sound/core.h>
18   -#include <sound/pcm.h>
19   -#include <sound/soc.h>
20   -
21   -#include <asm/mach-types.h>
22   -#include <mach/hardware.h>
23   -
24   -#include "ep93xx-pcm.h"
25   -
26   -static struct snd_soc_dai_link simone_dai = {
27   - .name = "AC97",
28   - .stream_name = "AC97 HiFi",
29   - .cpu_dai_name = "ep93xx-ac97",
30   - .codec_dai_name = "ac97-hifi",
31   - .codec_name = "ac97-codec",
32   - .platform_name = "ep93xx-pcm-audio",
33   -};
34   -
35   -static struct snd_soc_card snd_soc_simone = {
36   - .name = "Sim.One",
37   - .owner = THIS_MODULE,
38   - .dai_link = &simone_dai,
39   - .num_links = 1,
40   -};
41   -
42   -static struct platform_device *simone_snd_ac97_device;
43   -
44   -static int __devinit simone_probe(struct platform_device *pdev)
45   -{
46   - struct snd_soc_card *card = &snd_soc_simone;
47   - int ret;
48   -
49   - simone_snd_ac97_device = platform_device_register_simple("ac97-codec",
50   - -1, NULL, 0);
51   - if (IS_ERR(simone_snd_ac97_device))
52   - return PTR_ERR(simone_snd_ac97_device);
53   -
54   - card->dev = &pdev->dev;
55   -
56   - ret = snd_soc_register_card(card);
57   - if (ret) {
58   - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
59   - ret);
60   - platform_device_unregister(simone_snd_ac97_device);
61   - }
62   -
63   - return ret;
64   -}
65   -
66   -static int __devexit simone_remove(struct platform_device *pdev)
67   -{
68   - struct snd_soc_card *card = platform_get_drvdata(pdev);
69   -
70   - snd_soc_unregister_card(card);
71   - platform_device_unregister(simone_snd_ac97_device);
72   -
73   - return 0;
74   -}
75   -
76   -static struct platform_driver simone_driver = {
77   - .driver = {
78   - .name = "simone-audio",
79   - .owner = THIS_MODULE,
80   - },
81   - .probe = simone_probe,
82   - .remove = __devexit_p(simone_remove),
83   -};
84   -
85   -module_platform_driver(simone_driver);
86   -
87   -MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
88   -MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
89   -MODULE_LICENSE("GPL");
90   -MODULE_ALIAS("platform:simone-audio");
sound/soc/ep93xx/snappercl15.c
1   -/*
2   - * snappercl15.c -- SoC audio for Bluewater Systems Snapper CL15 module
3   - *
4   - * Copyright (C) 2008 Bluewater Systems Ltd
5   - * Author: Ryan Mallon
6   - *
7   - * This program is free software; you can redistribute it and/or modify it
8   - * under the terms of the GNU General Public License as published by the
9   - * Free Software Foundation; either version 2 of the License, or (at your
10   - * option) any later version.
11   - *
12   - */
13   -
14   -#include <linux/platform_device.h>
15   -#include <linux/module.h>
16   -#include <sound/core.h>
17   -#include <sound/pcm.h>
18   -#include <sound/soc.h>
19   -
20   -#include <asm/mach-types.h>
21   -#include <mach/hardware.h>
22   -
23   -#include "../codecs/tlv320aic23.h"
24   -#include "ep93xx-pcm.h"
25   -
26   -#define CODEC_CLOCK 5644800
27   -
28   -static int snappercl15_hw_params(struct snd_pcm_substream *substream,
29   - struct snd_pcm_hw_params *params)
30   -{
31   - struct snd_soc_pcm_runtime *rtd = substream->private_data;
32   - struct snd_soc_dai *codec_dai = rtd->codec_dai;
33   - struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
34   - int err;
35   -
36   - err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK,
37   - SND_SOC_CLOCK_IN);
38   - if (err)
39   - return err;
40   -
41   - err = snd_soc_dai_set_sysclk(cpu_dai, 0, CODEC_CLOCK,
42   - SND_SOC_CLOCK_OUT);
43   - if (err)
44   - return err;
45   -
46   - return 0;
47   -}
48   -
49   -static struct snd_soc_ops snappercl15_ops = {
50   - .hw_params = snappercl15_hw_params,
51   -};
52   -
53   -static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
54   - SND_SOC_DAPM_HP("Headphone Jack", NULL),
55   - SND_SOC_DAPM_LINE("Line In", NULL),
56   - SND_SOC_DAPM_MIC("Mic Jack", NULL),
57   -};
58   -
59   -static const struct snd_soc_dapm_route audio_map[] = {
60   - {"Headphone Jack", NULL, "LHPOUT"},
61   - {"Headphone Jack", NULL, "RHPOUT"},
62   -
63   - {"LLINEIN", NULL, "Line In"},
64   - {"RLINEIN", NULL, "Line In"},
65   -
66   - {"MICIN", NULL, "Mic Jack"},
67   -};
68   -
69   -static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
70   -{
71   - struct snd_soc_codec *codec = rtd->codec;
72   - struct snd_soc_dapm_context *dapm = &codec->dapm;
73   -
74   - snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
75   - ARRAY_SIZE(tlv320aic23_dapm_widgets));
76   -
77   - snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
78   - return 0;
79   -}
80   -
81   -static struct snd_soc_dai_link snappercl15_dai = {
82   - .name = "tlv320aic23",
83   - .stream_name = "AIC23",
84   - .cpu_dai_name = "ep93xx-i2s",
85   - .codec_dai_name = "tlv320aic23-hifi",
86   - .codec_name = "tlv320aic23-codec.0-001a",
87   - .platform_name = "ep93xx-pcm-audio",
88   - .init = snappercl15_tlv320aic23_init,
89   - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
90   - SND_SOC_DAIFMT_CBS_CFS,
91   - .ops = &snappercl15_ops,
92   -};
93   -
94   -static struct snd_soc_card snd_soc_snappercl15 = {
95   - .name = "Snapper CL15",
96   - .owner = THIS_MODULE,
97   - .dai_link = &snappercl15_dai,
98   - .num_links = 1,
99   -};
100   -
101   -static int __devinit snappercl15_probe(struct platform_device *pdev)
102   -{
103   - struct snd_soc_card *card = &snd_soc_snappercl15;
104   - int ret;
105   -
106   - ret = ep93xx_i2s_acquire();
107   - if (ret)
108   - return ret;
109   -
110   - card->dev = &pdev->dev;
111   -
112   - ret = snd_soc_register_card(card);
113   - if (ret) {
114   - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
115   - ret);
116   - ep93xx_i2s_release();
117   - }
118   -
119   - return ret;
120   -}
121   -
122   -static int __devexit snappercl15_remove(struct platform_device *pdev)
123   -{
124   - struct snd_soc_card *card = platform_get_drvdata(pdev);
125   -
126   - snd_soc_unregister_card(card);
127   - ep93xx_i2s_release();
128   -
129   - return 0;
130   -}
131   -
132   -static struct platform_driver snappercl15_driver = {
133   - .driver = {
134   - .name = "snappercl15-audio",
135   - .owner = THIS_MODULE,
136   - },
137   - .probe = snappercl15_probe,
138   - .remove = __devexit_p(snappercl15_remove),
139   -};
140   -
141   -module_platform_driver(snappercl15_driver);
142   -
143   -MODULE_AUTHOR("Ryan Mallon");
144   -MODULE_DESCRIPTION("ALSA SoC Snapper CL15");
145   -MODULE_LICENSE("GPL");
146   -MODULE_ALIAS("platform:snappercl15-audio");