The checkpatch in svn server has a bug about EXPORT_SYMBOL now. This
happened to me too.
-barry
________________________________
From: [email protected]
[mailto:[email protected]] On Behalf Of
[email protected]
Sent: Tuesday, April 06, 2010 1:13 PM
To: [email protected]
Subject: [Linux-kernel-commits] [8608] trunk/sound/soc:
[!no_src_qa!]
Revision
8608
<http://blackfin.uclinux.org/gf/project/linux-kernel/scmsvn/?action=brow
se&path=/&view=rev&root=linux-kernel&revision=8608>
Author
adamliyi <http://blackfin.uclinux.org/gf/user/adamliyi/>
Date
2010-04-06 01:12:46 -0400 (Tue, 06 Apr 2010)
Log Message
[!no_src_qa!]
Initial version of adav801/adav803 driver.
Ignore the warning:
WARNING: EXPORT_SYMBOL(foo); should immediately follow its
function/variable
#468: FILE: sound/soc/codecs/adav80x.c:229:
+EXPORT_SYMBOL_GPL(adav80x_dai);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its
function/variable
#519: FILE: sound/soc/codecs/adav80x.c:280:
+EXPORT_SYMBOL_GPL(soc_codec_dev_adav80x);
Modified Paths
* trunk/sound/soc/blackfin/Kconfig
* trunk/sound/soc/blackfin/Makefile
* trunk/sound/soc/codecs/Kconfig
* trunk/sound/soc/codecs/Makefile
Added Paths
* trunk/sound/soc/blackfin/bf5xx-adav80x.c
* trunk/sound/soc/codecs/adav80x.c
Diff
Modified: trunk/sound/soc/blackfin/Kconfig (8607 => 8608)
--- trunk/sound/soc/blackfin/Kconfig 2010-04-06 04:17:08 UTC
(rev 8607)
+++ trunk/sound/soc/blackfin/Kconfig 2010-04-06 05:12:46 UTC
(rev 8608)
@@ -68,6 +68,14 @@
help
Say Y if you want to add support for ADAU1381 SoC
audio.
+config SND_BF5XX_SOC_ADAV80X
+ tristate "SoC ADAV801/3 Audio support"
+ depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
+ select SND_BF5XX_SOC_I2S
+ select SND_SOC_ADAV80X
+ help
+ Say Y if you want to add support for ADAV80X SoC
audio.
+
config SND_BFIN_AD73311_SE
int "PF pin for AD73311L Chip Select"
depends on SND_BF5XX_SOC_AD73311
Modified: trunk/sound/soc/blackfin/Makefile (8607 => 8608)
--- trunk/sound/soc/blackfin/Makefile 2010-04-06 04:17:08 UTC
(rev 8607)
+++ trunk/sound/soc/blackfin/Makefile 2010-04-06 05:12:46 UTC
(rev 8608)
@@ -25,6 +25,7 @@
snd-adau1761-objs := bf5xx-adau1761.o
snd-adau1361-objs := bf5xx-adau1361.o
snd-adau1381-objs := bf5xx-adau1381.o
+snd-adav80x-objs := bf5xx-adav80x.o
obj-$(CONFIG_SND_BF5XX_SOC_AD183X) += snd-ad183x.o
obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
Added: trunk/sound/soc/blackfin/bf5xx-adav80x.c (0 => 8608)
--- trunk/sound/soc/blackfin/bf5xx-adav80x.c
(rev 0)
+++ trunk/sound/soc/blackfin/bf5xx-adav80x.c 2010-04-06
05:12:46 UTC (rev 8608)
@@ -0,0 +1,159 @@
+/*
+ * File: sound/soc/blackfin/bf5xx-adav80x.c
+ * Author: Yi Li <[email protected]>
+ *
+ * Created: Tue June 06 2010
+ * Description: board driver for ADAV80X sound chip
+ *
+ * Modified:
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public
License
+ * along with this program; if not, see the file COPYING, or
write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm_params.h>
+
+#include <asm/dma.h>
+#include <asm/portmux.h>
+#include <linux/gpio.h>
+#include "../codecs/adav80x.h"
+#include "bf5xx-sport.h"
+#include "bf5xx-i2s-pcm.h"
+#include "bf5xx-i2s.h"
+
+static struct snd_soc_card bf5xx_adav80x;
+
+static int bf5xx_adav80x_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 clk = 0;
+ int ret = 0;
+
+ pr_debug("%s rate %d format %x\n", __func__,
params_rate(params),
+ params_format(params));
+ /*
+ * If you are using a crystal source which frequency is
not 12MHz
+ * then modify the below case statement with frequency
of the crystal.
+ *
+ * If you are using the SPORT to generate clocking then
this is
+ * where to do it.
+ */
+
+ switch (params_rate(params)) {
+ case 8000:
+ case 16000:
+ case 48000:
+ case 96000:
+ case 11025:
+ case 22050:
+ case 44100:
+ clk = 12000000;
+ break;
+ }
+
+ /*
+ * CODEC is master for BCLK and LRC in this
configuration.
+ */
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
|
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+/*
+ ret = snd_soc_dai_set_sysclk(codec_dai, ADAV80X_SYSCLK,
clk,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+*/
+ return 0;
+}
+
+static struct snd_soc_ops bf5xx_adav80x_ops = {
+ .hw_params = bf5xx_adav80x_hw_params,
+};
+
+static struct snd_soc_dai_link bf5xx_adav80x_dai = {
+ .name = "adav80x",
+ .stream_name = "ADAV80X",
+ .cpu_dai = &bf5xx_i2s_dai,
+ .codec_dai = &adav80x_dai,
+ .ops = &bf5xx_adav80x_ops,
+};
+
+static struct snd_soc_card bf5xx_adav80x = {
+ .name = "bf5xx_adav80x",
+ .platform = &bf5xx_i2s_soc_platform,
+ .dai_link = &bf5xx_adav80x_dai,
+ .num_links = 1,
+};
+
+static struct snd_soc_device bf5xx_adav80x_snd_devdata = {
+ .card = &bf5xx_adav80x,
+ .codec_dev = &soc_codec_dev_adav80x,
+};
+
+static struct platform_device *bf5xx_adav80x_snd_device;
+
+static int __init bf5xx_adav80x_init(void)
+{
+ int ret;
+
+ bf5xx_adav80x_snd_device =
platform_device_alloc("soc-audio", -1);
+ if (!bf5xx_adav80x_snd_device)
+ return -ENOMEM;
+
+ platform_set_drvdata(bf5xx_adav80x_snd_device,
+ &bf5xx_adav80x_snd_devdata);
+ bf5xx_adav80x_snd_devdata.dev =
&bf5xx_adav80x_snd_device->dev;
+ ret = platform_device_add(bf5xx_adav80x_snd_device);
+
+ if (ret)
+ platform_device_put(bf5xx_adav80x_snd_device);
+
+ return ret;
+}
+
+static void __exit bf5xx_adav80x_exit(void)
+{
+ platform_device_unregister(bf5xx_adav80x_snd_device);
+}
+
+module_init(bf5xx_adav80x_init);
+module_exit(bf5xx_adav80x_exit);
+
+/* Module information */
+MODULE_AUTHOR("Yi Li");
+MODULE_DESCRIPTION("ALSA SoC ADAV80X Blackfin Board");
+MODULE_LICENSE("GPL");
Modified: trunk/sound/soc/codecs/Kconfig (8607 => 8608)
--- trunk/sound/soc/codecs/Kconfig 2010-04-06 04:17:08 UTC
(rev 8607)
+++ trunk/sound/soc/codecs/Kconfig 2010-04-06 05:12:46 UTC
(rev 8608)
@@ -21,6 +21,7 @@
select SND_SOC_ADAU1761 if I2C
select SND_SOC_ADAU1361 if I2C
select SND_SOC_ADAU1381 if I2C
+ select SND_SOC_ADAV80X if SND_SOC_I2C_AND_SPI
select SND_SOC_AK4104 if SPI_MASTER
select SND_SOC_AK4535 if I2C
select SND_SOC_AK4642 if I2C
@@ -115,6 +116,9 @@
config SND_SOC_ADAU1381
tristate
+config SND_SOC_ADAV80X
+ tristate
+
config SND_SOC_AK4104
tristate
Modified: trunk/sound/soc/codecs/Makefile (8607 => 8608)
--- trunk/sound/soc/codecs/Makefile 2010-04-06 04:17:08 UTC
(rev 8607)
+++ trunk/sound/soc/codecs/Makefile 2010-04-06 05:12:46 UTC
(rev 8608)
@@ -7,6 +7,7 @@
snd-soc-adau1371-objs := adau1371.o
snd-soc-adau1381-objs := adau1381.o
snd-soc-adau1761-objs := adau1761.o
+snd-soc-adav80x-objs := adav80x.o
snd-soc-ads117x-objs := ads117x.o
snd-soc-ak4104-objs := ak4104.o
snd-soc-ak4535-objs := ak4535.o
Added: trunk/sound/soc/codecs/adav80x.c (0 => 8608)
--- trunk/sound/soc/codecs/adav80x.c
(rev 0)
+++ trunk/sound/soc/codecs/adav80x.c 2010-04-06 05:12:46 UTC
(rev 8608)
@@ -0,0 +1,504 @@
+/*
+ * ADAV80X Audio Codec driver supporting ADAV801, ADAV803
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/soc-dapm.h>
+#include "adav80x.h"
+
+
+struct adav80x_priv {
+ struct snd_soc_codec codec;
+ u16 reg_cache[ADAV80X_NUM_REGS];
+};
+
+static struct snd_soc_codec *adav80x_codec;
+struct snd_soc_codec_device soc_codec_dev_adav80x;
+static int adav80x_register(struct adav80x_priv *adav80x, int
bus_type);
+static void adav80x_unregister(struct adav80x_priv *adav80x);
+
+static const struct snd_soc_dapm_widget adav80x_dapm_widgets[]
= {
+ SND_SOC_DAPM_DAC("DAC", "Playback", ADAV80X_DAC_CTRL1,
7, 1),
+ SND_SOC_DAPM_ADC("ADC", "Capture", ADAV80X_ADC_CTRL1, 5,
1),
+ SND_SOC_DAPM_SUPPLY("PLL_PWR", ADAV80X_PLL_CTRL1, 1, 1,
NULL, 0),
+};
+
+static const struct snd_soc_dapm_route audio_paths[] = {
+ { "DAC", NULL, "PLL_PWR" },
+ { "ADC", NULL, "PLL_PWR" },
+};
+
+/*
+ * ADAV80X volume/mute/de-emphasis etc. controls
+ */
+static const char *adav80x_deemp[] = {"None", "44.1kHz",
"32kHz", "48kHz"};
+
+static const struct soc_enum adav80x_deemp_enum =
+SOC_ENUM_SINGLE(ADAV80X_DAC_CTRL2, 0, 4, adav80x_deemp);
+
+static const struct snd_kcontrol_new adav80x_snd_controls[] = {
+ /* DAC volume control */
+ SOC_DOUBLE_R("DAC Volume", ADAV80X_DAC_L_VOL,
+ ADAV80X_DAC_R_VOL, 0, 0xFF, 0),
+ /* DAC peak volume detect, read clears it */
+ SOC_DOUBLE_R("DAC Peak Volume", ADAV80X_DAC_L_PEAK_VOL,
+ ADAV80X_DAC_R_PEAK_VOL, 0, 0x3F, 0),
+
+ /* ADC volume control */
+ SOC_DOUBLE_R("ADC Volume", ADAV80X_ADC_L_VOL,
+ ADAV80X_ADC_R_VOL, 0, 0xFF, 0),
+ /* ADC peak volume detect */
+ SOC_DOUBLE_R("ADC Peak Volume", ADAV80X_ADC_L_PEAK_VOL,
+ ADAV80X_ADC_R_PEAK_VOL, 0, 0x3F, 0),
+
+ /* ADC mute */
+ SOC_DOUBLE("ADC Switch", ADAV80X_ADC_CTRL1, 2, 3, 1, 1),
+
+ /* DAC mute */
+ SOC_DOUBLE("DAC Switch", ADAV80X_DAC_CTRL1, 0, 1, 1, 1),
+
+ /* ADC high-pass filter */
+ SOC_SINGLE("ADC High Pass Filter Switch",
ADAV80X_ADC_CTRL1, 6, 1, 0),
+
+ /* DAC de-emphasis */
+ SOC_ENUM("Playback Deemphasis", adav80x_deemp_enum),
+};
+
+/*
+ * DAI ops entries
+ */
+
+static int adav80x_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u8 rec_ctl = 0, playback_ctl = 0;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* use internal clock 1 */
+ playback_ctl |= 0x10;
+ rec_ctl |= 0x20;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ /* DAC word length depends on input, ADC need to set
word length */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ playback_ctl |= 0x1;
+ rec_ctl |= 0x1;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ playback_ctl |= 0x4;
+ rec_ctl |= 0x3;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ /* Use default - seems no polarity setting */
+ /* DAC control reg 1: CHSEL[1:0], POL[1:0] ? */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_write(codec, ADAV80X_PLAYBACK_CTRL,
playback_ctl);
+ snd_soc_write(codec, ADAV80X_REC_CTRL, rec_ctl);
+
+ return 0;
+}
+
+static int adav80x_hw_params(struct snd_pcm_substream
*substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ int word_len = 0;
+
+ struct snd_soc_pcm_runtime *rtd =
substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->card->codec;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ word_len = 3;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ word_len = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ word_len = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ word_len = 0;
+ break;
+ }
+
+
+ /* Playback port does not need to set word length? */
+
+ /* Record Port Control */
+ snd_soc_update_bits(codec, ADAV80X_REC_CTRL, 0x3<<2,
word_len<<2);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int adav80x_soc_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ return 0;
+}
+
+static int adav80x_soc_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+#else
+#define adav80x_soc_suspend NULL
+#define adav80x_soc_resume NULL
+#endif
+
+static int adav80x_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int reg;
+
+ reg = snd_soc_read(codec, ADAV80X_DAC_CTRL1);
+ reg = (mute > 0) ? reg & ~0x3 : reg | 0x3;
+ snd_soc_write(codec, ADAV80X_DAC_CTRL1, reg);
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops adav80x_dai_ops = {
+ .hw_params = adav80x_hw_params,
+ .set_fmt = adav80x_set_dai_fmt,
+ .digital_mute = adav80x_mute,
+};
+
+/* codec DAI instance */
+/* DAC sample rates: 32/44.1/48/96/192kHz, ADC sample reate:
48/96kHz - TBD */
+struct snd_soc_dai adav80x_dai = {
+ .name = "ADAV80X",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
SNDRV_PCM_FMTBIT_S24_LE,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
SNDRV_PCM_FMTBIT_S24_LE,
+ },
+ .ops = &adav80x_dai_ops,
+};
+EXPORT_SYMBOL_GPL(adav80x_dai);
+
+
+static int adav80x_probe(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev =
platform_get_drvdata(pdev);
+ struct snd_soc_codec *codec;
+ int ret = 0;
+
+ if (adav80x_codec == NULL) {
+ dev_err(&pdev->dev, "Codec device not
registered\n");
+ return -ENODEV;
+ }
+
+ socdev->card->codec = adav80x_codec;
+ codec = adav80x_codec;
+
+ /* register pcms */
+ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1,
SNDRV_DEFAULT_STR1);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to create pcms:
%d\n", ret);
+ goto pcm_err;
+ }
+
+ snd_soc_add_controls(codec, adav80x_snd_controls,
+
ARRAY_SIZE(adav80x_snd_controls));
+ snd_soc_dapm_new_controls(codec, adav80x_dapm_widgets,
+
ARRAY_SIZE(adav80x_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, audio_paths,
ARRAY_SIZE(audio_paths));
+
+pcm_err:
+ return ret;
+}
+
+/* power down chip */
+static int adav80x_remove(struct platform_device *pdev)
+{
+ struct snd_soc_device *socdev =
platform_get_drvdata(pdev);
+
+ snd_soc_free_pcms(socdev);
+ snd_soc_dapm_free(socdev);
+
+ return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_adav80x = {
+ .probe = adav80x_probe,
+ .remove = adav80x_remove,
+ .suspend = adav80x_soc_suspend,
+ .resume = adav80x_soc_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_adav80x);
+
+static int adav80x_register(struct adav80x_priv *adav80x, int
bus_type)
+{
+ int ret;
+ struct snd_soc_codec *codec = &adav80x->codec;
+
+ if (adav80x_codec) {
+ dev_err(codec->dev, "Another adav80x is
registered\n");
+ return -EINVAL;
+ }
+
+ mutex_init(&codec->mutex);
+ codec->private_data = adav80x;
+ codec->reg_cache = adav80x->reg_cache;
+ codec->reg_cache_size = ADAV80X_NUM_REGS;
+ codec->name = "ADAV80X";
+ codec->owner = THIS_MODULE;
+ codec->dai = &adav80x_dai;
+ codec->num_dai = 1;
+
+ INIT_LIST_HEAD(&codec->dapm_widgets);
+ INIT_LIST_HEAD(&codec->dapm_paths);
+
+ adav80x_dai.dev = codec->dev;
+ adav80x_codec = codec;
+
+
+ if (bus_type == SND_SOC_I2C)
+ /* addr(7-bit left shifted 1), data(8bit)*/
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8,
bus_type);
+ else
+ /* register format: addr(7bit), data(9bit) */
+ /* set spi bits_per_word to 8 instead of 16,
+ since addr need to be transfer before data */
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9,
bus_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to set cache I/O:
%d\n",
+ ret);
+ kfree(adav80x);
+ return ret;
+ }
+
+ ret = snd_soc_register_codec(codec);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to register codec:
%d\n", ret);
+ kfree(adav80x);
+ return ret;
+ }
+
+ ret = snd_soc_register_dai(&adav80x_dai);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to register DAI:
%d\n", ret);
+ snd_soc_unregister_codec(codec);
+ kfree(adav80x);
+ return ret;
+ }
+
+ /* default setting for adav80x */
+
+ /* These should be set on board level? */
+ /* DAC, ADC, ICLK clock source - XIN */
+ snd_soc_write(codec, ADAV80X_ICLK_CTRL1, 0x0);
+ snd_soc_write(codec, ADAV80X_ICLK_CTRL2, 0x0);
+
+ /* Power up XTAL oscillator */
+ snd_soc_write(codec, ADAV80X_PLL_CTRL1, 0xC);
+ /* Power down SYSCLK output, power down S/PDIF receiver
*/
+ snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x27);
+
+ /* Disable S/PDIF transmitter */
+ snd_soc_write(codec, ADAV80X_TX_CTRL, 0x0);
+
+ /* Datapath: ADC->record, AUX_IN->SRC->AUX_OUT */
+ snd_soc_write(codec, ADAV80X_DPATH_CTRL1, 0xC4);
+ /* Datapath: playback->DAC, DIR->DIT */
+ snd_soc_write(codec, ADAV80X_DPATH_CTRL2, 0x11);
+
+ /* Soft-mute SRC output */
+ snd_soc_write(codec, ADAV80X_GDELAY_MUTE, 0x80);
+
+ /* DAC: de-emphasis: none, MCLCK divider: 1, MCLK=256xFs
*/
+ snd_soc_write(codec, ADAV80X_DAC_CTRL2, 0x0);
+ /* Disable DAC zero flag */
+ snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6);
+ /* DAC: volume */
+ snd_soc_write(codec, ADAV80X_DAC_L_VOL, 0xFF);
+ snd_soc_write(codec, ADAV80X_DAC_R_VOL, 0xFF);
+
+ /* ADC: power up, unmute adc channles */
+ snd_soc_write(codec, ADAV80X_ADC_CTRL1, 0x0);
+ /* MCLCK divider: 1 */
+ snd_soc_write(codec, ADAV80X_ADC_CTRL2, 0x0);
+ /* ADC: volumn */
+ snd_soc_write(codec, ADAV80X_ADC_L_VOL, 0xFF);
+ snd_soc_write(codec, ADAV80X_ADC_R_VOL, 0xFF);
+
+ /* Disable ALC */
+ snd_soc_write(codec, ADAV80X_ALC_CTRL1, 0x0);
+
+ return 0;
+}
+
+static void adav80x_unregister(struct adav80x_priv *adav80x)
+{
+ snd_soc_unregister_dai(&adav80x_dai);
+ snd_soc_unregister_codec(&adav80x->codec);
+ kfree(adav80x);
+ adav80x_codec = NULL;
+}
+
+static int __devinit adav80x_bus_probe(struct device *dev, void
*ctrl_data,
+ int bus_type)
+{
+ struct snd_soc_codec *codec;
+ struct adav80x_priv *adav80x;
+
+ adav80x = kzalloc(sizeof(struct adav80x_priv),
GFP_KERNEL);
+ if (adav80x == NULL)
+ return -ENOMEM;
+
+ codec = &adav80x->codec;
+ codec->control_data = ctrl_data;
+ codec->dev = dev;
+
+ dev_set_drvdata(dev, adav80x);
+
+ return adav80x_register(adav80x, bus_type);
+}
+
+int adav80x_bus_remove(struct device *dev)
+{
+ struct adav80x_priv *adav80x = dev_get_drvdata(dev);
+
+ adav80x_unregister(adav80x);
+ return 0;
+}
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit adav80x_spi_probe(struct spi_device *spi)
+{
+ return adav80x_bus_probe(&spi->dev, spi, SND_SOC_SPI);
+}
+
+static int __devexit adav80x_spi_remove(struct spi_device *spi)
+{
+ return adav80x_bus_remove(&spi->dev);
+}
+
+static struct spi_driver adav80x_spi_driver = {
+ .driver = {
+ .name = "adav80x",
+ .owner = THIS_MODULE,
+ },
+ .probe = adav80x_spi_probe,
+ .remove = __devexit_p(adav80x_spi_remove),
+};
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static const struct i2c_device_id adav80x_id[] = {
+ { "adav803", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adav80x_id);
+
+static int __devinit adav80x_i2c_probe(struct i2c_client
*client,
+ const struct i2c_device_id *id)
+{
+ return adav80x_bus_probe(&client->dev, client,
SND_SOC_I2C);
+}
+
+static int __devexit adav80x_i2c_remove(struct i2c_client
*client)
+{
+ return adav80x_bus_remove(&client->dev);
+}
+
+static struct i2c_driver adav80x_i2c_driver = {
+ .driver = {
+ .name = "adav80x",
+ },
+ .probe = adav80x_i2c_probe,
+ .remove = __devexit_p(adav80x_i2c_remove),
+ .id_table = adav80x_id,
+};
+#endif
+
+static int __init adav80x_init(void)
+{
+ int ret;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&adav80x_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register ADAV80X I2C
driver: %d\n",
+ ret);
+ }
+#endif
+
+#if defined(CONFIG_SPI_MASTER)
+ ret = spi_register_driver(&adav80x_spi_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register ADAV80X SPI
driver: %d\n",
+ ret);
+ }
+#endif
+ return ret;
+}
+module_init(adav80x_init);
+
+static void __exit adav80x_exit(void)
+{
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&adav80x_spi_driver);
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&adav80x_i2c_driver);
+#endif
+}
+module_exit(adav80x_exit);
+
+MODULE_DESCRIPTION("ASoC adav80x driver");
+MODULE_AUTHOR("Yi Li");
+MODULE_LICENSE("GPL");
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits