aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/s3c24xx/smdk6410-wm8731.c
diff options
context:
space:
mode:
authormerge <null@invalid>2009-02-24 01:49:53 +0000
committerAndy Green <agreen@octopus.localdomain>2009-02-24 01:49:53 +0000
commit7fafbf75a0978b79e32c6a0ce15a776fea6d8481 (patch)
tree0d4eacd74a04b0bd9c0e2c926aefe07b8f48a38d /sound/soc/s3c24xx/smdk6410-wm8731.c
parent1c6a91fef7cb2e0fc4f41ddcfff74565b2a7659e (diff)
MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-s3c64xx-dma-support-1235439162-1235439227
pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-s3c64xx-dma-support-1235439162-1235439227 / 3d6a1b21cf5fbdb6250d781b0a4900a7a0768aa1 ... parent commitmessage: From: merge <null@invalid> MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-s3c64xx-dma-support-1235439162 stable-tracking-hist top was MERGE-via-mokopatches-tracking-s3c64xx-dma-support-1235439162 / 893e864e65adffc9eb085ed4f8b552a31dcec840 ... parent commitmessage: From: merge <null@invalid> MERGE-via-mokopatches-tracking-hist-s3c64xx-dma-support mokopatches-tracking-hist top was s3c64xx-dma-support / 2515f9a1d53d19b1e61d639875aedcbe7929666e ... parent commitmessage: From: Ben Dooks <ben@simtec.co.uk> S3C64XX: DMA support Add support for the DMA blocks in the S3C64XX series of CPUS, which are based on the ARM PL080 PrimeCell system. Unfortunately, these DMA controllers diverge from the PL080 design by adding another DMA controller register and configuration for OneNAND. Signed-off-by: Ben Dooks <ben@simtec.co.uk>
Diffstat (limited to 'sound/soc/s3c24xx/smdk6410-wm8731.c')
-rw-r--r--sound/soc/s3c24xx/smdk6410-wm8731.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/sound/soc/s3c24xx/smdk6410-wm8731.c b/sound/soc/s3c24xx/smdk6410-wm8731.c
new file mode 100644
index 00000000000..e11d5d48a5c
--- /dev/null
+++ b/sound/soc/s3c24xx/smdk6410-wm8731.c
@@ -0,0 +1,227 @@
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/wm8731.h"
+#include "s3c64xx-i2s.h"
+
+static struct platform_device *socdev;
+
+
+
+static void wm_shutdown(struct snd_pcm_substream *substream)
+{
+ printk(KERN_INFO "%s: substream %p\n", __func__, substream);
+}
+
+static int wm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ unsigned int fmt;
+ int ret;
+
+ printk(KERN_INFO "%s: (%p,%p)\n", __func__, substream, params);
+ printk(KERN_INFO "%s: dai: cpu %p, codec %p\n", __func__, cpu_dai, codec_dai);
+
+ //fmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS;
+ fmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM;
+ fmt |= SND_SOC_DAIFMT_I2S;
+
+ ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+ if (ret < 0)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+ if (ret < 0)
+ return ret;
+
+ if (fmt == (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM)) {
+ unsigned long iis_clkrate;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_MUX, 0,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: cpu set_sysclk err\n", __func__);
+ return ret;
+ }
+
+ /* set prescaler division for sample rate */
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C64XX_DIV_PRESCALER, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: codec clkdiv err\n", __func__);
+ return ret;
+ }
+
+ iis_clkrate = s3c64xx_i2s_get_clockrate(cpu_dai) / 2;
+ printk(KERN_INFO "%s: clockrate %ld\n", __func__, iis_clkrate);
+
+ iis_clkrate = 12000000; //tmphack//
+
+ /* set the codec system clock for DAC and ADC */
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
+ iis_clkrate,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: codec sysclk err\n", __func__);
+ return ret;
+ }
+
+ } else {
+ /* TODO */
+ BUG();
+ }
+
+ return 0;
+}
+
+static int wm_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+ struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_MUX, 0,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: cpu set_sysclk err\n", __func__);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C64XX_DIV_PRESCALER, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: cpu set_clkdiv err\n", __func__);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
+ 12000000, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: codec sysclk err\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops wm_ops = {
+ .startup = wm_startup,
+ .hw_params = wm_hw_params,
+ .shutdown = wm_shutdown,
+};
+
+static const struct snd_soc_dapm_widget widgets[] = {
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_INPUT("Line In"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+ /* headphone connected to LHPOUT1, RHPOUT1 */
+ {"Headphone Jack", NULL, "LHPOUT"},
+ {"Headphone Jack", NULL, "RHPOUT"},
+
+ {"Line Out", NULL, "LOUT" },
+ {"Line Out", NULL, "ROUT" },
+
+ {"LLINEIN", NULL, "Line In" },
+ {"RLINEIN", NULL, "Line In" },
+};
+
+static int wm_init(struct snd_soc_codec *codec)
+{
+ printk(KERN_DEBUG "%s: codec %p\n", __func__, codec);
+
+ snd_soc_dapm_new_controls(codec, widgets, ARRAY_SIZE(widgets));
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
+}
+
+#include "s3c24xx-pcm.h"
+
+static struct snd_soc_dai_link wm_dai_link = {
+ .name = "WM8731",
+ .stream_name = "WM8731",
+ .cpu_dai = &s3c64xx_i2s_dai,
+ .codec_dai = &wm8731_dai,
+ .init = wm_init,
+ .ops = &wm_ops,
+};
+
+static struct snd_soc_card wm_card = {
+ .name = "SMDK6410-WM8731",
+ .dai_link = &wm_dai_link,
+ .platform = &s3c24xx_soc_platform,
+ .num_links = 1,
+};
+
+struct wm8731_setup_data wm_setup = {
+ .i2c_bus = 0,
+ .i2c_address = 0x1a,
+};
+
+static struct snd_soc_device wm_snd_devdata = {
+ .card = &wm_card,
+ .codec_dev = &soc_codec_dev_wm8731,
+ .codec_data = &wm_setup,
+};
+
+static int __init smdk6410_wm8731_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "%s: welcome\n", __func__);
+
+ if (!machine_is_smdk6410()) {
+ printk(KERN_INFO "%s: for SMDK6410s\n", __func__);
+ return -ENOENT;
+ }
+
+ socdev = platform_device_alloc("soc-audio", 0);
+ if (!socdev) {
+ printk(KERN_ERR "%s: no device\n", __func__);
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(socdev, &wm_snd_devdata);
+
+ wm_snd_devdata.dev = &socdev->dev;
+
+ ret = platform_device_add(socdev);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to add\n", __func__);
+ goto err_dev;
+ }
+
+ printk(KERN_INFO "%s: succesfull\n", __func__);
+ return 0;
+
+err_dev:
+ platform_device_put(socdev);
+ return ret;
+}
+
+module_init(smdk6410_wm8731_init);
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");