diff options
author | Giridhar Maruthy <giridhar.maruthy@linaro.org> | 2011-12-22 15:37:52 +0530 |
---|---|---|
committer | Tushar Behera <tushar.behera@linaro.org> | 2012-06-20 11:12:40 +0530 |
commit | 39ac53f2de751977c4b30da574fdfc26c0aa23b5 (patch) | |
tree | a77efea7d9b3dd995288276b61be720661a6da29 | |
parent | fc250fb6e457f57193978b4ffd3df2479f36f8d1 (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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/alc5625/Kconfig | 10 | ||||
-rw-r--r-- | drivers/staging/alc5625/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/alc5625/origen_alc5625.c | 229 |
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"); |