aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiridhar Maruthy <giridhar.maruthy@linaro.org>2011-12-22 15:37:52 +0530
committerTushar Behera <tushar.behera@linaro.org>2012-06-20 11:12:40 +0530
commit39ac53f2de751977c4b30da574fdfc26c0aa23b5 (patch)
treea77efea7d9b3dd995288276b61be720661a6da29
parentfc250fb6e457f57193978b4ffd3df2479f36f8d1 (diff)
ASoC: samsung: ALC5625: Adding I2S platform support on Origen
Signed-off-by: Pan <pan@insignal.co.kr> Signed-off-by: Giridhar Maruthy <giridhar.maruthy@linaro.org> Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/alc5625/Kconfig10
-rw-r--r--drivers/staging/alc5625/Makefile1
-rw-r--r--drivers/staging/alc5625/origen_alc5625.c229
5 files changed, 243 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 05e33c700750..044bdb2698c2 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -132,4 +132,6 @@ source "drivers/staging/ipack/Kconfig"
source "drivers/staging/gdm72xx/Kconfig"
+source "drivers/staging/alc5625/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index a987b3ad380b..0fe991ae7b76 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_RAMSTER) += ramster/
obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
obj-$(CONFIG_USB_G_CCG) += ccg/
obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
+obj-$(CONFIG_SND_SOC_ORIGEN_ALC5625) += alc5625/
diff --git a/drivers/staging/alc5625/Kconfig b/drivers/staging/alc5625/Kconfig
index fda4f9b2606e..b35a4695497d 100644
--- a/drivers/staging/alc5625/Kconfig
+++ b/drivers/staging/alc5625/Kconfig
@@ -1,3 +1,13 @@
# Staging the origen board audio codec
config SND_SOC_ALC5625
tristate
+
+config SND_SOC_ORIGEN_ALC5625
+ tristate "SoC I2S Audio support for ALC5625 on ORIGEN board"
+ depends on SND_SOC_SAMSUNG && MACH_ORIGEN
+ select SND_SOC_ALC5625
+ select SND_SAMSUNG_I2S
+ select fool
+ help
+ Say Y if you want to add support for SoC audio
+ on origen board using ALC5625 codec
diff --git a/drivers/staging/alc5625/Makefile b/drivers/staging/alc5625/Makefile
index e5f4132605ba..ae4d85e7738b 100644
--- a/drivers/staging/alc5625/Makefile
+++ b/drivers/staging/alc5625/Makefile
@@ -1,2 +1,3 @@
# Staging the origen board audio codec
obj-$(CONFIG_SND_SOC_ALC5625) += alc5625.o
+obj-$(CONFIG_SND_SOC_ORIGEN_ALC5625) += origen_alc5625.o
diff --git a/drivers/staging/alc5625/origen_alc5625.c b/drivers/staging/alc5625/origen_alc5625.c
new file mode 100644
index 000000000000..75c1d2e6cd6d
--- /dev/null
+++ b/drivers/staging/alc5625/origen_alc5625.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2011 Insignal Co., Ltd.
+ *
+ * Author: Pan <pan@insginal.co.kr>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "../../../sound/soc/samsung/i2s.h"
+
+static int set_epll_rate(unsigned long rate)
+{
+ struct clk *fout_epll;
+
+ fout_epll = clk_get(NULL, "fout_epll");
+ if (IS_ERR(fout_epll)) {
+ printk(KERN_ERR "%s: failed to get fout_epll\n", __func__);
+ return -ENOENT;
+ }
+
+ if (rate == clk_get_rate(fout_epll))
+ goto out;
+
+ clk_set_rate(fout_epll, rate);
+out:
+ clk_put(fout_epll);
+
+ return 0;
+}
+
+static int origen_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 *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int bfs, psr, rfs, ret;
+ unsigned long rclk;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_U24:
+ case SNDRV_PCM_FORMAT_S24:
+ bfs = 48;
+ break;
+ case SNDRV_PCM_FORMAT_U16_LE:
+ case SNDRV_PCM_FORMAT_S16_LE:
+ bfs = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (params_rate(params)) {
+ case 16000:
+ case 22050:
+ case 24000:
+ case 32000:
+ case 44100:
+ case 48000:
+ case 88200:
+ case 96000:
+ rfs = (bfs == 48) ? 384 : 256;
+ break;
+ case 64000:
+ rfs = 384;
+ break;
+ case 8000:
+ case 11025:
+ case 12000:
+ rfs = (bfs == 48) ? 768 : 512;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rclk = params_rate(params) * rfs;
+
+ switch (rclk) {
+ case 4096000:
+ case 5644800:
+ case 6144000:
+ case 8467200:
+ case 9216000:
+ psr = 8;
+ break;
+ case 8192000:
+ case 11289600:
+ case 12288000:
+ case 16934400:
+ case 18432000:
+ psr = 4;
+ break;
+ case 22579200:
+ case 24576000:
+ case 33868800:
+ case 36864000:
+ psr = 2;
+ break;
+ case 67737600:
+ case 73728000:
+ psr = 1;
+ break;
+ default:
+ printk(KERN_ERR "Not yet supported!\n");
+ return -EINVAL;
+ }
+
+ set_epll_rate(rclk * psr);
+
+ /* Set the Codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* Set the AP DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK, rfs,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, SAMSUNG_I2S_DIV_BCLK, bfs);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops origen_ops = {
+ .hw_params = origen_hw_params,
+};
+
+static int origen_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ snd_soc_dapm_sync(dapm);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link origen_dai[] = {
+ { /* Primary DAI i/f */
+ .name = "ALC5625 PAIF",
+ .stream_name = "Pri_Dai",
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "alc5625-aif1",
+ .platform_name = "samsung-audio",
+ .codec_name = "alc5625-codec.1-001e",
+ .init = origen_wm8994_init_paiftx,
+ .ops = &origen_ops,
+ },
+};
+
+static struct snd_soc_card snd_soc_origen_audio = {
+ .name = "ORIGEN-I2S",
+ .dai_link = origen_dai,
+ .num_links = ARRAY_SIZE(origen_dai),
+};
+
+static int __devinit origen_audio_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct snd_soc_card *card = &snd_soc_origen_audio;
+
+ card->dev = &pdev->dev;
+
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+
+ return ret;
+}
+
+static int __devexit origen_audio_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static struct platform_driver origen_audio_driver = {
+ .driver = {
+ .name = "origen-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = origen_audio_probe,
+ .remove = __devexit_p(origen_audio_remove),
+};
+
+static int __init origen_audio_init(void)
+{
+ return platform_driver_register(&origen_audio_driver);
+}
+late_initcall(origen_audio_init);
+
+static void __exit origen_audio_exit(void)
+{
+ platform_driver_unregister(&origen_audio_driver);
+}
+module_exit(origen_audio_exit);
+
+MODULE_AUTHOR("Pan, <pan@insignal.co.kr>");
+MODULE_DESCRIPTION("ALSA SoC ORIGEN+ALC5625");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:origen-audio");