diff options
Diffstat (limited to 'sound/soc/ep93xx')
-rw-r--r-- | sound/soc/ep93xx/Kconfig | 9 | ||||
-rw-r--r-- | sound/soc/ep93xx/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/ep93xx/edb93xx.c | 142 | ||||
-rw-r--r-- | sound/soc/ep93xx/ep93xx-ac97.c | 1 | ||||
-rw-r--r-- | sound/soc/ep93xx/ep93xx-i2s.c | 31 | ||||
-rw-r--r-- | sound/soc/ep93xx/ep93xx-pcm.c | 4 |
6 files changed, 172 insertions, 17 deletions
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig index 57429041189..91a28de9410 100644 --- a/sound/soc/ep93xx/Kconfig +++ b/sound/soc/ep93xx/Kconfig @@ -30,3 +30,12 @@ config SND_EP93XX_SOC_SIMONE help Say Y or M here if you want to add support for AC97 audio on the Simplemachines Sim.One board. + +config SND_EP93XX_SOC_EDB93XX + tristate "SoC Audio support for Cirrus Logic EDB93xx boards" + depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A) + select SND_EP93XX_SOC_I2S + select SND_SOC_CS4271 + help + Say Y or M here if you want to add support for I2S audio on the + Cirrus Logic EDB93xx boards. diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile index 8e7977fb6b7..5514146cbdf 100644 --- a/sound/soc/ep93xx/Makefile +++ b/sound/soc/ep93xx/Makefile @@ -10,6 +10,8 @@ obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o # EP93XX Machine Support snd-soc-snappercl15-objs := snappercl15.o snd-soc-simone-objs := simone.o +snd-soc-edb93xx-objs := edb93xx.o obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o +obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c new file mode 100644 index 00000000000..d3aa15119d2 --- /dev/null +++ b/sound/soc/ep93xx/edb93xx.c @@ -0,0 +1,142 @@ +/* + * SoC audio for EDB93xx + * + * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This driver support CS4271 codec being master or slave, working + * in control port mode, connected either via SPI or I2C. + * The data format accepted is I2S or left-justified. + * DAPM support not implemented. + */ + +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <asm/mach-types.h> +#include <mach/hardware.h> +#include "ep93xx-pcm.h" + +#define edb93xx_has_audio() (machine_is_edb9301() || \ + machine_is_edb9302() || \ + machine_is_edb9302a() || \ + machine_is_edb9307a() || \ + machine_is_edb9315a()) + +static int edb93xx_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int err; + unsigned int mclk_rate; + unsigned int rate = params_rate(params); + + /* + * According to CS4271 datasheet we use MCLK/LRCK=256 for + * rates below 50kHz and 128 for higher sample rates + */ + if (rate < 50000) + mclk_rate = rate * 64 * 4; + else + mclk_rate = rate * 64 * 2; + + err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS); + if (err) + return err; + + err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF | + SND_SOC_DAIFMT_CBS_CFS); + if (err) + return err; + + err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate, + SND_SOC_CLOCK_IN); + if (err) + return err; + + return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate, + SND_SOC_CLOCK_OUT); +} + +static struct snd_soc_ops edb93xx_ops = { + .hw_params = edb93xx_hw_params, +}; + +static struct snd_soc_dai_link edb93xx_dai = { + .name = "CS4271", + .stream_name = "CS4271 HiFi", + .platform_name = "ep93xx-pcm-audio", + .cpu_dai_name = "ep93xx-i2s", + .codec_name = "spi0.0", + .codec_dai_name = "cs4271-hifi", + .ops = &edb93xx_ops, +}; + +static struct snd_soc_card snd_soc_edb93xx = { + .name = "EDB93XX", + .dai_link = &edb93xx_dai, + .num_links = 1, +}; + +static struct platform_device *edb93xx_snd_device; + +static int __init edb93xx_init(void) +{ + int ret; + + if (!edb93xx_has_audio()) + return -ENODEV; + + ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97, + EP93XX_SYSCON_I2SCLKDIV_ORIDE | + EP93XX_SYSCON_I2SCLKDIV_SPOL); + if (ret) + return ret; + + edb93xx_snd_device = platform_device_alloc("soc-audio", -1); + if (!edb93xx_snd_device) { + ret = -ENOMEM; + goto free_i2s; + } + + platform_set_drvdata(edb93xx_snd_device, &snd_soc_edb93xx); + ret = platform_device_add(edb93xx_snd_device); + if (ret) + goto device_put; + + return 0; + +device_put: + platform_device_put(edb93xx_snd_device); +free_i2s: + ep93xx_i2s_release(); + return ret; +} +module_init(edb93xx_init); + +static void __exit edb93xx_exit(void) +{ + platform_device_unregister(edb93xx_snd_device); + ep93xx_i2s_release(); +} +module_exit(edb93xx_exit); + +MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); +MODULE_DESCRIPTION("ALSA SoC EDB93xx"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c index 68a0bae1208..104e95cda0a 100644 --- a/sound/soc/ep93xx/ep93xx-ac97.c +++ b/sound/soc/ep93xx/ep93xx-ac97.c @@ -253,7 +253,6 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai); unsigned v = 0; - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c index fff579a1c13..042f4e93746 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/ep93xx/ep93xx-i2s.c @@ -242,7 +242,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, { struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); unsigned word_len, div, sdiv, lrdiv; - int found = 0, err; + int err; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: @@ -275,15 +275,14 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, * the codec uses. */ div = clk_get_rate(info->mclk) / params_rate(params); - for (sdiv = 2; sdiv <= 4; sdiv += 2) - for (lrdiv = 64; lrdiv <= 128; lrdiv <<= 1) - if (sdiv * lrdiv == div) { - found = 1; - goto out; - } -out: - if (!found) - return -EINVAL; + sdiv = 4; + if (div > (256 + 512) / 2) { + lrdiv = 128; + } else { + lrdiv = 64; + if (div < (128 + 256) / 2) + sdiv = 2; + } err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); if (err) @@ -314,10 +313,12 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); if (!dai->active) - return; + return 0; ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); + + return 0; } static int ep93xx_i2s_resume(struct snd_soc_dai *dai) @@ -325,10 +326,12 @@ static int ep93xx_i2s_resume(struct snd_soc_dai *dai) struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); if (!dai->active) - return; + return 0; ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); + + return 0; } #else #define ep93xx_i2s_suspend NULL @@ -352,13 +355,13 @@ static struct snd_soc_dai_driver ep93xx_i2s_dai = { .playback = { .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = EP93XX_I2S_FORMATS, }, .capture = { .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = EP93XX_I2S_FORMATS, }, .ops = &ep93xx_i2s_dai_ops, diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 06670776f64..a456e491155 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c @@ -35,9 +35,9 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = { SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER), - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .rate_min = SNDRV_PCM_RATE_8000, - .rate_max = SNDRV_PCM_RATE_96000, + .rate_max = SNDRV_PCM_RATE_192000, .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |