]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branches 'topic/asoc' and 'topic/hda' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Mon, 13 Oct 2008 01:42:18 +0000 (03:42 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 13 Oct 2008 01:42:18 +0000 (03:42 +0200)
55 files changed:
include/sound/soc-dapm.h
sound/oss/ac97_codec.c
sound/pci/ac97/ac97_patch.c
sound/soc/at91/Kconfig
sound/soc/at91/Makefile
sound/soc/at91/at91-ssc.c
sound/soc/at91/eti_b1_wm8731.c [deleted file]
sound/soc/blackfin/Kconfig
sound/soc/blackfin/Makefile
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-ac97.c
sound/soc/blackfin/bf5xx-ad73311.c [new file with mode: 0644]
sound/soc/blackfin/bf5xx-i2s.c
sound/soc/blackfin/bf5xx-sport.h
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ac97.c
sound/soc/codecs/ad1980.c
sound/soc/codecs/ad73311.c [new file with mode: 0644]
sound/soc/codecs/ad73311.h [new file with mode: 0644]
sound/soc/codecs/ak4535.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/tlv320aic23.c [new file with mode: 0644]
sound/soc/codecs/tlv320aic23.h [new file with mode: 0644]
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/uda1380.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8510.h
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8753.h
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c
sound/soc/omap/Kconfig
sound/soc/omap/Makefile
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.h
sound/soc/omap/omap-pcm.c
sound/soc/omap/osk5912.c [new file with mode: 0644]
sound/soc/pxa/corgi.c
sound/soc/pxa/em-x270.c
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tosa.c
sound/soc/s3c24xx/neo1973_wm8753.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c

index c1b26fcc0b5c81e8950c77230675bf9314b2c2a8..ca699a3017f39563fc8f6b1d4dc36841e724f125 100644 (file)
@@ -240,6 +240,7 @@ int snd_soc_dapm_sys_add(struct device *dev);
 /* dapm audio pin control and status */
 int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin);
 int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin);
+int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin);
 int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin);
 int snd_soc_dapm_sync(struct snd_soc_codec *codec);
 
index b63839e8f9bd13c344c1efdcf6f45d7eff434b94..456a1b4d7832222b577d43e14dcde7b3baba2c9c 100644 (file)
@@ -30,7 +30,7 @@
  **************************************************************************
  *
  * History
- * May 02, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * May 02, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
  *     Removed non existant WM9700
  *     Added support for WM9705, WM9708, WM9709, WM9710, WM9711
  *     WM9712 and WM9717
index 6ce3cbe98a6a11d7212cfca404a01a73f6bf26bd..6e831aff1bd0e50ae3f38bc6484c0688b6084632 100644 (file)
@@ -476,7 +476,7 @@ static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
 }
 
 /*
- * May 2, 2003 Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * May 2, 2003 Liam Girdwood <lrg@slimlogic.co.uk>
  *  removed broken wolfson00 patch.
  *  added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
  */
index 905186502e0009039efc81919022b9d4ffe44a54..85a883299c2e5dc10c72182f1e6a2d903c15d7dd 100644 (file)
@@ -8,20 +8,3 @@ config SND_AT91_SOC
 
 config SND_AT91_SOC_SSC
        tristate
-
-config SND_AT91_SOC_ETI_B1_WM8731
-       tristate "SoC Audio support for WM8731-based Endrelia ETI-B1 boards"
-       depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
-       select SND_AT91_SOC_SSC
-       select SND_SOC_WM8731
-       help
-         Say Y if you want to add support for SoC audio on WM8731-based
-         Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
-
-config SND_AT91_SOC_ETI_SLAVE
-       bool "Run codec in slave Mode on Endrelia boards"
-       depends on SND_AT91_SOC_ETI_B1_WM8731
-       default n
-       help
-         Say Y if you want to run with the AT91 SSC generating the BCLK
-         and LRC signals on Endrelia boards.
index f23da17cc3288e0e11ac2e951ffcf2a14b3e87bd..b817f11df28669be198c3e3743a535b98e4a5aec 100644 (file)
@@ -4,8 +4,3 @@ snd-soc-at91-ssc-objs := at91-ssc.o
 
 obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
 obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
-
-# AT91 Machine Support
-snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
-
-obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
index a5b1a79ebffb5f72968ac949546bd59b1ae2dc5f..1b61cc4612618eedc61434fa23f559d54a0e4d3a 100644 (file)
@@ -5,7 +5,7 @@
  *         Endrelia Technologies Inc.
  *
  * Based on pxa2xx Platform drivers by
- * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  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
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
deleted file mode 100644 (file)
index 684781e..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * eti_b1_wm8731  --  SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
- *
- * Author:     Frank Mandarino <fmandarino@endrelia.com>
- *             Endrelia Technologies Inc.
- * Created:    Mar 29, 2006
- *
- * Based on corgi.c by:
- *
- * Copyright 2005 Wolfson Microelectronics PLC.
- * Copyright 2005 Openedhand Ltd.
- *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- *          Richard Purdie <richard@openedhand.com>
- *
- *  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/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/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-
-#include "../codecs/wm8731.h"
-#include "at91-pcm.h"
-#include "at91-ssc.h"
-
-#if 0
-#define        DBG(x...)       printk(KERN_INFO "eti_b1_wm8731: " x)
-#else
-#define        DBG(x...)
-#endif
-
-static struct clk *pck1_clk;
-static struct clk *pllb_clk;
-
-
-static int eti_b1_startup(struct snd_pcm_substream *substream)
-{
-       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;
-       int ret;
-
-       /* cpu clock is the AT91 master clock sent to the SSC */
-       ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
-               60000000, SND_SOC_CLOCK_IN);
-       if (ret < 0)
-               return ret;
-
-       /* codec system clock is supplied by PCK1, set to 12MHz */
-       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
-               12000000, SND_SOC_CLOCK_IN);
-       if (ret < 0)
-               return ret;
-
-       /* Start PCK1 clock. */
-       clk_enable(pck1_clk);
-       DBG("pck1 started\n");
-
-       return 0;
-}
-
-static void eti_b1_shutdown(struct snd_pcm_substream *substream)
-{
-       /* Stop PCK1 clock. */
-       clk_disable(pck1_clk);
-       DBG("pck1 stopped\n");
-}
-
-static int eti_b1_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;
-       int ret;
-
-#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
-       unsigned int rate;
-       int cmr_div, period;
-
-       /* set 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 cpu 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;
-
-       /*
-        * The SSC clock dividers depend on the sample rate.  The CMR.DIV
-        * field divides the system master clock MCK to drive the SSC TK
-        * signal which provides the codec BCLK.  The TCMR.PERIOD and
-        * RCMR.PERIOD fields further divide the BCLK signal to drive
-        * the SSC TF and RF signals which provide the codec DACLRC and
-        * ADCLRC clocks.
-        *
-        * The dividers were determined through trial and error, where a
-        * CMR.DIV value is chosen such that the resulting BCLK value is
-        * divisible, or almost divisible, by (2 * sample rate), and then
-        * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
-        */
-       rate = params_rate(params);
-
-       switch (rate) {
-       case 8000:
-               cmr_div = 25;   /* BCLK = 60MHz/(2*25) = 1.2MHz */
-               period = 74;    /* LRC = BCLK/(2*(74+1)) = 8000Hz */
-               break;
-       case 32000:
-               cmr_div = 7;    /* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
-               period = 66;    /* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
-               break;
-       case 48000:
-               cmr_div = 13;   /* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
-               period = 23;    /* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
-               break;
-       default:
-               printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
-               return -EINVAL;
-       }
-
-       /* set the MCK divider for BCLK */
-       ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
-       if (ret < 0)
-               return ret;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               /* set the BCLK divider for DACLRC */
-               ret = snd_soc_dai_set_clkdiv(cpu_dai,
-                                               AT91SSC_TCMR_PERIOD, period);
-       } else {
-               /* set the BCLK divider for ADCLRC */
-               ret = snd_soc_dai_set_clkdiv(cpu_dai,
-                                               AT91SSC_RCMR_PERIOD, period);
-       }
-       if (ret < 0)
-               return ret;
-
-#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
-       /*
-        * Codec in Master Mode.
-        */
-
-       /* 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;
-
-#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
-
-       return 0;
-}
-
-static struct snd_soc_ops eti_b1_ops = {
-       .startup = eti_b1_startup,
-       .hw_params = eti_b1_hw_params,
-       .shutdown = eti_b1_shutdown,
-};
-
-
-static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
-       SND_SOC_DAPM_MIC("Int Mic", NULL),
-       SND_SOC_DAPM_SPK("Ext Spk", NULL),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
-
-       /* speaker connected to LHPOUT */
-       {"Ext Spk", NULL, "LHPOUT"},
-
-       /* mic is connected to Mic Jack, with WM8731 Mic Bias */
-       {"MICIN", NULL, "Mic Bias"},
-       {"Mic Bias", NULL, "Int Mic"},
-};
-
-/*
- * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
- */
-static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
-{
-       DBG("eti_b1_wm8731_init() called\n");
-
-       /* Add specific widgets */
-       snd_soc_dapm_new_controls(codec, eti_b1_dapm_widgets,
-                                 ARRAY_SIZE(eti_b1_dapm_widgets));
-
-       /* Set up specific audio path interconnects */
-       snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon));
-
-       /* not connected */
-       snd_soc_dapm_disable_pin(codec, "RLINEIN");
-       snd_soc_dapm_disable_pin(codec, "LLINEIN");
-
-       /* always connected */
-       snd_soc_dapm_enable_pin(codec, "Int Mic");
-       snd_soc_dapm_enable_pin(codec, "Ext Spk");
-
-       snd_soc_dapm_sync(codec);
-
-       return 0;
-}
-
-static struct snd_soc_dai_link eti_b1_dai = {
-       .name = "WM8731",
-       .stream_name = "WM8731 PCM",
-       .cpu_dai = &at91_ssc_dai[1],
-       .codec_dai = &wm8731_dai,
-       .init = eti_b1_wm8731_init,
-       .ops = &eti_b1_ops,
-};
-
-static struct snd_soc_machine snd_soc_machine_eti_b1 = {
-       .name = "ETI_B1_WM8731",
-       .dai_link = &eti_b1_dai,
-       .num_links = 1,
-};
-
-static struct wm8731_setup_data eti_b1_wm8731_setup = {
-       .i2c_bus = 0,
-       .i2c_address = 0x1a,
-};
-
-static struct snd_soc_device eti_b1_snd_devdata = {
-       .machine = &snd_soc_machine_eti_b1,
-       .platform = &at91_soc_platform,
-       .codec_dev = &soc_codec_dev_wm8731,
-       .codec_data = &eti_b1_wm8731_setup,
-};
-
-static struct platform_device *eti_b1_snd_device;
-
-static int __init eti_b1_init(void)
-{
-       int ret;
-       struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-
-       if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
-               DBG("SSC1 memory region is busy\n");
-               return -EBUSY;
-       }
-
-       ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
-       if (!ssc->base) {
-               DBG("SSC1 memory ioremap failed\n");
-               ret = -ENOMEM;
-               goto fail_release_mem;
-       }
-
-       ssc->pid = AT91RM9200_ID_SSC1;
-
-       eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!eti_b1_snd_device) {
-               DBG("platform device allocation failed\n");
-               ret = -ENOMEM;
-               goto fail_io_unmap;
-       }
-
-       platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
-       eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
-
-       ret = platform_device_add(eti_b1_snd_device);
-       if (ret) {
-               DBG("platform device add failed\n");
-               platform_device_put(eti_b1_snd_device);
-               goto fail_io_unmap;
-       }
-
-       at91_set_A_periph(AT91_PIN_PB6, 0);     /* TF1 */
-       at91_set_A_periph(AT91_PIN_PB7, 0);     /* TK1 */
-       at91_set_A_periph(AT91_PIN_PB8, 0);     /* TD1 */
-       at91_set_A_periph(AT91_PIN_PB9, 0);     /* RD1 */
-/*     at91_set_A_periph(AT91_PIN_PB10, 0);*/  /* RK1 */
-       at91_set_A_periph(AT91_PIN_PB11, 0);    /* RF1 */
-
-       /*
-        * Set PCK1 parent to PLLB and its rate to 12 Mhz.
-        */
-       pllb_clk = clk_get(NULL, "pllb");
-       pck1_clk = clk_get(NULL, "pck1");
-
-       clk_set_parent(pck1_clk, pllb_clk);
-       clk_set_rate(pck1_clk, 12000000);
-
-       DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
-
-       /* assign the GPIO pin to PCK1 */
-       at91_set_B_periph(AT91_PIN_PA24, 0);
-
-#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
-       printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
-#else
-       printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
-#endif
-       return ret;
-
-fail_io_unmap:
-       iounmap(ssc->base);
-fail_release_mem:
-       release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
-       return ret;
-}
-
-static void __exit eti_b1_exit(void)
-{
-       struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
-
-       clk_put(pck1_clk);
-       clk_put(pllb_clk);
-
-       platform_device_unregister(eti_b1_snd_device);
-
-       iounmap(ssc->base);
-       release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
-}
-
-module_init(eti_b1_init);
-module_exit(eti_b1_exit);
-
-/* Module information */
-MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
-MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
-MODULE_LICENSE("GPL");
index f98331d099e7f05379b70dd1080f4477a4c7f39c..dc006206f622d043d4257162e71466f3b77bf0fb 100644 (file)
@@ -17,6 +17,22 @@ config SND_BF5XX_SOC_SSM2602
        help
          Say Y if you want to add support for SoC audio on BF527-EZKIT.
 
+config SND_BF5XX_SOC_AD73311
+       tristate "SoC AD73311 Audio support for Blackfin"
+       depends on SND_BF5XX_I2S
+       select SND_BF5XX_SOC_I2S
+       select SND_SOC_AD73311
+       help
+         Say Y if you want to add support for AD73311 codec on Blackfin.
+
+config SND_BFIN_AD73311_SE
+       int "PF pin for AD73311L Chip Select"
+       depends on SND_BF5XX_SOC_AD73311
+       default 4
+       help
+         Enter the GPIO used to control AD73311's SE pin. Acceptable
+         values are 0 to 7
+
 config SND_BF5XX_AC97
        tristate "SoC AC97 Audio for the ADI BF5xx chip"
        depends on BLACKFIN && SND_SOC
index 9ea8bd9e0ba3448471fdbfc3b52b7d76c27eb9b8..97bb37a6359c9b72816424658fdab4636c76fa36 100644 (file)
@@ -14,7 +14,8 @@ obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
 # Blackfin Machine Support
 snd-ad1980-objs := bf5xx-ad1980.o
 snd-ssm2602-objs := bf5xx-ssm2602.o
-
+snd-ad73311-objs := bf5xx-ad73311.o
 
 obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
 obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
+obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
index 51f4907c4831af2f86fb04aa4a3c7fa5b10e22d2..25e50d2ea1ec321d4140295f6d6ce587d79f0a9a 100644 (file)
@@ -56,6 +56,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
                sport->tx_pos += runtime->period_size;
                if (sport->tx_pos >= runtime->buffer_size)
                        sport->tx_pos %= runtime->buffer_size;
+               sport->tx_delay_pos = sport->tx_pos;
        } else {
                bf5xx_ac97_to_pcm(
                        (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
@@ -72,7 +73,15 @@ static void bf5xx_dma_irq(void *data)
        struct snd_pcm_substream *pcm = data;
 #if defined(CONFIG_SND_MMAP_SUPPORT)
        struct snd_pcm_runtime *runtime = pcm->runtime;
+       struct sport_device *sport = runtime->private_data;
        bf5xx_mmap_copy(pcm, runtime->period_size);
+       if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (sport->once == 0) {
+                       snd_pcm_period_elapsed(pcm);
+                       bf5xx_mmap_copy(pcm, runtime->period_size);
+                       sport->once = 1;
+               }
+       }
 #endif
        snd_pcm_period_elapsed(pcm);
 }
@@ -114,6 +123,10 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
 
 static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+       memset(runtime->dma_area, 0, runtime->buffer_size);
        snd_pcm_lib_free_pages(substream);
        return 0;
 }
@@ -127,16 +140,11 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
         * SPORT working in TMD mode(include AC97).
         */
 #if defined(CONFIG_SND_MMAP_SUPPORT)
-       size_t size = bf5xx_pcm_hardware.buffer_bytes_max
-                       * sizeof(struct ac97_frame) / 4;
-       /*clean up intermediate buffer*/
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               memset(sport->tx_dma_buf, 0, size);
                sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
                sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
                        runtime->period_size * sizeof(struct ac97_frame));
        } else {
-               memset(sport->rx_dma_buf, 0, size);
                sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
                sport_config_rx_dma(sport, sport->rx_dma_buf, runtime->periods,
                        runtime->period_size * sizeof(struct ac97_frame));
@@ -164,8 +172,12 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        pr_debug("%s enter\n", __func__);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       bf5xx_mmap_copy(substream, runtime->period_size);
+                       snd_pcm_period_elapsed(substream);
+                       sport->tx_delay_pos = 0;
                        sport_tx_start(sport);
+               }
                else
                        sport_rx_start(sport);
                break;
@@ -198,7 +210,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
 
 #if defined(CONFIG_SND_MMAP_SUPPORT)
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               curr = sport->tx_pos;
+               curr = sport->tx_delay_pos;
        else
                curr = sport->rx_pos;
 #else
@@ -237,6 +249,21 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
        return ret;
 }
 
+static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct sport_device *sport = runtime->private_data;
+
+       pr_debug("%s enter\n", __func__);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               sport->once = 0;
+               memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
+       } else
+               memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
+
+       return 0;
+}
+
 #ifdef CONFIG_SND_MMAP_SUPPORT
 static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
        struct vm_area_struct *vma)
@@ -272,6 +299,7 @@ static      int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
 
 struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
        .open           = bf5xx_pcm_open,
+       .close          = bf5xx_pcm_close,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = bf5xx_pcm_hw_params,
        .hw_free        = bf5xx_pcm_hw_free,
index c782e311fd56a38d9c0ad04ccf11e82bd851c4f7..5e5aafb6485f0bce67bf211a24bc475db69f686b 100644 (file)
@@ -128,7 +128,6 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
        int nextfrag = sport_tx_curr_frag(sport);
        struct ac97_frame *nextwrite;
 
-       sport_incfrag(sport, &nextfrag, 1);
        sport_incfrag(sport, &nextfrag, 1);
 
        nextwrite = (struct ac97_frame *)(sport->tx_buf + \
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
new file mode 100644 (file)
index 0000000..622c9b9
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * File:         sound/soc/blackfin/bf5xx-ad73311.c
+ * Author:       Cliff Cai <Cliff.Cai@analog.com>
+ *
+ * Created:      Thur Sep 25 2008
+ * Description:  Board driver for ad73311 sound chip
+ *
+ * Modified:
+ *               Copyright 2008 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 <linux/delay.h>
+#include <linux/gpio.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/blackfin.h>
+#include <asm/cacheflush.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#include "../codecs/ad73311.h"
+#include "bf5xx-sport.h"
+#include "bf5xx-i2s-pcm.h"
+#include "bf5xx-i2s.h"
+
+#if CONFIG_SND_BF5XX_SPORT_NUM == 0
+#define bfin_write_SPORT_TCR1  bfin_write_SPORT0_TCR1
+#define bfin_read_SPORT_TCR1   bfin_read_SPORT0_TCR1
+#define bfin_write_SPORT_TCR2  bfin_write_SPORT0_TCR2
+#define bfin_write_SPORT_TX16  bfin_write_SPORT0_TX16
+#define bfin_read_SPORT_STAT   bfin_read_SPORT0_STAT
+#else
+#define bfin_write_SPORT_TCR1  bfin_write_SPORT1_TCR1
+#define bfin_read_SPORT_TCR1   bfin_read_SPORT1_TCR1
+#define bfin_write_SPORT_TCR2  bfin_write_SPORT1_TCR2
+#define bfin_write_SPORT_TX16  bfin_write_SPORT1_TX16
+#define bfin_read_SPORT_STAT   bfin_read_SPORT1_STAT
+#endif
+
+#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
+
+static struct snd_soc_machine bf5xx_ad73311;
+
+static int snd_ad73311_startup(void)
+{
+       pr_debug("%s enter\n", __func__);
+
+       /* Pull up SE pin on AD73311L */
+       gpio_set_value(GPIO_SE, 1);
+       return 0;
+}
+
+static int snd_ad73311_configure(void)
+{
+       unsigned short ctrl_regs[6];
+       unsigned short status = 0;
+       int count = 0;
+
+       /* DMCLK = MCLK = 16.384 MHz
+        * SCLK = DMCLK/8 = 2.048 MHz
+        * Sample Rate = DMCLK/2048  = 8 KHz
+        */
+       ctrl_regs[0] = AD_CONTROL | AD_WRITE | CTRL_REG_B | REGB_MCDIV(0) | \
+                       REGB_SCDIV(0) | REGB_DIRATE(0);
+       ctrl_regs[1] = AD_CONTROL | AD_WRITE | CTRL_REG_C | REGC_PUDEV | \
+                       REGC_PUADC | REGC_PUDAC | REGC_PUREF | REGC_REFUSE ;
+       ctrl_regs[2] = AD_CONTROL | AD_WRITE | CTRL_REG_D | REGD_OGS(2) | \
+                       REGD_IGS(2);
+       ctrl_regs[3] = AD_CONTROL | AD_WRITE | CTRL_REG_E | REGE_DA(0x1f);
+       ctrl_regs[4] = AD_CONTROL | AD_WRITE | CTRL_REG_F | REGF_SEEN ;
+       ctrl_regs[5] = AD_CONTROL | AD_WRITE | CTRL_REG_A | REGA_MODE_DATA;
+
+       local_irq_disable();
+       snd_ad73311_startup();
+       udelay(1);
+
+       bfin_write_SPORT_TCR1(TFSR);
+       bfin_write_SPORT_TCR2(0xF);
+       SSYNC();
+
+       /* SPORT Tx Register is a 8 x 16 FIFO, all the data can be put to
+        * FIFO before enable SPORT to transfer the data
+        */
+       for (count = 0; count < 6; count++)
+               bfin_write_SPORT_TX16(ctrl_regs[count]);
+       SSYNC();
+       bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() | TSPEN);
+       SSYNC();
+
+       /* When TUVF is set, the data is already send out */
+       while (!(status & TUVF) && count++ < 10000) {
+               udelay(1);
+               status = bfin_read_SPORT_STAT();
+               SSYNC();
+       }
+       bfin_write_SPORT_TCR1(bfin_read_SPORT_TCR1() & ~TSPEN);
+       SSYNC();
+       local_irq_enable();
+
+       if (count == 10000) {
+               printk(KERN_ERR "ad73311: failed to configure codec\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int bf5xx_probe(struct platform_device *pdev)
+{
+       int err;
+       if (gpio_request(GPIO_SE, "AD73311_SE")) {
+               printk(KERN_ERR "%s: Failed ro request GPIO_%d\n", __func__, GPIO_SE);
+               return -EBUSY;
+       }
+
+       gpio_direction_output(GPIO_SE, 0);
+
+       err = snd_ad73311_configure();
+       if (err < 0)
+               return -EFAULT;
+
+       return 0;
+}
+
+static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+       pr_debug("%s enter\n", __func__);
+       cpu_dai->private_data = sport_handle;
+       return 0;
+}
+
+static int bf5xx_ad73311_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->dai->cpu_dai;
+       int ret = 0;
+
+       pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
+               params_format(params));
+
+       /* set cpu DAI configuration */
+       ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+
+static struct snd_soc_ops bf5xx_ad73311_ops = {
+       .startup = bf5xx_ad73311_startup,
+       .hw_params = bf5xx_ad73311_hw_params,
+};
+
+static struct snd_soc_dai_link bf5xx_ad73311_dai = {
+       .name = "ad73311",
+       .stream_name = "AD73311",
+       .cpu_dai = &bf5xx_i2s_dai,
+       .codec_dai = &ad73311_dai,
+       .ops = &bf5xx_ad73311_ops,
+};
+
+static struct snd_soc_machine bf5xx_ad73311 = {
+       .name = "bf5xx_ad73311",
+       .probe = bf5xx_probe,
+       .dai_link = &bf5xx_ad73311_dai,
+       .num_links = 1,
+};
+
+static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
+       .machine = &bf5xx_ad73311,
+       .platform = &bf5xx_i2s_soc_platform,
+       .codec_dev = &soc_codec_dev_ad73311,
+};
+
+static struct platform_device *bf52x_ad73311_snd_device;
+
+static int __init bf5xx_ad73311_init(void)
+{
+       int ret;
+
+       pr_debug("%s enter\n", __func__);
+       bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!bf52x_ad73311_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
+       bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev;
+       ret = platform_device_add(bf52x_ad73311_snd_device);
+
+       if (ret)
+               platform_device_put(bf52x_ad73311_snd_device);
+
+       return ret;
+}
+
+static void __exit bf5xx_ad73311_exit(void)
+{
+       pr_debug("%s enter\n", __func__);
+       platform_device_unregister(bf52x_ad73311_snd_device);
+}
+
+module_init(bf5xx_ad73311_init);
+module_exit(bf5xx_ad73311_exit);
+
+/* Module information */
+MODULE_AUTHOR("Cliff Cai");
+MODULE_DESCRIPTION("ALSA SoC AD73311 Blackfin");
+MODULE_LICENSE("GPL");
+
index 43a4092eeb89f0d623df6b5fa0dda8b6a24d6bb8..827587f08180de31774c0fdc79817189d2bf605b 100644 (file)
@@ -70,6 +70,13 @@ static struct sport_param sport_params[2] = {
        }
 };
 
+static u16 sport_req[][7] = {
+               { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+                 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
+               { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+                 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
+};
+
 static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
@@ -78,6 +85,14 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        /* interface format:support I2S,slave mode */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
+               bf5xx_i2s.tcr1 |= TFSR | TCKFE;
+               bf5xx_i2s.rcr1 |= RFSR | RCKFE;
+               bf5xx_i2s.tcr2 |= TSFSE;
+               bf5xx_i2s.rcr2 |= RSFSE;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               bf5xx_i2s.tcr1 |= TFSR;
+               bf5xx_i2s.rcr1 |= RFSR;
                break;
        case SND_SOC_DAIFMT_LEFT_J:
                ret = -EINVAL;
@@ -127,14 +142,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_FORMAT_S16_LE:
                bf5xx_i2s.tcr2 |= 15;
                bf5xx_i2s.rcr2 |= 15;
+               sport_handle->wdsize = 2;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
                bf5xx_i2s.tcr2 |= 23;
                bf5xx_i2s.rcr2 |= 23;
+               sport_handle->wdsize = 3;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                bf5xx_i2s.tcr2 |= 31;
                bf5xx_i2s.rcr2 |= 31;
+               sport_handle->wdsize = 4;
                break;
        }
 
@@ -145,17 +163,17 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
                 * need to configure both of them at the time when the first
                 * stream is opened.
                 *
-                * CPU DAI format:I2S, slave mode.
+                * CPU DAI:slave mode.
                 */
-               ret = sport_config_rx(sport_handle, RFSR | RCKFE,
-                                     RSFSE|bf5xx_i2s.rcr2, 0, 0);
+               ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
+                                     bf5xx_i2s.rcr2, 0, 0);
                if (ret) {
                        pr_err("SPORT is busy!\n");
                        return -EBUSY;
                }
 
-               ret = sport_config_tx(sport_handle, TFSR | TCKFE,
-                                     TSFSE|bf5xx_i2s.tcr2, 0, 0);
+               ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
+                                     bf5xx_i2s.tcr2, 0, 0);
                if (ret) {
                        pr_err("SPORT is busy!\n");
                        return -EBUSY;
@@ -174,13 +192,6 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
 static int bf5xx_i2s_probe(struct platform_device *pdev,
                           struct snd_soc_dai *dai)
 {
-       u16 sport_req[][7] = {
-               { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
-                 P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0},
-               { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
-                 P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0},
-       };
-
        pr_debug("%s enter\n", __func__);
        if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
                pr_err("Requesting Peripherals failed\n");
@@ -198,6 +209,13 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
        return 0;
 }
 
+static void bf5xx_i2s_remove(struct platform_device *pdev,
+                          struct snd_soc_dai *dai)
+{
+       pr_debug("%s enter\n", __func__);
+       peripheral_free_list(&sport_req[sport_num][0]);
+}
+
 #ifdef CONFIG_PM
 static int bf5xx_i2s_suspend(struct platform_device *dev,
                             struct snd_soc_dai *dai)
@@ -263,15 +281,16 @@ struct snd_soc_dai bf5xx_i2s_dai = {
        .id = 0,
        .type = SND_SOC_DAI_I2S,
        .probe = bf5xx_i2s_probe,
+       .remove = bf5xx_i2s_remove,
        .suspend = bf5xx_i2s_suspend,
        .resume = bf5xx_i2s_resume,
        .playback = {
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = BF5XX_I2S_RATES,
                .formats = BF5XX_I2S_FORMATS,},
        .capture = {
-               .channels_min = 2,
+               .channels_min = 1,
                .channels_max = 2,
                .rates = BF5XX_I2S_RATES,
                .formats = BF5XX_I2S_FORMATS,},
index 4c163454bbf8410570e2f8e43cf06da224cae66e..fcadcc081f7fe4994a2dc3dbc0514656c7c6cd06 100644 (file)
@@ -123,6 +123,8 @@ struct sport_device {
        int rx_pos;
        unsigned int tx_buffer_size;
        unsigned int rx_buffer_size;
+       int tx_delay_pos;
+       int once;
 #endif
        void *private_data;
 };
index e0b9869df0f107ed2876a2a8b9c8893ff8740cd5..4975d8573e4f51414cf2a24c03943c56fd1eeb51 100644 (file)
@@ -3,9 +3,11 @@ config SND_SOC_ALL_CODECS
        depends on I2C
        select SPI
        select SPI_MASTER
+       select SND_SOC_AD73311
        select SND_SOC_AK4535
        select SND_SOC_CS4270
        select SND_SOC_SSM2602
+       select SND_SOC_TLV320AIC23
        select SND_SOC_TLV320AIC26
        select SND_SOC_TLV320AIC3X
        select SND_SOC_UDA1380
@@ -34,6 +36,9 @@ config SND_SOC_AC97_CODEC
 config SND_SOC_AD1980
        tristate
 
+config SND_SOC_AD73311
+       tristate
+
 config SND_SOC_AK4535
        tristate
 
@@ -58,9 +63,13 @@ config SND_SOC_CS4270_VD33_ERRATA
 config SND_SOC_SSM2602
        tristate
 
+config SND_SOC_TLV320AIC23
+       tristate
+       depends on I2C
+
 config SND_SOC_TLV320AIC26
        tristate "TI TLV320AIC26 Codec support"
-       depends on SND_SOC && SPI
+       depends on SPI
 
 config SND_SOC_TLV320AIC3X
        tristate
index f977978a3409e2c19584f1819ddde1989bd9aeef..90f0a585fc70e1f5a4d9a9be1b8514a22100917a 100644 (file)
@@ -1,8 +1,10 @@
 snd-soc-ac97-objs := ac97.o
 snd-soc-ad1980-objs := ad1980.o
+snd-soc-ad73311-objs := ad73311.o
 snd-soc-ak4535-objs := ak4535.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-ssm2602-objs := ssm2602.o
+snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
 snd-soc-uda1380-objs := uda1380.o
@@ -20,9 +22,11 @@ snd-soc-wm9713-objs := wm9713.o
 
 obj-$(CONFIG_SND_SOC_AC97_CODEC)       += snd-soc-ac97.o
 obj-$(CONFIG_SND_SOC_AD1980)   += snd-soc-ad1980.o
+obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
 obj-$(CONFIG_SND_SOC_AK4535)   += snd-soc-ak4535.o
 obj-$(CONFIG_SND_SOC_CS4270)   += snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
+obj-$(CONFIG_SND_SOC_TLV320AIC23)      += snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC26)      += snd-soc-tlv320aic26.o
 obj-$(CONFIG_SND_SOC_TLV320AIC3X)      += snd-soc-tlv320aic3x.o
 obj-$(CONFIG_SND_SOC_UDA1380)  += snd-soc-uda1380.o
index 61fd96ca7bc782588e17655ebd8dd12887837e75..bd1ebdc6c86ce0e6ef021139f5ac10b93831f4d4 100644 (file)
@@ -2,8 +2,7 @@
  * ac97.c  --  ALSA Soc AC97 codec support
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  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
index 4e09c1f2c063a3f335188d043314ff0dd525f8ac..1397b8e06c0b41eda7002815a276baba8f3ea035 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <sound/core.h>
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
new file mode 100644 (file)
index 0000000..37af860
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * ad73311.c  --  ALSA Soc AD73311 codec support
+ *
+ * Copyright:  Analog Device Inc.
+ * Author:     Cliff Cai <cliff.cai@analog.com>
+ *
+ *  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.
+ *
+ *  Revision history
+ *    25th Sep 2008   Initial version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "ad73311.h"
+
+struct snd_soc_dai ad73311_dai = {
+       .name = "AD73311",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+};
+EXPORT_SYMBOL_GPL(ad73311_dai);
+
+static int ad73311_soc_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+       mutex_init(&codec->mutex);
+       codec->name = "AD73311";
+       codec->owner = THIS_MODULE;
+       codec->dai = &ad73311_dai;
+       codec->num_dai = 1;
+       socdev->codec = codec;
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "ad73311: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "ad73311: failed to register card\n");
+               goto register_err;
+       }
+
+       return ret;
+
+register_err:
+       snd_soc_free_pcms(socdev);
+pcm_err:
+       kfree(socdev->codec);
+       socdev->codec = NULL;
+       return ret;
+}
+
+static int ad73311_soc_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec == NULL)
+               return 0;
+       snd_soc_free_pcms(socdev);
+       kfree(codec);
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_ad73311 = {
+       .probe =        ad73311_soc_probe,
+       .remove =       ad73311_soc_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
+
+MODULE_DESCRIPTION("ASoC ad73311 driver");
+MODULE_AUTHOR("Cliff Cai ");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h
new file mode 100644 (file)
index 0000000..507ce0c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * File:         sound/soc/codec/ad73311.h
+ * Based on:
+ * Author:       Cliff Cai <cliff.cai@analog.com>
+ *
+ * Created:      Thur Sep 25, 2008
+ * Description:  definitions for AD73311 registers
+ *
+ *
+ * Modified:
+ *               Copyright 2006 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
+ */
+
+#ifndef __AD73311_H__
+#define __AD73311_H__
+
+#define AD_CONTROL     0x8000
+#define AD_DATA                0x0000
+#define AD_READ                0x4000
+#define AD_WRITE       0x0000
+
+/* Control register A */
+#define CTRL_REG_A     (0 << 8)
+
+#define REGA_MODE_PRO  0x00
+#define REGA_MODE_DATA 0x01
+#define REGA_MODE_MIXED        0x03
+#define REGA_DLB               0x04
+#define REGA_SLB               0x08
+#define REGA_DEVC(x)           ((x & 0x7) << 4)
+#define REGA_RESET             0x80
+
+/* Control register B */
+#define CTRL_REG_B     (1 << 8)
+
+#define REGB_DIRATE(x) (x & 0x3)
+#define REGB_SCDIV(x)  ((x & 0x3) << 2)
+#define REGB_MCDIV(x)  ((x & 0x7) << 4)
+#define REGB_CEE               (1 << 7)
+
+/* Control register C */
+#define CTRL_REG_C     (2 << 8)
+
+#define REGC_PUDEV             (1 << 0)
+#define REGC_PUADC             (1 << 3)
+#define REGC_PUDAC             (1 << 4)
+#define REGC_PUREF             (1 << 5)
+#define REGC_REFUSE            (1 << 6)
+
+/* Control register D */
+#define CTRL_REG_D     (3 << 8)
+
+#define REGD_IGS(x)            (x & 0x7)
+#define REGD_RMOD              (1 << 3)
+#define REGD_OGS(x)            ((x & 0x7) << 4)
+#define REGD_MUTE              (x << 7)
+
+/* Control register E */
+#define CTRL_REG_E     (4 << 8)
+
+#define REGE_DA(x)             (x & 0x1f)
+#define REGE_IBYP              (1 << 5)
+
+/* Control register F */
+#define CTRL_REG_F     (5 << 8)
+
+#define REGF_SEEN              (1 << 5)
+#define REGF_INV               (1 << 6)
+#define REGF_ALB               (1 << 7)
+
+extern struct snd_soc_dai ad73311_dai;
+extern struct snd_soc_codec_device soc_codec_dev_ad73311;
+#endif
index 088cf99277203ff4d729d722629ed8cf222f2cb0..2a89b5888e11c33bdedf44b817e0c61282b95d0d 100644 (file)
@@ -28,7 +28,6 @@
 
 #include "ak4535.h"
 
-#define AUDIO_NAME "ak4535"
 #define AK4535_VERSION "0.3"
 
 struct snd_soc_codec_device soc_codec_dev_ak4535;
index 940ce1c3522e007733c9bfc9066d822f21727077..44ef0dacd564701b3999316d9c2e21c5b41ec4a8 100644 (file)
@@ -42,7 +42,6 @@
 
 #include "ssm2602.h"
 
-#define AUDIO_NAME "ssm2602"
 #define SSM2602_VERSION "0.1"
 
 struct snd_soc_codec_device soc_codec_dev_ssm2602;
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
new file mode 100644 (file)
index 0000000..bac7815
--- /dev/null
@@ -0,0 +1,714 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver
+ *
+ * Author:      Arun KS, <arunks@mistralsolutions.com>
+ * Copyright:   (C) 2008 Mistral Solutions Pvt Ltd.,
+ *
+ * Based on sound/soc/codecs/wm8731.c by Richard Purdie
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Notes:
+ *  The AIC23 is a driver for a low power stereo audio
+ *  codec tlv320aic23
+ *
+ *  The machine layer should disable unsupported inputs/outputs by
+ *  snd_soc_dapm_disable_pin(codec, "LHPOUT"), etc.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.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 <sound/tlv.h>
+#include <sound/initval.h>
+
+#include "tlv320aic23.h"
+
+#define AIC23_VERSION "0.1"
+
+struct tlv320aic23_srate_reg_info {
+       u32 sample_rate;
+       u8 control;             /* SR3, SR2, SR1, SR0 and BOSR */
+       u8 divider;             /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
+};
+
+/*
+ * AIC23 register cache
+ */
+static const u16 tlv320aic23_reg[] = {
+       0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */
+       0x001A, 0x0004, 0x0007, 0x0001, /* 4 */
+       0x0020, 0x0000, 0x0000, 0x0000, /* 8 */
+       0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
+};
+
+/*
+ * read tlv320aic23 register cache
+ */
+static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
+                                                     *codec, unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= ARRAY_SIZE(tlv320aic23_reg))
+               return -1;
+       return cache[reg];
+}
+
+/*
+ * write tlv320aic23 register cache
+ */
+static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
+                                              u8 reg, u16 value)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= ARRAY_SIZE(tlv320aic23_reg))
+               return;
+       cache[reg] = value;
+}
+
+/*
+ * write to the tlv320aic23 register space
+ */
+static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
+                            unsigned int value)
+{
+
+       u8 data;
+
+       /* TLV320AIC23 has 7 bit address and 9 bits of data
+        * so we need to switch one data bit into reg and rest
+        * of data into val
+        */
+
+       if ((reg < 0 || reg > 9) && (reg != 15)) {
+               printk(KERN_WARNING "%s Invalid register R%d\n", __func__, reg);
+               return -1;
+       }
+
+       data = (reg << 1) | (value >> 8 & 0x01);
+
+       tlv320aic23_write_reg_cache(codec, reg, value);
+
+       if (codec->hw_write(codec->control_data, data,
+                           (value & 0xff)) == 0)
+               return 0;
+
+       printk(KERN_ERR "%s cannot write %03x to register R%d\n", __func__,
+              value, reg);
+
+       return -EIO;
+}
+
+static const char *rec_src_text[] = { "Line", "Mic" };
+static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
+
+static const struct soc_enum rec_src_enum =
+       SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
+
+static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls =
+SOC_DAPM_ENUM("Input Select", rec_src_enum);
+
+static const struct soc_enum tlv320aic23_rec_src =
+       SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text);
+static const struct soc_enum tlv320aic23_deemph =
+       SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text);
+
+static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0);
+static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0);
+static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0);
+
+static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       u16 val, reg;
+
+       val = (ucontrol->value.integer.value[0] & 0x07);
+
+       /* linear conversion to userspace
+       * 000   =       -6db
+       * 001   =       -9db
+       * 010   =       -12db
+       * 011   =       -18db (Min)
+       * 100   =       0db (Max)
+       */
+       val = (val >= 4) ? 4  : (3 - val);
+
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
+       tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
+
+       return 0;
+}
+
+static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       u16 val;
+
+       val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
+       val = val >> 6;
+       val = (val >= 4) ? 4  : (3 -  val);
+       ucontrol->value.integer.value[0] = val;
+       return 0;
+
+}
+
+#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+       .tlv.p = (tlv_array), \
+       .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
+       .put = snd_soc_tlv320aic23_put_volsw, \
+       .private_value =  SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
+       SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
+                        TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
+       SOC_SINGLE("Digital Playback Switch", TLV320AIC23_DIGT, 3, 1, 1),
+       SOC_DOUBLE_R("Line Input Switch", TLV320AIC23_LINVOL,
+                    TLV320AIC23_RINVOL, 7, 1, 0),
+       SOC_DOUBLE_R_TLV("Line Input Volume", TLV320AIC23_LINVOL,
+                        TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
+       SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
+       SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
+       SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
+                                 6, 4, 0, sidetone_vol_tlv),
+       SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
+};
+
+/* add non dapm controls */
+static int tlv320aic23_add_controls(struct snd_soc_codec *codec)
+{
+
+       int err, i;
+
+       for (i = 0; i < ARRAY_SIZE(tlv320aic23_snd_controls); i++) {
+               err = snd_ctl_add(codec->card,
+                                 snd_soc_cnew(&tlv320aic23_snd_controls[i],
+                                              codec, NULL));
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+
+}
+
+/* PGA Mixer controls for Line and Mic switch */
+static const struct snd_kcontrol_new tlv320aic23_output_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line Bypass Switch", TLV320AIC23_ANLG, 3, 1, 0),
+       SOC_DAPM_SINGLE("Mic Sidetone Switch", TLV320AIC23_ANLG, 5, 1, 0),
+       SOC_DAPM_SINGLE("Playback Switch", TLV320AIC23_ANLG, 4, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
+       SND_SOC_DAPM_DAC("DAC", "Playback", TLV320AIC23_PWR, 3, 1),
+       SND_SOC_DAPM_ADC("ADC", "Capture", TLV320AIC23_PWR, 2, 1),
+       SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
+                        &tlv320aic23_rec_src_mux_controls),
+       SND_SOC_DAPM_MIXER("Output Mixer", TLV320AIC23_PWR, 4, 1,
+                          &tlv320aic23_output_mixer_controls[0],
+                          ARRAY_SIZE(tlv320aic23_output_mixer_controls)),
+       SND_SOC_DAPM_PGA("Line Input", TLV320AIC23_PWR, 0, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Mic Input", TLV320AIC23_PWR, 1, 1, NULL, 0),
+
+       SND_SOC_DAPM_OUTPUT("LHPOUT"),
+       SND_SOC_DAPM_OUTPUT("RHPOUT"),
+       SND_SOC_DAPM_OUTPUT("LOUT"),
+       SND_SOC_DAPM_OUTPUT("ROUT"),
+
+       SND_SOC_DAPM_INPUT("LLINEIN"),
+       SND_SOC_DAPM_INPUT("RLINEIN"),
+
+       SND_SOC_DAPM_INPUT("MICIN"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+       /* Output Mixer */
+       {"Output Mixer", "Line Bypass Switch", "Line Input"},
+       {"Output Mixer", "Playback Switch", "DAC"},
+       {"Output Mixer", "Mic Sidetone Switch", "Mic Input"},
+
+       /* Outputs */
+       {"RHPOUT", NULL, "Output Mixer"},
+       {"LHPOUT", NULL, "Output Mixer"},
+       {"LOUT", NULL, "Output Mixer"},
+       {"ROUT", NULL, "Output Mixer"},
+
+       /* Inputs */
+       {"Line Input", "NULL", "LLINEIN"},
+       {"Line Input", "NULL", "RLINEIN"},
+
+       {"Mic Input", "NULL", "MICIN"},
+
+       /* input mux */
+       {"Capture Source", "Line", "Line Input"},
+       {"Capture Source", "Mic", "Mic Input"},
+       {"ADC", NULL, "Capture Source"},
+
+};
+
+/* tlv320aic23 related */
+static const struct tlv320aic23_srate_reg_info srate_reg_info[] = {
+       {4000, 0x06, 1},        /*  4000 */
+       {8000, 0x06, 0},        /*  8000 */
+       {16000, 0x0C, 1},       /* 16000 */
+       {22050, 0x11, 1},       /* 22050 */
+       {24000, 0x00, 1},       /* 24000 */
+       {32000, 0x0C, 0},       /* 32000 */
+       {44100, 0x11, 0},       /* 44100 */
+       {48000, 0x00, 0},       /* 48000 */
+       {88200, 0x1F, 0},       /* 88200 */
+       {96000, 0x0E, 0},       /* 96000 */
+};
+
+static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
+                                 ARRAY_SIZE(tlv320aic23_dapm_widgets));
+
+       /* set up audio path interconnects */
+       snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+static int tlv320aic23_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_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 iface_reg, data;
+       u8 count = 0;
+
+       iface_reg =
+           tlv320aic23_read_reg_cache(codec,
+                                      TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+
+       /* Search for the right sample rate */
+       /* Verify what happens if the rate is not supported
+        * now it goes to 96Khz */
+       while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
+              (count < ARRAY_SIZE(srate_reg_info))) {
+               count++;
+       }
+
+       data =  (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
+               (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
+               TLV320AIC23_USB_CLK_ON;
+
+       tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface_reg |= (0x01 << 2);
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface_reg |= (0x02 << 2);
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               iface_reg |= (0x03 << 2);
+               break;
+       }
+       tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+
+       return 0;
+}
+
+static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+
+       /* set active */
+       tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
+
+       return 0;
+}
+
+static void tlv320aic23_shutdown(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+
+       /* deactivate */
+       if (!codec->active) {
+               udelay(50);
+               tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+       }
+}
+
+static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 reg;
+
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
+       if (mute)
+               reg |= TLV320AIC23_DACM_MUTE;
+
+       else
+               reg &= ~TLV320AIC23_DACM_MUTE;
+
+       tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
+
+       return 0;
+}
+
+static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                  unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 iface_reg;
+
+       iface_reg =
+           tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
+
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               iface_reg |= TLV320AIC23_MS_MASTER;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+
+       }
+
+       /* interface format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               iface_reg |= TLV320AIC23_FOR_I2S;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               iface_reg |= TLV320AIC23_FOR_DSP;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface_reg |= TLV320AIC23_FOR_LJUST;
+               break;
+       default:
+               return -EINVAL;
+
+       }
+
+       tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+
+       return 0;
+}
+
+static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+                                     int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+
+       switch (freq) {
+       case 12000000:
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
+                                     enum snd_soc_bias_level level)
+{
+       u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               /* vref/mid, osc on, dac unmute */
+               tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               /* everything off except vref/vmid, */
+               tlv320aic23_write(codec, TLV320AIC23_PWR, reg | 0x0040);
+               break;
+       case SND_SOC_BIAS_OFF:
+               /* everything off, dac mute, inactive */
+               tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+               tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+#define AIC23_RATES    SNDRV_PCM_RATE_8000_96000
+#define AIC23_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+                        SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai tlv320aic23_dai = {
+       .name = "tlv320aic23",
+       .playback = {
+                    .stream_name = "Playback",
+                    .channels_min = 2,
+                    .channels_max = 2,
+                    .rates = AIC23_RATES,
+                    .formats = AIC23_FORMATS,},
+       .capture = {
+                   .stream_name = "Capture",
+                   .channels_min = 2,
+                   .channels_max = 2,
+                   .rates = AIC23_RATES,
+                   .formats = AIC23_FORMATS,},
+       .ops = {
+               .prepare = tlv320aic23_pcm_prepare,
+               .hw_params = tlv320aic23_hw_params,
+               .shutdown = tlv320aic23_shutdown,
+               },
+       .dai_ops = {
+                   .digital_mute = tlv320aic23_mute,
+                   .set_fmt = tlv320aic23_set_dai_fmt,
+                   .set_sysclk = tlv320aic23_set_dai_sysclk,
+                   }
+};
+EXPORT_SYMBOL_GPL(tlv320aic23_dai);
+
+static int tlv320aic23_suspend(struct platform_device *pdev,
+                              pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+       tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
+}
+
+static int tlv320aic23_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+       int i;
+       u16 reg;
+
+       /* Sync reg_cache with the hardware */
+       for (reg = 0; reg < ARRAY_SIZE(tlv320aic23_reg); i++) {
+               u16 val = tlv320aic23_read_reg_cache(codec, reg);
+               tlv320aic23_write(codec, reg, val);
+       }
+
+       tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       tlv320aic23_set_bias_level(codec, codec->suspend_bias_level);
+
+       return 0;
+}
+
+/*
+ * initialise the AIC23 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int tlv320aic23_init(struct snd_soc_device *socdev)
+{
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret = 0;
+       u16 reg;
+
+       codec->name = "tlv320aic23";
+       codec->owner = THIS_MODULE;
+       codec->read = tlv320aic23_read_reg_cache;
+       codec->write = tlv320aic23_write;
+       codec->set_bias_level = tlv320aic23_set_bias_level;
+       codec->dai = &tlv320aic23_dai;
+       codec->num_dai = 1;
+       codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
+       codec->reg_cache =
+           kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
+       if (codec->reg_cache == NULL)
+               return -ENOMEM;
+
+       /* Reset codec */
+       tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       /* power on device */
+       tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
+
+       /* Unmute input */
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
+       tlv320aic23_write(codec, TLV320AIC23_LINVOL,
+                         (reg & (~TLV320AIC23_LIM_MUTED)) |
+                         (TLV320AIC23_LRS_ENABLED));
+
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
+       tlv320aic23_write(codec, TLV320AIC23_RINVOL,
+                         (reg & (~TLV320AIC23_LIM_MUTED)) |
+                         TLV320AIC23_LRS_ENABLED);
+
+       reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
+       tlv320aic23_write(codec, TLV320AIC23_ANLG,
+                        (reg) & (~TLV320AIC23_BYPASS_ON) &
+                        (~TLV320AIC23_MICM_MUTED));
+
+       /* Default output volume */
+       tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
+                         TLV320AIC23_DEFAULT_OUT_VOL &
+                         TLV320AIC23_OUT_VOL_MASK);
+       tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
+                         TLV320AIC23_DEFAULT_OUT_VOL &
+                         TLV320AIC23_OUT_VOL_MASK);
+
+       tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
+
+       tlv320aic23_add_controls(codec);
+       tlv320aic23_add_widgets(codec);
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "tlv320aic23: failed to register card\n");
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       kfree(codec->reg_cache);
+       return ret;
+}
+static struct snd_soc_device *tlv320aic23_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+/*
+ * If the i2c layer weren't so broken, we could pass this kind of data
+ * around
+ */
+static int tlv320aic23_codec_probe(struct i2c_client *i2c,
+                                  const struct i2c_device_id *i2c_id)
+{
+       struct snd_soc_device *socdev = tlv320aic23_socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret;
+
+       if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EINVAL;
+
+       i2c_set_clientdata(i2c, codec);
+       codec->control_data = i2c;
+
+       ret = tlv320aic23_init(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n");
+               goto err;
+       }
+       return ret;
+
+err:
+       kfree(codec);
+       kfree(i2c);
+       return ret;
+}
+static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
+{
+       put_device(&i2c->dev);
+       return 0;
+}
+
+static const struct i2c_device_id tlv320aic23_id[] = {
+       {"tlv320aic23", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
+
+static struct i2c_driver tlv320aic23_i2c_driver = {
+       .driver = {
+                  .name = "tlv320aic23",
+                  },
+       .probe = tlv320aic23_codec_probe,
+       .remove = __exit_p(tlv320aic23_i2c_remove),
+       .id_table = tlv320aic23_id,
+};
+
+#endif
+
+static int tlv320aic23_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
+
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+
+       socdev->codec = codec;
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       tlv320aic23_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       codec->hw_write = (hw_write_t) i2c_smbus_write_byte_data;
+       codec->hw_read = NULL;
+       ret = i2c_add_driver(&tlv320aic23_i2c_driver);
+       if (ret != 0)
+               printk(KERN_ERR "can't add i2c driver");
+#endif
+       return ret;
+}
+
+static int tlv320aic23_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec->control_data)
+               tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&tlv320aic23_i2c_driver);
+#endif
+       kfree(codec->reg_cache);
+       kfree(codec);
+
+       return 0;
+}
+struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
+       .probe = tlv320aic23_probe,
+       .remove = tlv320aic23_remove,
+       .suspend = tlv320aic23_suspend,
+       .resume = tlv320aic23_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
+
+MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
new file mode 100644 (file)
index 0000000..79d1faf
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * ALSA SoC TLV320AIC23 codec driver
+ *
+ * Author:      Arun KS, <arunks@mistralsolutions.com>
+ * Copyright:   (C) 2008 Mistral Solutions Pvt Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _TLV320AIC23_H
+#define _TLV320AIC23_H
+
+/* Codec TLV320AIC23 */
+#define TLV320AIC23_LINVOL             0x00
+#define TLV320AIC23_RINVOL             0x01
+#define TLV320AIC23_LCHNVOL            0x02
+#define TLV320AIC23_RCHNVOL            0x03
+#define TLV320AIC23_ANLG               0x04
+#define TLV320AIC23_DIGT               0x05
+#define TLV320AIC23_PWR                        0x06
+#define TLV320AIC23_DIGT_FMT           0x07
+#define TLV320AIC23_SRATE              0x08
+#define TLV320AIC23_ACTIVE             0x09
+#define TLV320AIC23_RESET              0x0F
+
+/* Left (right) line input volume control register */
+#define TLV320AIC23_LRS_ENABLED                0x0100
+#define TLV320AIC23_LIM_MUTED          0x0080
+#define TLV320AIC23_LIV_DEFAULT                0x0017
+#define TLV320AIC23_LIV_MAX            0x001f
+#define TLV320AIC23_LIV_MIN            0x0000
+
+/* Left (right) channel headphone volume control register */
+#define TLV320AIC23_LZC_ON             0x0080
+#define TLV320AIC23_LHV_DEFAULT                0x0079
+#define TLV320AIC23_LHV_MAX            0x007f
+#define TLV320AIC23_LHV_MIN            0x0000
+
+/* Analog audio path control register */
+#define TLV320AIC23_STA_REG(x)         ((x)<<6)
+#define TLV320AIC23_STE_ENABLED                0x0020
+#define TLV320AIC23_DAC_SELECTED       0x0010
+#define TLV320AIC23_BYPASS_ON          0x0008
+#define TLV320AIC23_INSEL_MIC          0x0004
+#define TLV320AIC23_MICM_MUTED         0x0002
+#define TLV320AIC23_MICB_20DB          0x0001
+
+/* Digital audio path control register */
+#define TLV320AIC23_DACM_MUTE          0x0008
+#define TLV320AIC23_DEEMP_32K          0x0002
+#define TLV320AIC23_DEEMP_44K          0x0004
+#define TLV320AIC23_DEEMP_48K          0x0006
+#define TLV320AIC23_ADCHP_ON           0x0001
+
+/* Power control down register */
+#define TLV320AIC23_DEVICE_PWR_OFF     0x0080
+#define TLV320AIC23_CLK_OFF            0x0040
+#define TLV320AIC23_OSC_OFF            0x0020
+#define TLV320AIC23_OUT_OFF            0x0010
+#define TLV320AIC23_DAC_OFF            0x0008
+#define TLV320AIC23_ADC_OFF            0x0004
+#define TLV320AIC23_MIC_OFF            0x0002
+#define TLV320AIC23_LINE_OFF           0x0001
+
+/* Digital audio interface register */
+#define TLV320AIC23_MS_MASTER          0x0040
+#define TLV320AIC23_LRSWAP_ON          0x0020
+#define TLV320AIC23_LRP_ON             0x0010
+#define TLV320AIC23_IWL_16             0x0000
+#define TLV320AIC23_IWL_20             0x0004
+#define TLV320AIC23_IWL_24             0x0008
+#define TLV320AIC23_IWL_32             0x000C
+#define TLV320AIC23_FOR_I2S            0x0002
+#define TLV320AIC23_FOR_DSP            0x0003
+#define TLV320AIC23_FOR_LJUST          0x0001
+
+/* Sample rate control register */
+#define TLV320AIC23_CLKOUT_HALF                0x0080
+#define TLV320AIC23_CLKIN_HALF         0x0040
+#define TLV320AIC23_BOSR_384fs         0x0002  /* BOSR_272fs in USB mode */
+#define TLV320AIC23_USB_CLK_ON         0x0001
+#define TLV320AIC23_SR_MASK             0xf
+#define TLV320AIC23_CLKOUT_SHIFT        7
+#define TLV320AIC23_CLKIN_SHIFT         6
+#define TLV320AIC23_SR_SHIFT            2
+#define TLV320AIC23_BOSR_SHIFT          1
+
+/* Digital interface register */
+#define TLV320AIC23_ACT_ON             0x0001
+
+/*
+ * AUDIO related MACROS
+ */
+
+#define TLV320AIC23_DEFAULT_OUT_VOL    0x70
+#define TLV320AIC23_DEFAULT_IN_VOLUME  0x10
+
+#define TLV320AIC23_OUT_VOL_MIN                TLV320AIC23_LHV_MIN
+#define TLV320AIC23_OUT_VOL_MAX                TLV320AIC23_LHV_MAX
+#define TLV320AIC23_OUT_VO_RANGE       (TLV320AIC23_OUT_VOL_MAX - \
+                                       TLV320AIC23_OUT_VOL_MIN)
+#define TLV320AIC23_OUT_VOL_MASK       TLV320AIC23_OUT_VOL_MAX
+
+#define TLV320AIC23_IN_VOL_MIN         TLV320AIC23_LIV_MIN
+#define TLV320AIC23_IN_VOL_MAX         TLV320AIC23_LIV_MAX
+#define TLV320AIC23_IN_VOL_RANGE       (TLV320AIC23_IN_VOL_MAX - \
+                                       TLV320AIC23_IN_VOL_MIN)
+#define TLV320AIC23_IN_VOL_MASK                TLV320AIC23_IN_VOL_MAX
+
+#define TLV320AIC23_SIDETONE_MASK      0x1c0
+#define TLV320AIC23_SIDETONE_0         0x100
+#define TLV320AIC23_SIDETONE_6         0x000
+#define TLV320AIC23_SIDETONE_9         0x040
+#define TLV320AIC23_SIDETONE_12                0x080
+#define TLV320AIC23_SIDETONE_18                0x0c0
+
+extern struct snd_soc_dai tlv320aic23_dai;
+extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23;
+
+#endif /* _TLV320AIC23_H */
index 566a427c928f18085101add5e5990736101850dc..05336ed7e4935fdbd0d9f27a1f77e3b0c5c0bef2 100644 (file)
@@ -48,7 +48,6 @@
 
 #include "tlv320aic3x.h"
 
-#define AUDIO_NAME "aic3x"
 #define AIC3X_VERSION "0.2"
 
 /* codec private data */
@@ -991,7 +990,7 @@ EXPORT_SYMBOL_GPL(aic3x_headset_detected);
                         SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 struct snd_soc_dai aic3x_dai = {
-       .name = "aic3x",
+       .name = "tlv320aic3x",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -1055,7 +1054,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
        struct aic3x_setup_data *setup = socdev->codec_data;
        int reg, ret = 0;
 
-       codec->name = "aic3x";
+       codec->name = "tlv320aic3x";
        codec->owner = THIS_MODULE;
        codec->read = aic3x_read_reg_cache;
        codec->write = aic3x_write;
index d206d7f892b68b8c0103bc5337b27e5b460b62d2..a69ee72a7af553ca3f36d03d2c63288d97914232 100644 (file)
@@ -36,7 +36,6 @@
 #include "uda1380.h"
 
 #define UDA1380_VERSION "0.6"
-#define AUDIO_NAME "uda1380"
 
 /*
  * uda1380 register cache
index 9a37c8d95ed2475892f75cbef7a6ca43fc3e1533..d8ca2da8d634e5e2a827339f3f3939d196d89941 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2006 Wolfson Microelectronics PLC.
  *
- * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -18,6 +18,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -27,7 +28,6 @@
 
 #include "wm8510.h"
 
-#define AUDIO_NAME "wm8510"
 #define WM8510_VERSION "0.6"
 
 struct snd_soc_codec_device soc_codec_dev_wm8510;
@@ -55,6 +55,9 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
        0x0001,
 };
 
+#define WM8510_POWER1_BIASEN  0x08
+#define WM8510_POWER1_BUFIOEN 0x10
+
 /*
  * read wm8510 register cache
  */
@@ -224,9 +227,9 @@ SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
 SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
 SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
 
-SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0,
-                &wm8510_micpga_controls[0],
-                ARRAY_SIZE(wm8510_micpga_controls)),
+SND_SOC_DAPM_MIXER("Mic PGA", WM8510_POWER2, 2, 0,
+                  &wm8510_micpga_controls[0],
+                  ARRAY_SIZE(wm8510_micpga_controls)),
 SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0,
        &wm8510_boost_controls[0],
        ARRAY_SIZE(wm8510_boost_controls)),
@@ -526,23 +529,35 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
 static int wm8510_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
+       u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               wm8510_write(codec, WM8510_POWER1, 0x1ff);
-               wm8510_write(codec, WM8510_POWER2, 0x1ff);
-               wm8510_write(codec, WM8510_POWER3, 0x1ff);
-               break;
        case SND_SOC_BIAS_PREPARE:
+               power1 |= 0x1;  /* VMID 50k */
+               wm8510_write(codec, WM8510_POWER1, power1);
+               break;
+
        case SND_SOC_BIAS_STANDBY:
+               power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
+
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       /* Initial cap charge at VMID 5k */
+                       wm8510_write(codec, WM8510_POWER1, power1 | 0x3);
+                       mdelay(100);
+               }
+
+               power1 |= 0x2;  /* VMID 500k */
+               wm8510_write(codec, WM8510_POWER1, power1);
                break;
+
        case SND_SOC_BIAS_OFF:
-               /* everything off, dac mute, inactive */
-               wm8510_write(codec, WM8510_POWER1, 0x0);
-               wm8510_write(codec, WM8510_POWER2, 0x0);
-               wm8510_write(codec, WM8510_POWER3, 0x0);
+               wm8510_write(codec, WM8510_POWER1, 0);
+               wm8510_write(codec, WM8510_POWER2, 0);
+               wm8510_write(codec, WM8510_POWER3, 0);
                break;
        }
+
        codec->bias_level = level;
        return 0;
 }
@@ -640,6 +655,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
        }
 
        /* power on device */
+       codec->bias_level = SND_SOC_BIAS_OFF;
        wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        wm8510_add_controls(codec);
        wm8510_add_widgets(codec);
@@ -747,6 +763,62 @@ err_driver:
 }
 #endif
 
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8510_spi_probe(struct spi_device *spi)
+{
+       struct snd_soc_device *socdev = wm8510_socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret;
+
+       codec->control_data = spi;
+
+       ret = wm8510_init(socdev);
+       if (ret < 0)
+               dev_err(&spi->dev, "failed to initialise WM8510\n");
+
+       return ret;
+}
+
+static int __devexit wm8510_spi_remove(struct spi_device *spi)
+{
+       return 0;
+}
+
+static struct spi_driver wm8510_spi_driver = {
+       .driver = {
+               .name   = "wm8510",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = wm8510_spi_probe,
+       .remove         = __devexit_p(wm8510_spi_remove),
+};
+
+static int wm8510_spi_write(struct spi_device *spi, const char *data, int len)
+{
+       struct spi_transfer t;
+       struct spi_message m;
+       u8 msg[2];
+
+       if (len <= 0)
+               return 0;
+
+       msg[0] = data[0];
+       msg[1] = data[1];
+
+       spi_message_init(&m);
+       memset(&t, 0, (sizeof t));
+
+       t.tx_buf = &msg[0];
+       t.len = len;
+
+       spi_message_add_tail(&t, &m);
+       spi_sync(spi, &m);
+
+       return len;
+}
+#endif /* CONFIG_SPI_MASTER */
+
 static int wm8510_probe(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -772,8 +844,14 @@ static int wm8510_probe(struct platform_device *pdev)
                codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8510_add_i2c_device(pdev, setup);
        }
-#else
-       /* Add other interfaces here */
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       if (setup->spi) {
+               codec->hw_write = (hw_write_t)wm8510_spi_write;
+               ret = spi_register_driver(&wm8510_spi_driver);
+               if (ret != 0)
+                       printk(KERN_ERR "can't add spi driver");
+       }
 #endif
 
        if (ret != 0)
@@ -795,6 +873,9 @@ static int wm8510_remove(struct platform_device *pdev)
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_unregister_device(codec->control_data);
        i2c_del_driver(&wm8510_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8510_spi_driver);
 #endif
        kfree(codec);
 
index c53683960456ad2a568c3ae44eea7c9095e7723b..bdefcf5c69ff2a9ed57e160843710467d19d33d0 100644 (file)
@@ -94,6 +94,7 @@
 #define WM8510_MCLKDIV_12      (7 << 5)
 
 struct wm8510_setup_data {
+       int spi;
        int i2c_bus;
        unsigned short i2c_address;
 };
index df1ffbe305bf3875a4daa9f22c9ff709a6370bde..627ebfb4209b72b786ad66f992b0659491f8f74d 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -36,7 +35,6 @@
 
 #include "wm8580.h"
 
-#define AUDIO_NAME "wm8580"
 #define WM8580_VERSION "0.1"
 
 struct pll_state {
index 7b64d9a7ff76408092520d614c1601dbb901c7be..7f8a7e36b33e9124d0c3d924301d9cccb6cb9c5f 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "wm8731.h"
 
-#define AUDIO_NAME "wm8731"
 #define WM8731_VERSION "0.13"
 
 struct snd_soc_codec_device soc_codec_dev_wm8731;
index 4892e398a5982fa89b87ecbd1d2ceaa6fdc3af53..9b7296ee5b08fa541c6dfdbc44f9b5b8b31f92d6 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "wm8750.h"
 
-#define AUDIO_NAME "WM8750"
 #define WM8750_VERSION "0.12"
 
 /* codec private data */
index 8c4df44f334582b2fa23a8be42a0ecdea472c1c0..d426eaa2218575b75004a48f86cfe9079d84fa21 100644 (file)
@@ -2,8 +2,7 @@
  * wm8753.c  --  WM8753 ALSA Soc Audio driver
  *
  * Copyright 2003 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  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
@@ -40,6 +39,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -51,7 +51,6 @@
 
 #include "wm8753.h"
 
-#define AUDIO_NAME "wm8753"
 #define WM8753_VERSION "0.16"
 
 static int caps_charge = 2000;
@@ -1719,6 +1718,63 @@ err_driver:
 }
 #endif
 
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8753_spi_probe(struct spi_device *spi)
+{
+       struct snd_soc_device *socdev = wm8753_socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret;
+
+       codec->control_data = spi;
+
+       ret = wm8753_init(socdev);
+       if (ret < 0)
+               dev_err(&spi->dev, "failed to initialise WM8753\n");
+
+       return ret;
+}
+
+static int __devexit wm8753_spi_remove(struct spi_device *spi)
+{
+       return 0;
+}
+
+static struct spi_driver wm8753_spi_driver = {
+       .driver = {
+               .name   = "wm8753",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = wm8753_spi_probe,
+       .remove         = __devexit_p(wm8753_spi_remove),
+};
+
+static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
+{
+       struct spi_transfer t;
+       struct spi_message m;
+       u8 msg[2];
+
+       if (len <= 0)
+               return 0;
+
+       msg[0] = data[0];
+       msg[1] = data[1];
+
+       spi_message_init(&m);
+       memset(&t, 0, (sizeof t));
+
+       t.tx_buf = &msg[0];
+       t.len = len;
+
+       spi_message_add_tail(&t, &m);
+       spi_sync(spi, &m);
+
+       return len;
+}
+#endif
+
+
 static int wm8753_probe(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -1753,8 +1809,14 @@ static int wm8753_probe(struct platform_device *pdev)
                codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8753_add_i2c_device(pdev, setup);
        }
-#else
-               /* Add other interfaces here */
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       if (setup->spi) {
+               codec->hw_write = (hw_write_t)wm8753_spi_write;
+               ret = spi_register_driver(&wm8753_spi_driver);
+               if (ret != 0)
+                       printk(KERN_ERR "can't add spi driver");
+       }
 #endif
 
        if (ret != 0) {
@@ -1797,6 +1859,9 @@ static int wm8753_remove(struct platform_device *pdev)
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_unregister_device(codec->control_data);
        i2c_del_driver(&wm8753_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8753_spi_driver);
 #endif
        kfree(codec->private_data);
        kfree(codec);
index 7defde069f1df92793c254f49c305351db3d8b86..f55704ce931b44e135b8038967eaebf751dbf632 100644 (file)
@@ -2,8 +2,7 @@
  * wm8753.h  --  audio driver for WM8753
  *
  * Copyright 2003 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  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
@@ -79,6 +78,7 @@
 #define WM8753_ADCTL2          0x3f
 
 struct wm8753_setup_data {
+       int spi;
        int i2c_bus;
        unsigned short i2c_address;
 };
index 0b8c6d38b48f4253db572b422bec4d04da9bedb5..3b326c9b55866bba7a81c1421329026bed290247 100644 (file)
@@ -18,7 +18,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index a3f54ec4226eb554248c75133508a5d7d21701f2..ce40d78776058456782f5d723152250bfc79e681 100644 (file)
@@ -653,14 +653,14 @@ static const struct snd_kcontrol_new wm8903_snd_controls[] = {
 
 /* Input PGAs - No TLV since the scale depends on PGA mode */
 SOC_SINGLE("Left Input PGA Switch", WM8903_ANALOGUE_LEFT_INPUT_0,
-          7, 1, 0),
+          7, 1, 1),
 SOC_SINGLE("Left Input PGA Volume", WM8903_ANALOGUE_LEFT_INPUT_0,
           0, 31, 0),
 SOC_SINGLE("Left Input PGA Common Mode Switch", WM8903_ANALOGUE_LEFT_INPUT_1,
           6, 1, 0),
 
 SOC_SINGLE("Right Input PGA Switch", WM8903_ANALOGUE_RIGHT_INPUT_0,
-          7, 1, 0),
+          7, 1, 1),
 SOC_SINGLE("Right Input PGA Volume", WM8903_ANALOGUE_RIGHT_INPUT_0,
           0, 31, 0),
 SOC_SINGLE("Right Input PGA Common Mode Switch", WM8903_ANALOGUE_RIGHT_INPUT_1,
index 974a4cd0f3fdbd6ce0845e8ea7fcb954e345ecd9..f41a578ddd4fabe908053cee4b273a43155b0e77 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "wm8971.h"
 
-#define AUDIO_NAME "wm8971"
 #define WM8971_VERSION "0.9"
 
 #define        WM8971_REG_COUNT                43
index 63410d7b5efb3623c8e92585ac51fb9ff8737606..572d22b0880b5b1f1033e244cee6269831cd9216 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "wm8990.h"
 
-#define AUDIO_NAME "wm8990"
 #define WM8990_VERSION "0.2"
 
 /* codec private data */
index 2f1c91b1d5567feb6fc3aea44eece7a3f00dd158..ffb471e420e2e76718f931420135c8b99cf21864 100644 (file)
@@ -2,8 +2,7 @@
  * wm9712.c  --  ALSA Soc WM9712 codec support
  *
  * Copyright 2006 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  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
index 441d0580db1f75adf212ee40a882cd4ca47fb4c0..aba402b3c99994a95489bde9e526da23f7d4ea69 100644 (file)
@@ -2,8 +2,7 @@
  * wm9713.c  --  ALSA Soc WM9713 codec support
  *
  * Copyright 2006 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  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
index aea27e70043cf8f687884227c117ceed224c98f4..8b7766b998d7de431bd30d18d32569019a116d28 100644 (file)
@@ -13,3 +13,11 @@ config SND_OMAP_SOC_N810
        select SND_SOC_TLV320AIC3X
        help
          Say Y if you want to add support for SoC audio on Nokia N810.
+
+config SND_OMAP_SOC_OSK5912
+       tristate "SoC Audio support for omap osk5912"
+       depends on SND_OMAP_SOC && MACH_OMAP_OSK
+       select SND_OMAP_SOC_MCBSP
+       select SND_SOC_TLV320AIC23
+       help
+         Say Y if you want to add support for SoC audio on osk5912.
index d8d8d58075e3ee4c0b362eadeee9fce1b43cc2d3..e09d1f297f644c856c16250dc7cdc407bd6f7e6f 100644 (file)
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
 
 # OMAP Machine Support
 snd-soc-n810-objs := n810.o
+snd-soc-osk5912-objs := osk5912.o
 
 obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
index d166b6b2a60dd9b78ade26cb76532cbe1b3c30a8..fae3ad36e0bfc3e03606561c48c0c54bb7d192b6 100644 (file)
@@ -247,9 +247,9 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
        int i, err;
 
        /* Not connected */
-       snd_soc_dapm_disable_pin(codec, "MONO_LOUT");
-       snd_soc_dapm_disable_pin(codec, "HPLCOM");
-       snd_soc_dapm_disable_pin(codec, "HPRCOM");
+       snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
+       snd_soc_dapm_nc_pin(codec, "HPLCOM");
+       snd_soc_dapm_nc_pin(codec, "HPRCOM");
 
        /* Add N810 specific controls */
        for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
index 35310e16d7f3658623fdf9755ae6df7190688a1e..0a063a98a6613820295419a5cab10bd09a8dc338 100644 (file)
@@ -59,12 +59,7 @@ static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
  * Stream DMA parameters. DMA request line and port address are set runtime
  * since they are different between OMAP1 and later OMAPs
  */
-static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2] = {
-{
-       { .name         = "I2S PCM Stereo out", },
-       { .name         = "I2S PCM Stereo in", },
-},
-};
+static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
 
 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
 static const int omap1_dma_reqs[][2] = {
@@ -84,11 +79,22 @@ static const unsigned long omap1_mcbsp_port[][2] = {
 static const int omap1_dma_reqs[][2] = {};
 static const unsigned long omap1_mcbsp_port[][2] = {};
 #endif
-#if defined(CONFIG_ARCH_OMAP2420)
-static const int omap2420_dma_reqs[][2] = {
+
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+static const int omap24xx_dma_reqs[][2] = {
        { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
        { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+       { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
+       { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
+       { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
+#endif
 };
+#else
+static const int omap24xx_dma_reqs[][2] = {};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2420)
 static const unsigned long omap2420_mcbsp_port[][2] = {
        { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
          OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
@@ -96,10 +102,43 @@ static const unsigned long omap2420_mcbsp_port[][2] = {
          OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
 };
 #else
-static const int omap2420_dma_reqs[][2] = {};
 static const unsigned long omap2420_mcbsp_port[][2] = {};
 #endif
 
+#if defined(CONFIG_ARCH_OMAP2430)
+static const unsigned long omap2430_mcbsp_port[][2] = {
+       { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
+};
+#else
+static const unsigned long omap2430_mcbsp_port[][2] = {};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP34XX)
+static const unsigned long omap34xx_mcbsp_port[][2] = {
+       { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
+       { OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
+         OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
+};
+#else
+static const unsigned long omap34xx_mcbsp_port[][2] = {};
+#endif
+
 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -167,14 +206,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                dma = omap1_dma_reqs[bus_id][substream->stream];
                port = omap1_mcbsp_port[bus_id][substream->stream];
        } else if (cpu_is_omap2420()) {
-               dma = omap2420_dma_reqs[bus_id][substream->stream];
+               dma = omap24xx_dma_reqs[bus_id][substream->stream];
                port = omap2420_mcbsp_port[bus_id][substream->stream];
+       } else if (cpu_is_omap2430()) {
+               dma = omap24xx_dma_reqs[bus_id][substream->stream];
+               port = omap2430_mcbsp_port[bus_id][substream->stream];
+       } else if (cpu_is_omap343x()) {
+               dma = omap24xx_dma_reqs[bus_id][substream->stream];
+               port = omap34xx_mcbsp_port[bus_id][substream->stream];
        } else {
-               /*
-                * TODO: Add support for 2430 and 3430
-                */
                return -ENODEV;
        }
+       omap_mcbsp_dai_dma_params[id][substream->stream].name =
+               substream->stream ? "Audio Capture" : "Audio Playback";
        omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
        omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
        cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
@@ -245,6 +289,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                regs->rcr2      |= RDATDLY(1);
                regs->xcr2      |= XDATDLY(1);
                break;
+       case SND_SOC_DAIFMT_DSP_A:
+               /* 0-bit data delay */
+               regs->rcr2      |= RDATDLY(0);
+               regs->xcr2      |= XDATDLY(0);
+               break;
        default:
                /* Unsupported data format */
                return -EINVAL;
@@ -310,7 +359,7 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
                                       int clk_id)
 {
        int sel_bit;
-       u16 reg;
+       u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
 
        if (cpu_class_is_omap1()) {
                /* OMAP1's can use only external source clock */
@@ -320,6 +369,12 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
                        return 0;
        }
 
+       if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
+               return -EINVAL;
+
+       if (cpu_is_omap343x())
+               reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
+
        switch (mcbsp_data->bus_id) {
        case 0:
                reg = OMAP2_CONTROL_DEVCONF0;
@@ -329,20 +384,26 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
                reg = OMAP2_CONTROL_DEVCONF0;
                sel_bit = 6;
                break;
-       /* TODO: Support for ports 3 - 5 in OMAP2430 and OMAP34xx */
+       case 2:
+               reg = reg_devconf1;
+               sel_bit = 0;
+               break;
+       case 3:
+               reg = reg_devconf1;
+               sel_bit = 2;
+               break;
+       case 4:
+               reg = reg_devconf1;
+               sel_bit = 4;
+               break;
        default:
                return -EINVAL;
        }
 
-       if (cpu_class_is_omap2()) {
-               if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK) {
-                       omap_ctrl_writel(omap_ctrl_readl(reg) &
-                                        ~(1 << sel_bit), reg);
-               } else {
-                       omap_ctrl_writel(omap_ctrl_readl(reg) |
-                                        (1 << sel_bit), reg);
-               }
-       }
+       if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
+               omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
+       else
+               omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
 
        return 0;
 }
@@ -376,37 +437,49 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        return err;
 }
 
-struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS] = {
-{
-       .name = "omap-mcbsp-dai",
-       .id = 0,
-       .type = SND_SOC_DAI_I2S,
-       .playback = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = OMAP_MCBSP_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .capture = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = OMAP_MCBSP_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .ops = {
-               .startup = omap_mcbsp_dai_startup,
-               .shutdown = omap_mcbsp_dai_shutdown,
-               .trigger = omap_mcbsp_dai_trigger,
-               .hw_params = omap_mcbsp_dai_hw_params,
-       },
-       .dai_ops = {
-               .set_fmt = omap_mcbsp_dai_set_dai_fmt,
-               .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
-               .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
-       },
-       .private_data = &mcbsp_data[0].bus_id,
-},
+#define OMAP_MCBSP_DAI_BUILDER(link_id)                                \
+{                                                              \
+       .name = "omap-mcbsp-dai-(link_id)",                     \
+       .id = (link_id),                                        \
+       .type = SND_SOC_DAI_I2S,                                \
+       .playback = {                                           \
+               .channels_min = 2,                              \
+               .channels_max = 2,                              \
+               .rates = OMAP_MCBSP_RATES,                      \
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,             \
+       },                                                      \
+       .capture = {                                            \
+               .channels_min = 2,                              \
+               .channels_max = 2,                              \
+               .rates = OMAP_MCBSP_RATES,                      \
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,             \
+       },                                                      \
+       .ops = {                                                \
+               .startup = omap_mcbsp_dai_startup,              \
+               .shutdown = omap_mcbsp_dai_shutdown,            \
+               .trigger = omap_mcbsp_dai_trigger,              \
+               .hw_params = omap_mcbsp_dai_hw_params,          \
+       },                                                      \
+       .dai_ops = {                                            \
+               .set_fmt = omap_mcbsp_dai_set_dai_fmt,          \
+               .set_clkdiv = omap_mcbsp_dai_set_clkdiv,        \
+               .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,    \
+       },                                                      \
+       .private_data = &mcbsp_data[(link_id)].bus_id,          \
+}
+
+struct snd_soc_dai omap_mcbsp_dai[] = {
+       OMAP_MCBSP_DAI_BUILDER(0),
+       OMAP_MCBSP_DAI_BUILDER(1),
+#if NUM_LINKS >= 3
+       OMAP_MCBSP_DAI_BUILDER(2),
+#endif
+#if NUM_LINKS == 5
+       OMAP_MCBSP_DAI_BUILDER(3),
+       OMAP_MCBSP_DAI_BUILDER(4),
+#endif
 };
+
 EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
 
 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
index ed8afb55067173fc4969b2984ae20e10f5cabdea..df7ad13ba73d14711ca8aff42067e317b1639d1e 100644 (file)
@@ -38,11 +38,17 @@ enum omap_mcbsp_div {
        OMAP_MCBSP_CLKGDV,              /* Sample rate generator divider */
 };
 
-/*
- * REVISIT: Preparation for the ASoC v2. Let the number of available links to
- * be same than number of McBSP ports found in OMAP(s) we are compiling for.
- */
-#define NUM_LINKS      1
+#if defined(CONFIG_ARCH_OMAP2420)
+#define NUM_LINKS      2
+#endif
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+#undef  NUM_LINKS
+#define NUM_LINKS      3
+#endif
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+#undef  NUM_LINKS
+#define NUM_LINKS      5
+#endif
 
 extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
 
index 690bfeaec4a0ee3b157b0ccb7a7ea1a1ea5e4189..e9084fdd2082efcbc14695e801ec6ad89ff66599 100644 (file)
@@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
        prtd->dma_data = dma_data;
        err = omap_request_dma(dma_data->dma_req, dma_data->name,
                               omap_pcm_dma_irq, substream, &prtd->dma_ch);
-       if (!cpu_is_omap1510()) {
+       if (!err & !cpu_is_omap1510()) {
                /*
                 * Link channel with itself so DMA doesn't need any
                 * reprogramming while looping the buffer
@@ -147,12 +147,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
                dma_params.src_or_dst_synch     = OMAP_DMA_DST_SYNC;
                dma_params.src_start            = runtime->dma_addr;
                dma_params.dst_start            = dma_data->port_addr;
+               dma_params.dst_port             = OMAP_DMA_PORT_MPUI;
        } else {
                dma_params.src_amode            = OMAP_DMA_AMODE_CONSTANT;
                dma_params.dst_amode            = OMAP_DMA_AMODE_POST_INC;
                dma_params.src_or_dst_synch     = OMAP_DMA_SRC_SYNC;
                dma_params.src_start            = dma_data->port_addr;
                dma_params.dst_start            = runtime->dma_addr;
+               dma_params.src_port             = OMAP_DMA_PORT_MPUI;
        }
        /*
         * Set DMA transfer frame size equal to ALSA period size and frame
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
new file mode 100644 (file)
index 0000000..0fe7337
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * osk5912.c  --  SoC audio for OSK 5912
+ *
+ * Copyright (C) 2008 Mistral Solutions
+ *
+ * Contact: Arun KS  <arunks@mistralsolutions.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <linux/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/tlv320aic23.h"
+
+#define CODEC_CLOCK    12000000
+
+static struct clk *tlv320aic23_mclk;
+
+static int osk_startup(struct snd_pcm_substream *substream)
+{
+       return clk_enable(tlv320aic23_mclk);
+}
+
+static void osk_shutdown(struct snd_pcm_substream *substream)
+{
+       clk_disable(tlv320aic23_mclk);
+}
+
+static int osk_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;
+       int err;
+
+       /* Set codec DAI configuration */
+       err = snd_soc_dai_set_fmt(codec_dai,
+                                 SND_SOC_DAIFMT_DSP_A |
+                                 SND_SOC_DAIFMT_NB_IF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+       if (err < 0) {
+               printk(KERN_ERR "can't set codec DAI configuration\n");
+               return err;
+       }
+
+       /* Set cpu DAI configuration */
+       err = snd_soc_dai_set_fmt(cpu_dai,
+                                 SND_SOC_DAIFMT_DSP_A |
+                                 SND_SOC_DAIFMT_NB_IF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+       if (err < 0) {
+               printk(KERN_ERR "can't set cpu DAI configuration\n");
+               return err;
+       }
+
+       /* Set the codec system clock for DAC and ADC */
+       err =
+           snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
+
+       if (err < 0) {
+               printk(KERN_ERR "can't set codec system clock\n");
+               return err;
+       }
+
+       return err;
+}
+
+static struct snd_soc_ops osk_ops = {
+       .startup = osk_startup,
+       .hw_params = osk_hw_params,
+       .shutdown = osk_shutdown,
+};
+
+static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+       SND_SOC_DAPM_LINE("Line In", NULL),
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       {"Headphone Jack", NULL, "LHPOUT"},
+       {"Headphone Jack", NULL, "RHPOUT"},
+
+       {"LLINEIN", NULL, "Line In"},
+       {"RLINEIN", NULL, "Line In"},
+
+       {"MICIN", NULL, "Mic Jack"},
+};
+
+static int osk_tlv320aic23_init(struct snd_soc_codec *codec)
+{
+
+       /* Add osk5912 specific widgets */
+       snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
+                                 ARRAY_SIZE(tlv320aic23_dapm_widgets));
+
+       /* Set up osk5912 specific audio path audio_map */
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+       snd_soc_dapm_enable_pin(codec, "Line In");
+       snd_soc_dapm_enable_pin(codec, "Mic Jack");
+
+       snd_soc_dapm_sync(codec);
+
+       return 0;
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link osk_dai = {
+       .name = "TLV320AIC23",
+       .stream_name = "AIC23",
+       .cpu_dai = &omap_mcbsp_dai[0],
+       .codec_dai = &tlv320aic23_dai,
+       .init = osk_tlv320aic23_init,
+       .ops = &osk_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_machine snd_soc_machine_osk = {
+       .name = "OSK5912",
+       .dai_link = &osk_dai,
+       .num_links = 1,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device osk_snd_devdata = {
+       .machine = &snd_soc_machine_osk,
+       .platform = &omap_soc_platform,
+       .codec_dev = &soc_codec_dev_tlv320aic23,
+};
+
+static struct platform_device *osk_snd_device;
+
+static int __init osk_soc_init(void)
+{
+       int err;
+       u32 curRate;
+       struct device *dev;
+
+       if (!(machine_is_omap_osk()))
+               return -ENODEV;
+
+       osk_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!osk_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(osk_snd_device, &osk_snd_devdata);
+       osk_snd_devdata.dev = &osk_snd_device->dev;
+       *(unsigned int *)osk_dai.cpu_dai->private_data = 0;     /* McBSP1 */
+       err = platform_device_add(osk_snd_device);
+       if (err)
+               goto err1;
+
+       dev = &osk_snd_device->dev;
+
+       tlv320aic23_mclk = clk_get(dev, "mclk");
+       if (IS_ERR(tlv320aic23_mclk)) {
+               printk(KERN_ERR "Could not get mclk clock\n");
+               return -ENODEV;
+       }
+
+       if (clk_get_usecount(tlv320aic23_mclk) > 0) {
+               /* MCLK is already in use */
+               printk(KERN_WARNING
+                      "MCLK in use at %d Hz. We change it to %d Hz\n",
+                      (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK);
+       }
+
+       /*
+        * Configure 12 MHz output on MCLK.
+        */
+       curRate = (uint) clk_get_rate(tlv320aic23_mclk);
+       if (curRate != CODEC_CLOCK) {
+               if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) {
+                       printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n");
+                       err = -ECANCELED;
+                       goto err1;
+               }
+       }
+
+       printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n",
+              (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK,
+              clk_get_usecount(tlv320aic23_mclk));
+
+       return 0;
+err1:
+       clk_put(tlv320aic23_mclk);
+       platform_device_del(osk_snd_device);
+       platform_device_put(osk_snd_device);
+
+       return err;
+
+}
+
+static void __exit osk_soc_exit(void)
+{
+       platform_device_unregister(osk_snd_device);
+}
+
+module_init(osk_soc_init);
+module_exit(osk_soc_exit);
+
+MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+MODULE_DESCRIPTION("ALSA SoC OSK 5912");
+MODULE_LICENSE("GPL");
index 72b7a5140bf832d97667dd01bfbf4c936d9fc0fd..dd7fa0b329c7e6fd99d75ffce523c7d7674e804a 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -289,8 +289,8 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_disable_pin(codec, "LLINEIN");
-       snd_soc_dapm_disable_pin(codec, "RLINEIN");
+       snd_soc_dapm_nc_pin(codec, "LLINEIN");
+       snd_soc_dapm_nc_pin(codec, "RLINEIN");
 
        /* Add corgi specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
index d9c3f7b28be212ecdb7cc1bf62ce22d09f2808df..e6ff6929ab4b799f7b9875144681469c15e6d8fe 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
index f84f7d8db09a0f19d5eb75089203bd603f25708f..4d9930c52789989313a8a1189bbc99b26160d8b2 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -242,8 +242,8 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_disable_pin(codec, "LLINEIN");
-       snd_soc_dapm_disable_pin(codec, "RLINEIN");
+       snd_soc_dapm_nc_pin(codec, "LLINEIN");
+       snd_soc_dapm_nc_pin(codec, "RLINEIN");
        snd_soc_dapm_enable_pin(codec, "MICIN");
 
        /* Add poodle specific controls */
index 39d19212f6d3c3fb5a3bfe4cb828d5294c25a82a..64057b1d220df8f133114743210098963c4e486f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *         lrg@slimlogic.co.uk
  *
  *  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
@@ -366,6 +366,6 @@ module_init(pxa2xx_i2s_init);
 module_exit(pxa2xx_i2s_exit);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
 MODULE_LICENSE("GPL");
index 3d4738c06e7eecc239abd796cb325b63766dff71..8f89188e541e90c06f28eacd0bd5a8b8d5f028ad 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -291,13 +291,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
        int i, err;
 
        /* NC codec pins */
-       snd_soc_dapm_disable_pin(codec, "RINPUT1");
-       snd_soc_dapm_disable_pin(codec, "LINPUT2");
-       snd_soc_dapm_disable_pin(codec, "RINPUT2");
-       snd_soc_dapm_disable_pin(codec, "LINPUT3");
-       snd_soc_dapm_disable_pin(codec, "RINPUT3");
-       snd_soc_dapm_disable_pin(codec, "OUT3");
-       snd_soc_dapm_disable_pin(codec, "MONO1");
+       snd_soc_dapm_nc_pin(codec, "RINPUT1");
+       snd_soc_dapm_nc_pin(codec, "LINPUT2");
+       snd_soc_dapm_nc_pin(codec, "RINPUT2");
+       snd_soc_dapm_nc_pin(codec, "LINPUT3");
+       snd_soc_dapm_nc_pin(codec, "RINPUT3");
+       snd_soc_dapm_nc_pin(codec, "OUT3");
+       snd_soc_dapm_nc_pin(codec, "MONO1");
 
        /* Add spitz specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
index 2baaa750f123013f566fb351e972651a967db382..afefe41b8c46c9f47ae255b14ec1ebed56e3522e 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
  *          Richard Purdie <richard@openedhand.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -190,8 +190,8 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_disable_pin(codec, "OUT3");
-       snd_soc_dapm_disable_pin(codec, "MONOOUT");
+       snd_soc_dapm_nc_pin(codec, "OUT3");
+       snd_soc_dapm_nc_pin(codec, "MONOOUT");
 
        /* add tosa specific controls */
        for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
index 73a50e93a9a222e5296f9a0d5191f9756a275a64..87ddfefcc2fba18b821f3b154fbe03d86e1bf3e7 100644 (file)
@@ -511,21 +511,20 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
        DBG("Entered %s\n", __func__);
 
        /* set up NC codec pins */
-       snd_soc_dapm_disable_pin(codec, "LOUT2");
-       snd_soc_dapm_disable_pin(codec, "ROUT2");
-       snd_soc_dapm_disable_pin(codec, "OUT3");
-       snd_soc_dapm_disable_pin(codec, "OUT4");
-       snd_soc_dapm_disable_pin(codec, "LINE1");
-       snd_soc_dapm_disable_pin(codec, "LINE2");
-
-
-       /* set endpoints to default mode */
-       set_scenario_endpoints(codec, NEO_AUDIO_OFF);
+       snd_soc_dapm_nc_pin(codec, "LOUT2");
+       snd_soc_dapm_nc_pin(codec, "ROUT2");
+       snd_soc_dapm_nc_pin(codec, "OUT3");
+       snd_soc_dapm_nc_pin(codec, "OUT4");
+       snd_soc_dapm_nc_pin(codec, "LINE1");
+       snd_soc_dapm_nc_pin(codec, "LINE2");
 
        /* Add neo1973 specific widgets */
        snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
                                  ARRAY_SIZE(wm8753_dapm_widgets));
 
+       /* set endpoints to default mode */
+       set_scenario_endpoints(codec, NEO_AUDIO_OFF);
+
        /* add neo1973 specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
                err = snd_ctl_add(codec->card,
@@ -603,6 +602,8 @@ static int lm4857_i2c_probe(struct i2c_client *client,
 {
        DBG("Entered %s\n", __func__);
 
+       i2c = client;
+
        lm4857_write_regs();
        return 0;
 }
@@ -611,6 +612,8 @@ static int lm4857_i2c_remove(struct i2c_client *client)
 {
        DBG("Entered %s\n", __func__);
 
+       i2c = NULL;
+
        return 0;
 }
 
@@ -650,7 +653,7 @@ static void lm4857_shutdown(struct i2c_client *dev)
 }
 
 static const struct i2c_device_id lm4857_i2c_id[] = {
-       { "neo1973_lm4857", 0 }
+       { "neo1973_lm4857", 0 },
        { }
 };
 
@@ -668,48 +671,6 @@ static struct i2c_driver lm4857_i2c_driver = {
 };
 
 static struct platform_device *neo1973_snd_device;
-static struct i2c_client *lm4857_client;
-
-static int __init neo1973_add_lm4857_device(struct platform_device *pdev,
-                                           int i2c_bus,
-                                           unsigned short i2c_address)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-       int ret;
-
-       ret = i2c_add_driver(&lm4857_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add lm4857 driver\n");
-               return ret;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = i2c_address;
-       strlcpy(info.type, "neo1973_lm4857", I2C_NAME_SIZE);
-
-       adapter = i2c_get_adapter(i2c_bus);
-       if (!adapter) {
-               dev_err(&pdev->dev, "can't get i2c adapter %d\n", i2c_bus);
-               goto err_driver;
-       }
-
-       client = i2c_new_device(adapter, &info);
-       i2c_put_adapter(adapter);
-       if (!client) {
-               dev_err(&pdev->dev, "can't add lm4857 device at 0x%x\n",
-                       (unsigned int)info.addr);
-               goto err_driver;
-       }
-
-       lm4857_client = client;
-       return 0;
-
-err_driver:
-       i2c_del_driver(&lm4857_i2c_driver);
-       return -ENODEV;
-}
 
 static int __init neo1973_init(void)
 {
@@ -736,8 +697,8 @@ static int __init neo1973_init(void)
                return ret;
        }
 
-       ret = neo1973_add_lm4857_device(neo1973_snd_device,
-                                       neo1973_wm8753_setup, 0x7C);
+       ret = i2c_add_driver(&lm4857_i2c_driver);
+
        if (ret != 0)
                platform_device_unregister(neo1973_snd_device);
 
@@ -748,7 +709,6 @@ static void __exit neo1973_exit(void)
 {
        DBG("Entered %s\n", __func__);
 
-       i2c_unregister_device(lm4857_client);
        i2c_del_driver(&lm4857_i2c_driver);
        platform_device_unregister(neo1973_snd_device);
 }
index ad381138fc2e482e0bf0110a96cf32c385ba8c04..462e635dfc74bc084f2c140480c4e6fe8e8cd7cc 100644 (file)
@@ -4,8 +4,7 @@
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
  *
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *         with code, comments and ideas from :-
  *         Richard Purdie <richard@openedhand.com>
  *
@@ -1886,7 +1885,7 @@ module_init(snd_soc_init);
 module_exit(snd_soc_exit);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 MODULE_DESCRIPTION("ALSA SoC Core");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:soc-audio");
index 9ca9c08610fa85bfd7fa7967555f07e1c6ac8082..efbd0b37810aba581672c1208bf82a99a2d1554a 100644 (file)
@@ -2,8 +2,7 @@
  * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *
  *  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
@@ -1483,6 +1482,26 @@ int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
 
+/**
+ * snd_soc_dapm_nc_pin - permanently disable pin.
+ * @codec: SoC codec
+ * @pin: pin name
+ *
+ * Marks the specified pin as being not connected, disabling it along
+ * any parent or child widgets.  At present this is identical to
+ * snd_soc_dapm_disable_pin() but in future it will be extended to do
+ * additional things such as disabling controls which only affect
+ * paths through the pin.
+ *
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
+{
+       return snd_soc_dapm_set_pin(codec, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
+
 /**
  * snd_soc_dapm_get_pin_status - get audio pin status
  * @codec: audio codec
@@ -1521,6 +1540,6 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
 EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
 
 /* Module information */
-MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
+MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
 MODULE_LICENSE("GPL");