Path: blob/master/sound/soc/samsung/smdk_wm8580pcm.c
10817 views
/*1* sound/soc/samsung/smdk_wm8580pcm.c2*3* Copyright (c) 2011 Samsung Electronics Co. Ltd4*5* This program is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License as published by the7* Free Software Foundation; either version 2 of the License, or (at your8* option) any later version.9*/10#include <sound/soc.h>11#include <sound/pcm_params.h>12#include <sound/pcm.h>1314#include <asm/mach-types.h>1516#include "../codecs/wm8580.h"17#include "dma.h"18#include "pcm.h"1920/*21* Board Settings:22* o '1' means 'ON'23* o '0' means 'OFF'24* o 'X' means 'Don't care'25*26* SMDK6410, SMDK6440, SMDK6450 Base B/D: CFG1-0000, CFG2-111127* SMDKC110, SMDKV210: CFGB11-100100, CFGB12-000028*/2930#define SMDK_WM8580_EXT_OSC 1200000031#define SMDK_WM8580_EXT_MCLK 409600032#define SMDK_WM8580_EXT_VOICE 20480003334static unsigned long mclk_freq;35static unsigned long xtal_freq;3637/*38* If MCLK clock directly gets from XTAL, we don't have to use PLL39* to make MCLK, but if XTAL clock source connects with other codec40* pin (like XTI), we should have to set codec's PLL to make MCLK.41* Because Samsung SoC does not support pcmcdclk output like I2S.42*/4344static int smdk_wm8580_pcm_hw_params(struct snd_pcm_substream *substream,45struct snd_pcm_hw_params *params)46{47struct snd_soc_pcm_runtime *rtd = substream->private_data;48struct snd_soc_dai *codec_dai = rtd->codec_dai;49struct snd_soc_dai *cpu_dai = rtd->cpu_dai;50int rfs, ret;5152switch (params_rate(params)) {53case 8000:54break;55default:56printk(KERN_ERR "%s:%d Sampling Rate %u not supported!\n",57__func__, __LINE__, params_rate(params));58return -EINVAL;59}6061rfs = mclk_freq / params_rate(params) / 2;6263/* Set the codec DAI configuration */64ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B65| SND_SOC_DAIFMT_IB_NF66| SND_SOC_DAIFMT_CBS_CFS);67if (ret < 0)68return ret;6970/* Set the cpu DAI configuration */71ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_B72| SND_SOC_DAIFMT_IB_NF73| SND_SOC_DAIFMT_CBS_CFS);74if (ret < 0)75return ret;7677if (mclk_freq == xtal_freq) {78ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_MCLK,79mclk_freq, SND_SOC_CLOCK_IN);80if (ret < 0)81return ret;8283ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,84WM8580_CLKSRC_MCLK);85if (ret < 0)86return ret;87} else {88ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA,89mclk_freq, SND_SOC_CLOCK_IN);90if (ret < 0)91return ret;9293ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,94WM8580_CLKSRC_PLLA);95if (ret < 0)96return ret;9798ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,99xtal_freq, mclk_freq);100if (ret < 0)101return ret;102}103104/* Set PCM source clock on CPU */105ret = snd_soc_dai_set_sysclk(cpu_dai, S3C_PCM_CLKSRC_MUX,106mclk_freq, SND_SOC_CLOCK_IN);107if (ret < 0)108return ret;109110/* Set SCLK_DIV for making bclk */111ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_PCM_SCLK_PER_FS, rfs);112if (ret < 0)113return ret;114115return 0;116}117118static struct snd_soc_ops smdk_wm8580_pcm_ops = {119.hw_params = smdk_wm8580_pcm_hw_params,120};121122static struct snd_soc_dai_link smdk_dai[] = {123{124.name = "WM8580 PAIF PCM RX",125.stream_name = "Playback",126.cpu_dai_name = "samsung-pcm.0",127.codec_dai_name = "wm8580-hifi-playback",128.platform_name = "samsung-audio",129.codec_name = "wm8580-codec.0-001b",130.ops = &smdk_wm8580_pcm_ops,131}, {132.name = "WM8580 PAIF PCM TX",133.stream_name = "Capture",134.cpu_dai_name = "samsung-pcm.0",135.codec_dai_name = "wm8580-hifi-capture",136.platform_name = "samsung-audio",137.codec_name = "wm8580-codec.0-001b",138.ops = &smdk_wm8580_pcm_ops,139},140};141142static struct snd_soc_card smdk_pcm = {143.name = "SMDK-PCM",144.dai_link = smdk_dai,145.num_links = 2,146};147148/*149* After SMDKC110 Base Board's Rev is '0.1', 12MHz External OSC(X1)150* is absent (or not connected), so we connect EXT_VOICE_CLK(OSC4),151* 2.0484Mhz, directly with MCLK both Codec and SoC.152*/153static int __devinit snd_smdk_probe(struct platform_device *pdev)154{155int ret = 0;156157xtal_freq = SMDK_WM8580_EXT_OSC;158mclk_freq = SMDK_WM8580_EXT_MCLK;159160if (machine_is_smdkc110() || machine_is_smdkv210())161xtal_freq = mclk_freq = SMDK_WM8580_EXT_VOICE;162163smdk_pcm.dev = &pdev->dev;164ret = snd_soc_register_card(&smdk_pcm);165if (ret) {166dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret);167return ret;168}169170return 0;171}172173static int __devexit snd_smdk_remove(struct platform_device *pdev)174{175snd_soc_unregister_card(&smdk_pcm);176platform_set_drvdata(pdev, NULL);177return 0;178}179180static struct platform_driver snd_smdk_driver = {181.driver = {182.owner = THIS_MODULE,183.name = "samsung-smdk-pcm",184},185.probe = snd_smdk_probe,186.remove = __devexit_p(snd_smdk_remove),187};188189static int __init smdk_audio_init(void)190{191return platform_driver_register(&snd_smdk_driver);192}193194module_init(smdk_audio_init);195196static void __exit smdk_audio_exit(void)197{198platform_driver_unregister(&snd_smdk_driver);199}200201module_exit(smdk_audio_exit);202203MODULE_AUTHOR("Sangbeom Kim, <[email protected]>");204MODULE_DESCRIPTION("ALSA SoC SMDK WM8580 for PCM");205MODULE_LICENSE("GPL");206207208