linux-omap2 : Update ASoC patches.
authorPhilip Balister <philip@balister.org>
Sun, 3 Aug 2008 12:38:39 +0000 (12:38 +0000)
committerPhilip Balister <philip@balister.org>
Sun, 3 Aug 2008 12:38:39 +0000 (12:38 +0000)
packages/linux/linux-omap2-git/beagleboard/ASoC-TWL4030-codec-driver.patch [new file with mode: 0644]
packages/linux/linux-omap2-git/beagleboard/ASoC-machine-driver-for-OMAP3-EVM.patch [new file with mode: 0644]
packages/linux/linux-omap2-git/beagleboard/ASoC-machine-driver-for_OMAP3-Beagle.patch [new file with mode: 0644]
packages/linux/linux-omap2_git.bb

diff --git a/packages/linux/linux-omap2-git/beagleboard/ASoC-TWL4030-codec-driver.patch b/packages/linux/linux-omap2-git/beagleboard/ASoC-TWL4030-codec-driver.patch
new file mode 100644 (file)
index 0000000..ef9a0ed
--- /dev/null
@@ -0,0 +1,831 @@
+From: Steve Sakoman <steve@sakoman.com>
+Date: Fri, 18 Jul 2008 16:41:27 +0000 (-0700)
+Subject: ASoC TWL4030 codec driver
+X-Git-Url: http://www.sakoman.net/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=commitdiff_plain;h=67b73de03016cc31b1f91af93c57b8e749c13520;hp=d3b3ae0fe6c71641da19c8de466ec366d39847e3
+
+ASoC TWL4030 codec driver
+
+Basic audio support for the TWL4030
+
+Signed-off-by: Steve Sakoman <steve@sakoman.com>
+---
+
+diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
+index 3903ab7..468536d 100644
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -44,3 +44,7 @@ config SND_SOC_CS4270_VD33_ERRATA
+ config SND_SOC_TLV320AIC3X
+       tristate
+       depends on SND_SOC && I2C
++
++config SND_SOC_TWL4030
++      tristate
++      depends on SND_SOC && I2C
+diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
+index 4e1314c..d2c0b12 100644
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -6,6 +6,7 @@ snd-soc-wm9712-objs := wm9712.o
+ snd-soc-wm9713-objs := wm9713.o
+ snd-soc-cs4270-objs := cs4270.o
+ snd-soc-tlv320aic3x-objs := tlv320aic3x.o
++snd-soc-twl4030-objs := twl4030.o
+ obj-$(CONFIG_SND_SOC_AC97_CODEC)      += snd-soc-ac97.o
+ obj-$(CONFIG_SND_SOC_WM8731)  += snd-soc-wm8731.o
+@@ -15,3 +16,4 @@ obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
+ obj-$(CONFIG_SND_SOC_WM9713)  += snd-soc-wm9713.o
+ obj-$(CONFIG_SND_SOC_CS4270)  += snd-soc-cs4270.o
+ obj-$(CONFIG_SND_SOC_TLV320AIC3X)     += snd-soc-tlv320aic3x.o
++obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
+diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
+new file mode 100644
+index 0000000..25a154c
+--- /dev/null
++++ b/sound/soc/codecs/twl4030.c
+@@ -0,0 +1,626 @@
++/*
++ * ALSA SoC TWL4030 codec driver
++ *
++ * Author:      Steve Sakoman, <steve@sakoman.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.
++ */
++
++#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 <linux/i2c/twl4030.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/initval.h>
++
++#include "twl4030.h"
++
++/*
++ * twl4030 register cache & default register settings
++ */
++static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
++      0x00, /* this register not used         */
++      0x93, /* REG_CODEC_MODE         (0x1)   */
++      0xc3, /* REG_OPTION             (0x2)   */
++      0x00, /* REG_UNKNOWN            (0x3)   */
++      0x00, /* REG_MICBIAS_CTL        (0x4)   */
++      0x34, /* REG_ANAMICL            (0x5)   */
++      0x14, /* REG_ANAMICR            (0x6)   */
++      0x0a, /* REG_AVADC_CTL          (0x7)   */
++      0x00, /* REG_ADCMICSEL          (0x8)   */
++      0x00, /* REG_DIGMIXING          (0x9)   */
++      0x0c, /* REG_ATXL1PGA           (0xA)   */
++      0x0c, /* REG_ATXR1PGA           (0xB)   */
++      0x00, /* REG_AVTXL2PGA          (0xC)   */
++      0x00, /* REG_AVTXR2PGA          (0xD)   */
++      0x01, /* REG_AUDIO_IF           (0xE)   */
++      0x00, /* REG_VOICE_IF           (0xF)   */
++      0x00, /* REG_ARXR1PGA           (0x10)  */
++      0x00, /* REG_ARXL1PGA           (0x11)  */
++      0x6c, /* REG_ARXR2PGA           (0x12)  */
++      0x6c, /* REG_ARXL2PGA           (0x13)  */
++      0x00, /* REG_VRXPGA             (0x14)  */
++      0x00, /* REG_VSTPGA             (0x15)  */
++      0x00, /* REG_VRX2ARXPGA         (0x16)  */
++      0x0c, /* REG_AVDAC_CTL          (0x17)  */
++      0x00, /* REG_ARX2VTXPGA         (0x18)  */
++      0x00, /* REG_ARXL1_APGA_CTL     (0x19)  */
++      0x00, /* REG_ARXR1_APGA_CTL     (0x1A)  */
++      0x4b, /* REG_ARXL2_APGA_CTL     (0x1B)  */
++      0x4b, /* REG_ARXR2_APGA_CTL     (0x1C)  */
++      0x00, /* REG_ATX2ARXPGA         (0x1D)  */
++      0x00, /* REG_BT_IF              (0x1E)  */
++      0x00, /* REG_BTPGA              (0x1F)  */
++      0x00, /* REG_BTSTPGA            (0x20)  */
++      0x00, /* REG_EAR_CTL            (0x21)  */
++      0x24, /* REG_HS_SEL             (0x22)  */
++      0x0a, /* REG_HS_GAIN_SET        (0x23)  */
++      0x00, /* REG_HS_POPN_SET        (0x24)  */
++      0x00, /* REG_PREDL_CTL          (0x25)  */
++      0x00, /* REG_PREDR_CTL          (0x26)  */
++      0x00, /* REG_PRECKL_CTL         (0x27)  */
++      0x00, /* REG_PRECKR_CTL         (0x28)  */
++      0x00, /* REG_HFL_CTL            (0x29)  */
++      0x00, /* REG_HFR_CTL            (0x2A)  */
++      0x00, /* REG_ALC_CTL            (0x2B)  */
++      0x00, /* REG_ALC_SET1           (0x2C)  */
++      0x00, /* REG_ALC_SET2           (0x2D)  */
++      0x00, /* REG_BOOST_CTL          (0x2E)  */
++      0x01, /* REG_SOFTVOL_CTL        (0x2F)  */
++      0x00, /* REG_DTMF_FREQSEL       (0x30)  */
++      0x00, /* REG_DTMF_TONEXT1H      (0x31)  */
++      0x00, /* REG_DTMF_TONEXT1L      (0x32)  */
++      0x00, /* REG_DTMF_TONEXT2H      (0x33)  */
++      0x00, /* REG_DTMF_TONEXT2L      (0x34)  */
++      0x00, /* REG_DTMF_TONOFF        (0x35)  */
++      0x00, /* REG_DTMF_WANONOFF      (0x36)  */
++      0x00, /* REG_I2S_RX_SCRAMBLE_H  (0x37)  */
++      0x00, /* REG_I2S_RX_SCRAMBLE_M  (0x38)  */
++      0x00, /* REG_I2S_RX_SCRAMBLE_L  (0x39)  */
++      0x16, /* REG_APLL_CTL           (0x3A)  */
++      0x00, /* REG_DTMF_CTL           (0x3B)  */
++      0x00, /* REG_DTMF_PGA_CTL2      (0x3C)  */
++      0x00, /* REG_DTMF_PGA_CTL1      (0x3D)  */
++      0x00, /* REG_MISC_SET_1         (0x3E)  */
++      0x00, /* REG_PCMBTMUX           (0x3F)  */
++      0x00, /* not used               (0x40)  */
++      0x00, /* not used               (0x41)  */
++      0x00, /* not used               (0x42)  */
++      0x00, /* REG_RX_PATH_SEL        (0x43)  */
++      0x00, /* REG_VDL_APGA_CTL       (0x44)  */
++      0x00, /* REG_VIBRA_CTL          (0x45)  */
++      0x00, /* REG_VIBRA_SET          (0x46)  */
++      0x00, /* REG_VIBRA_PWM_SET      (0x47)  */
++      0x00, /* REG_ANAMIC_GAIN        (0x48)  */
++      0x00, /* REG_MISC_SET_2         (0x49)  */
++};
++
++static void twl4030_dump_registers(void)
++{
++      int i = 0;
++      u8 data;
++
++      printk(KERN_INFO "TWL 4030 Register dump for Audio Module\n");
++
++      for (i = REG_CODEC_MODE; i <= REG_MISC_SET_2; i++) {
++              twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &data, i);
++              printk(KERN_INFO "Register[0x%02x]=0x%02x\n", i, data);
++      }
++}
++
++struct twl4030_priv {
++      unsigned int dummy;
++};
++
++/*
++ * read twl4030 register cache
++ */
++static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec,
++      unsigned int reg)
++{
++      u8 *cache = codec->reg_cache;
++
++      return cache[reg];
++}
++
++/*
++ * write twl4030 register cache
++ */
++static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
++                                              u8 reg, u8 value)
++{
++      u8 *cache = codec->reg_cache;
++
++      if (reg >= TWL4030_CACHEREGNUM)
++              return;
++      cache[reg] = value;
++}
++
++/*
++ * write to the twl4030 register space
++ */
++static int twl4030_write(struct snd_soc_codec *codec,
++                      unsigned int reg, unsigned int value)
++{
++      twl4030_write_reg_cache(codec, reg, value);
++      return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
++}
++
++static void twl4030_init_chip(void)
++{
++      unsigned char byte;
++      int i;
++
++      twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
++              twl4030_reg[REG_CODEC_MODE] & 0xfd, REG_CODEC_MODE);
++
++      udelay(10); /* delay for power settling */
++
++      for (i = REG_OPTION; i <= REG_MISC_SET_2; i++)
++              twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
++                                      twl4030_reg[i], i);
++
++      twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
++              twl4030_reg[REG_CODEC_MODE], REG_CODEC_MODE);
++
++      udelay(10); /* delay for power settling */
++
++      /* initiate offset cancellation */
++      twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
++              twl4030_reg[REG_ANAMICL] | 0x80, REG_ANAMICL);
++
++      /* wait for offset cancellation to complete */
++      twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, REG_ANAMICL);
++      while ((byte & 0x80) == 0x80)
++              twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE,
++                                      &byte, REG_ANAMICL);
++
++      twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
++              twl4030_reg[REG_MISC_SET_1] | 0x02, REG_MISC_SET_1);
++
++}
++
++static const struct snd_kcontrol_new twl4030_snd_controls[] = {
++      SOC_DOUBLE_R("Master Playback Volume",
++               REG_ARXL2PGA, REG_ARXR2PGA,
++              0, 127, 0),
++      SOC_DOUBLE_R("Capture Volume",
++               REG_ATXL1PGA, REG_ATXR1PGA,
++              0, 127, 0),
++};
++
++/* add non dapm controls */
++static int twl4030_add_controls(struct snd_soc_codec *codec)
++{
++      int err, i;
++
++      for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) {
++              err = snd_ctl_add(codec->card,
++                                snd_soc_cnew(&twl4030_snd_controls[i],
++                                              codec, NULL));
++              if (err < 0)
++                      return err;
++      }
++
++      return 0;
++}
++
++static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
++      SND_SOC_DAPM_INPUT("INL"),
++      SND_SOC_DAPM_INPUT("INR"),
++
++      SND_SOC_DAPM_OUTPUT("OUTL"),
++      SND_SOC_DAPM_OUTPUT("OUTR"),
++
++      SND_SOC_DAPM_DAC("DACL", "Left Playback", SND_SOC_NOPM, 0, 0),
++      SND_SOC_DAPM_DAC("DACR", "Right Playback", SND_SOC_NOPM, 0, 0),
++
++      SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0),
++      SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0),
++};
++
++static const char *intercon[][3] = {
++      /* outputs */
++      {"OUTL", NULL, "DACL"},
++      {"OUTR", NULL, "DACR"},
++
++      /* inputs */
++      {"ADCL", NULL, "INL"},
++      {"ADCR", NULL, "INR"},
++
++      /* terminator */
++      {NULL, NULL, NULL},
++};
++
++static int twl4030_add_widgets(struct snd_soc_codec *codec)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(twl4030_dapm_widgets); i++)
++              snd_soc_dapm_new_control(codec, &twl4030_dapm_widgets[i]);
++
++      /* set up audio path interconnects */
++      for (i = 0; intercon[i][0] != NULL; i++)
++              snd_soc_dapm_connect_input(codec, intercon[i][0],
++                      intercon[i][1], intercon[i][2]);
++
++      snd_soc_dapm_new_widgets(codec);
++      return 0;
++}
++
++static int twl4030_dapm_event(struct snd_soc_codec *codec, int event)
++{
++
++      printk(KERN_INFO "TWL4030 Audio Codec dapm event\n");
++      switch (event) {
++      case SNDRV_CTL_POWER_D0: /* full On */
++              break;
++      case SNDRV_CTL_POWER_D1: /* partial On */
++      case SNDRV_CTL_POWER_D2: /* partial On */
++              break;
++      case SNDRV_CTL_POWER_D3hot: /* off, with power */
++              break;
++      case SNDRV_CTL_POWER_D3cold: /* off, without power */
++              break;
++      }
++      codec->dapm_state = event;
++
++      return 0;
++}
++
++static void twl4030_power_up(struct snd_soc_codec *codec, u8 mode)
++{
++      u8 popn, hsgain;
++
++      twl4030_write(codec, REG_CODEC_MODE, mode & ~CODECPDZ);
++      twl4030_write(codec, REG_CODEC_MODE, mode | CODECPDZ);
++      udelay(10);
++
++      popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET);
++      popn &= RAMP_DELAY;
++      popn |= VMID_EN | RAMP_DELAY_161MS;
++      twl4030_write(codec, REG_HS_POPN_SET, popn);
++
++      hsgain = HSR_GAIN_0DB | HSL_GAIN_0DB;
++      twl4030_write(codec, REG_HS_GAIN_SET, hsgain);
++
++      popn |= RAMP_EN;
++      twl4030_write(codec, REG_HS_POPN_SET, popn);
++}
++
++static void twl4030_power_down(struct snd_soc_codec *codec)
++{
++      u8 popn, hsgain, mode;
++
++      popn = twl4030_read_reg_cache(codec, REG_HS_POPN_SET);
++      popn &= ~RAMP_EN;
++      twl4030_write(codec, REG_HS_POPN_SET, popn);
++
++      hsgain = HSR_GAIN_PWR_DOWN | HSL_GAIN_PWR_DOWN;
++      twl4030_write(codec, REG_HS_GAIN_SET, hsgain);
++
++      popn &= ~VMID_EN;
++      twl4030_write(codec, REG_HS_POPN_SET, popn);
++
++      mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE);
++      mode &= ~CODECPDZ;
++      twl4030_write(codec, REG_CODEC_MODE, mode);
++      udelay(10);
++}
++
++
++static int twl4030_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;
++      struct twl4030_priv *twl4030 = codec->private_data;
++      u8 mode, old_mode, format, old_format;
++
++
++      /* bit rate */
++      old_mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE) & ~CODECPDZ;
++      mode = old_mode;
++      mode &= ~APLL_RATE;
++      switch (params_rate(params)) {
++      case 44100:
++              mode |= APLL_RATE_44100;
++              break;
++      case 48000:
++              mode |= APLL_RATE_48000;
++              break;
++      default:
++              printk(KERN_INFO "TWL4030 hw params: unknown rate %d\n",
++                      params_rate(params));
++              return -EINVAL;
++      }
++
++      if (mode != old_mode) {
++              /* change rate and turn codec back on */
++              twl4030_write(codec, REG_CODEC_MODE, mode);
++              mode |= CODECPDZ;
++              twl4030_write(codec, REG_CODEC_MODE, mode);
++      }
++
++      /* sample size */
++      old_format = twl4030_read_reg_cache(codec, REG_AUDIO_IF);
++      format = old_format;
++      format &= ~DATA_WIDTH;
++      switch (params_format(params)) {
++      case SNDRV_PCM_FORMAT_S16_LE:
++              format |= DATA_WIDTH_16S_16W;
++              break;
++      case SNDRV_PCM_FORMAT_S24_LE:
++              format |= DATA_WIDTH_32S_24W;
++              break;
++      default:
++              printk(KERN_INFO "TWL4030 hw params: unknown format %d\n",
++                      params_format(params));
++              return -EINVAL;
++      }
++
++      if (format != old_format) {
++
++              /* turn off codec before changing format */
++              mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE);
++              mode &= ~CODECPDZ;
++              twl4030_write(codec, REG_CODEC_MODE, mode);
++
++              /* change format */
++              twl4030_write(codec, REG_AUDIO_IF, format);
++
++              /* turn on codec */
++              mode |= CODECPDZ;
++              twl4030_write(codec, REG_CODEC_MODE, mode);
++      }
++      return 0;
++}
++
++static int twl4030_mute(struct snd_soc_codec_dai *dai, int mute)
++{
++      struct snd_soc_codec *codec = dai->codec;
++
++      u8 ldac_reg = twl4030_read_reg_cache(codec, REG_ARXL2PGA);
++      u8 rdac_reg = twl4030_read_reg_cache(codec, REG_ARXR2PGA);
++
++      if (mute) {
++              twl4030_write(codec, REG_ARXL2PGA, 0x00);
++              twl4030_write(codec, REG_ARXR2PGA, 0x00);
++              twl4030_write_reg_cache(codec, REG_ARXL2PGA, ldac_reg);
++              twl4030_write_reg_cache(codec, REG_ARXR2PGA, rdac_reg);
++      } else {
++              twl4030_write(codec, REG_ARXL2PGA, ldac_reg);
++              twl4030_write(codec, REG_ARXR2PGA, rdac_reg);
++      }
++
++      return 0;
++}
++
++static int twl4030_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
++                           unsigned int fmt)
++{
++      struct snd_soc_codec *codec = codec_dai->codec;
++      struct twl4030_priv *twl4030 = codec->private_data;
++      u8 mode, old_format, format;
++
++      /* get format */
++      old_format = twl4030_read_reg_cache(codec, REG_AUDIO_IF);
++      format = old_format;
++
++      /* set master/slave audio interface */
++      switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++      case SND_SOC_DAIFMT_CBM_CFM:
++              format &= ~(AIF_SLAVE_EN);
++              format |= CLK256FS_EN;
++              break;
++      case SND_SOC_DAIFMT_CBS_CFS:
++              format &= ~(CLK256FS_EN);
++              format |= AIF_SLAVE_EN;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      /* interface format */
++      format &= ~AIF_FORMAT;
++      switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++      case SND_SOC_DAIFMT_I2S:
++              /* printk(KERN_INFO "TWL4030 set dai fmt: i2s\n"); */
++              format |= AIF_FORMAT_CODEC;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      if (format != old_format) {
++
++              /* turn off codec before changing format */
++              mode = twl4030_read_reg_cache(codec, REG_CODEC_MODE);
++              mode &= ~CODECPDZ;
++              twl4030_write(codec, REG_CODEC_MODE, mode);
++
++              /* change format */
++              twl4030_write(codec, REG_AUDIO_IF, format);
++
++              mode |= CODECPDZ;
++              twl4030_write(codec, REG_CODEC_MODE, mode);
++      }
++
++      return 0;
++}
++
++#define TWL4030_RATES  (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
++#define TWL4030_FORMATS        (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
++
++struct snd_soc_codec_dai twl4030_dai = {
++      .name = "twl4030",
++      .playback = {
++              .stream_name = "Playback",
++              .channels_min = 2,
++              .channels_max = 2,
++              .rates = TWL4030_RATES,
++              .formats = TWL4030_FORMATS,},
++      .capture = {
++              .stream_name = "Capture",
++              .channels_min = 2,
++              .channels_max = 2,
++              .rates = TWL4030_RATES,
++              .formats = TWL4030_FORMATS,},
++      .ops = {
++              .hw_params = twl4030_hw_params,
++      },
++      .dai_ops = {
++              .digital_mute = twl4030_mute,
++              .set_fmt = twl4030_set_dai_fmt,
++      }
++};
++EXPORT_SYMBOL_GPL(twl4030_dai);
++
++static int twl4030_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;
++
++      printk(KERN_INFO "TWL4030 Audio Codec suspend\n");
++      twl4030_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
++
++      return 0;
++}
++
++static int twl4030_resume(struct platform_device *pdev)
++{
++      struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++      struct snd_soc_codec *codec = socdev->codec;
++      int i;
++      u16 *cache = codec->reg_cache;
++
++      printk(KERN_INFO "TWL4030 Audio Codec resume\n");
++      /* Sync reg_cache with the hardware */
++      for (i = REG_CODEC_MODE; i <= REG_MISC_SET_2; i++)
++              twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, cache[i], i);
++
++      twl4030_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
++      twl4030_dapm_event(codec, codec->suspend_dapm_state);
++      return 0;
++}
++
++/*
++ * initialize the driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++
++static int twl4030_init(struct snd_soc_device *socdev)
++{
++      struct snd_soc_codec *codec = socdev->codec;
++      int ret = 0;
++
++      printk(KERN_INFO "TWL4030 Audio Codec init \n");
++
++      codec->name = "twl4030";
++      codec->owner = THIS_MODULE;
++      codec->read = twl4030_read_reg_cache;
++      codec->write = twl4030_write;
++      codec->dapm_event = twl4030_dapm_event;
++      codec->dai = &twl4030_dai;
++      codec->num_dai = 1;
++      codec->reg_cache_size = sizeof(twl4030_reg);
++      codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
++                                      GFP_KERNEL);
++      if (codec->reg_cache == NULL)
++              return -ENOMEM;
++
++      /* register pcms */
++      ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++      if (ret < 0) {
++              printk(KERN_ERR "twl4030: failed to create pcms\n");
++              goto pcm_err;
++      }
++
++      twl4030_add_controls(codec);
++      twl4030_add_widgets(codec);
++
++      ret = snd_soc_register_card(socdev);
++      if (ret < 0) {
++              printk(KERN_ERR "twl4030: failed to register card\n");
++              goto card_err;
++      }
++
++      twl4030_init_chip();
++      twl4030_power_up(codec, APLL_RATE_44100 | OPT_MODE);
++
++      return ret;
++
++card_err:
++      printk(KERN_INFO "TWL4030 Audio Codec init card error\n");
++      snd_soc_free_pcms(socdev);
++      snd_soc_dapm_free(socdev);
++pcm_err:
++      printk(KERN_INFO "TWL4030 Audio Codec init pcm error\n");
++      kfree(codec->reg_cache);
++      return ret;
++}
++
++static struct snd_soc_device *twl4030_socdev;
++
++static int twl4030_probe(struct platform_device *pdev)
++{
++      struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++      struct snd_soc_codec *codec;
++      struct twl4030_priv *twl4030;
++
++      codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
++      if (codec == NULL)
++              return -ENOMEM;
++
++      twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
++      if (twl4030 == NULL) {
++              kfree(codec);
++              return -ENOMEM;
++      }
++
++      codec->private_data = twl4030;
++      socdev->codec = codec;
++      mutex_init(&codec->mutex);
++      INIT_LIST_HEAD(&codec->dapm_widgets);
++      INIT_LIST_HEAD(&codec->dapm_paths);
++
++      twl4030_socdev = socdev;
++      twl4030_init(socdev);
++
++      return 0;
++}
++
++static int twl4030_remove(struct platform_device *pdev)
++{
++      struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++      struct snd_soc_codec *codec = socdev->codec;
++
++      printk(KERN_INFO "TWL4030 Audio Codec remove\n");
++      kfree(codec->private_data);
++      kfree(codec);
++
++      return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_twl4030 = {
++      .probe = twl4030_probe,
++      .remove = twl4030_remove,
++      .suspend = twl4030_suspend,
++      .resume = twl4030_resume,
++};
++EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
++
++MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
++MODULE_AUTHOR("Steve Sakoman");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
+new file mode 100644
+index 0000000..6eecde1
+--- /dev/null
++++ b/sound/soc/codecs/twl4030.h
+@@ -0,0 +1,152 @@
++/*
++ * ALSA SoC TWL4030 codec driver
++ *
++ * Author:      Steve Sakoman, <steve@sakoman.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.
++ */
++
++#ifndef __TWL4030_AUDIO_H__
++#define __TWL4030_AUDIO_H__
++
++#define REG_CODEC_MODE                0x1
++#define REG_OPTION            0x2
++#define REG_UNKNOWN           0x3
++#define REG_MICBIAS_CTL               0x4
++#define REG_ANAMICL           0x5
++#define REG_ANAMICR           0x6
++#define REG_AVADC_CTL         0x7
++#define REG_ADCMICSEL         0x8
++#define REG_DIGMIXING         0x9
++#define REG_ATXL1PGA          0xA
++#define REG_ATXR1PGA          0xB
++#define REG_AVTXL2PGA         0xC
++#define REG_AVTXR2PGA         0xD
++#define REG_AUDIO_IF          0xE
++#define REG_VOICE_IF          0xF
++#define REG_ARXR1PGA          0x10
++#define REG_ARXL1PGA          0x11
++#define REG_ARXR2PGA          0x12
++#define REG_ARXL2PGA          0x13
++#define REG_VRXPGA            0x14
++#define REG_VSTPGA            0x15
++#define REG_VRX2ARXPGA                0x16
++#define REG_AVDAC_CTL         0x17
++#define REG_ARX2VTXPGA                0x18
++#define REG_ARXL1_APGA_CTL    0x19
++#define REG_ARXR1_APGA_CTL    0x1A
++#define REG_ARXL2_APGA_CTL    0x1B
++#define REG_ARXR2_APGA_CTL    0x1C
++#define REG_ATX2ARXPGA                0x1D
++#define REG_BT_IF             0x1E
++#define REG_BTPGA             0x1F
++#define REG_BTSTPGA           0x20
++#define REG_EAR_CTL           0x21
++#define REG_HS_SEL            0x22
++#define REG_HS_GAIN_SET               0x23
++#define REG_HS_POPN_SET               0x24
++#define REG_PREDL_CTL         0x25
++#define REG_PREDR_CTL         0x26
++#define REG_PRECKL_CTL                0x27
++#define REG_PRECKR_CTL                0x28
++#define REG_HFL_CTL           0x29
++#define REG_HFR_CTL           0x2A
++#define REG_ALC_CTL           0x2B
++#define REG_ALC_SET1          0x2C
++#define REG_ALC_SET2          0x2D
++#define REG_BOOST_CTL         0x2E
++#define REG_SOFTVOL_CTL               0x2F
++#define REG_DTMF_FREQSEL      0x30
++#define REG_DTMF_TONEXT1H     0x31
++#define REG_DTMF_TONEXT1L     0x32
++#define REG_DTMF_TONEXT2H     0x33
++#define REG_DTMF_TONEXT2L     0x34
++#define REG_DTMF_TONOFF               0x35
++#define REG_DTMF_WANONOFF     0x36
++#define REG_I2S_RX_SCRAMBLE_H 0x37
++#define REG_I2S_RX_SCRAMBLE_M 0x38
++#define REG_I2S_RX_SCRAMBLE_L 0x39
++#define REG_APLL_CTL          0x3A
++#define REG_DTMF_CTL          0x3B
++#define REG_DTMF_PGA_CTL2     0x3C
++#define REG_DTMF_PGA_CTL1     0x3D
++#define REG_MISC_SET_1                0x3E
++#define REG_PCMBTMUX          0x3F
++#define REG_RX_PATH_SEL               0x43
++#define REG_VDL_APGA_CTL      0x44
++#define REG_VIBRA_CTL         0x45
++#define REG_VIBRA_SET         0x46
++#define REG_VIBRA_PWM_SET     0x47
++#define REG_ANAMIC_GAIN               0x48
++#define REG_MISC_SET_2                0x49
++
++#define TWL4030_CACHEREGNUM   (REG_MISC_SET_2 + 1)
++
++/* Bitfield Definitions */
++
++/* CODEC_MODE (0x01) Fields */
++
++#define APLL_RATE             0xF0
++#define APLL_RATE_8000                0x00
++#define APLL_RATE_11025               0x10
++#define APLL_RATE_12000               0x20
++#define APLL_RATE_16000               0x40
++#define APLL_RATE_22050               0x50
++#define APLL_RATE_24000               0x60
++#define APLL_RATE_32000               0x80
++#define APLL_RATE_44100               0x90
++#define APLL_RATE_48000               0xa0
++#define SEL_16K                       0x04
++#define CODECPDZ              0x02
++#define OPT_MODE              0x01
++
++/* AUDIO_IF (0x0E) Fields */
++
++#define AIF_SLAVE_EN          0x80
++#define DATA_WIDTH            0x60
++#define DATA_WIDTH_16S_16W    0x00
++#define DATA_WIDTH_32S_16W    0x40
++#define DATA_WIDTH_32S_24W    0x60
++#define AIF_FORMAT            0x18
++#define AIF_FORMAT_CODEC      0x00
++#define AIF_FORMAT_LEFT               0x08
++#define AIF_FORMAT_RIGHT      0x10
++#define AIF_FORMAT_TDM                0x18
++#define AIF_TRI_EN            0x04
++#define CLK256FS_EN           0x02
++#define AIF_EN                        0x01
++
++/* HS_GAIN_SET (0x23) Fields */
++
++#define HSR_GAIN              0x0c
++#define HSR_GAIN_PWR_DOWN     0x00
++#define HSR_GAIN_PLUS_6DB     0x04
++#define HSR_GAIN_0DB          0x08
++#define HSR_GAIN_MINUS_6DB    0x0c
++#define HSL_GAIN              0x0c
++#define HSL_GAIN_PWR_DOWN     0x00
++#define HSL_GAIN_PLUS_6DB     0x01
++#define HSL_GAIN_0DB          0x02
++#define HSL_GAIN_MINUS_6DB    0x03
++
++/* HS_POPN_SET (0x24) Fields */
++
++#define VMID_EN                       0x40
++#define       EXTMUTE                 0x20
++#define RAMP_DELAY            0x1C
++#define RAMP_DELAY_20MS               0x00
++#define RAMP_DELAY_40MS               0x04
++#define RAMP_DELAY_81MS               0x08
++#define RAMP_DELAY_161MS      0x0c
++#define RAMP_DELAY_323MS      0x10
++#define RAMP_DELAY_645MS      0x14
++#define RAMP_DELAY_1291MS     0x18
++#define RAMP_DELAY_2581MS     0x1c
++#define RAMP_EN                       0x02
++
++extern struct snd_soc_codec_dai twl4030_dai;
++extern struct snd_soc_codec_device soc_codec_dev_twl4030;
++
++#endif        /* End of __TWL4030_AUDIO_H__ */
diff --git a/packages/linux/linux-omap2-git/beagleboard/ASoC-machine-driver-for-OMAP3-EVM.patch b/packages/linux/linux-omap2-git/beagleboard/ASoC-machine-driver-for-OMAP3-EVM.patch
new file mode 100644 (file)
index 0000000..ea8108e
--- /dev/null
@@ -0,0 +1,278 @@
+From: Steve Sakoman <steve@sakoman.com>
+Date: Fri, 18 Jul 2008 16:41:37 +0000 (-0700)
+Subject: ASoC machine driver for OMAP3 EVM
+X-Git-Url: http://www.sakoman.net/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=commitdiff_plain;h=2e6af042b4af677e62e32d048e770f6755e67a7f
+
+ASoC machine driver for OMAP3 EVM
+
+Add basic audio support for OMAP3 EVM
+
+Signed-off-by: Steve Sakoman <steve@sakoman.com>
+---
+
+diff --git a/arch/arm/configs/omap3_beagle_defconfig b/arch/arm/configs/omap3_beagle_defconfig
+index cce83e5..a48780a 100644
+--- a/arch/arm/configs/omap3_beagle_defconfig
++++ b/arch/arm/configs/omap3_beagle_defconfig
+@@ -735,7 +735,82 @@ CONFIG_FONT_8x16=y
+ #
+ # Sound
+ #
+-# CONFIG_SOUND is not set
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++CONFIG_SND_HWDEP=y
++CONFIG_SND_RAWMIDI=y
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_PCM_OSS_PLUGINS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++CONFIG_SND_VERBOSE_PRINTK=y
++CONFIG_SND_DEBUG=y
++CONFIG_SND_DEBUG_DETECT=y
++CONFIG_SND_PCM_XRUN_DEBUG=y
++
++#
++# Generic devices
++#
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++# CONFIG_SND_OMAP_AIC23 is not set
++# CONFIG_SND_OMAP_TSC2101 is not set
++# CONFIG_SND_SX1 is not set
++# CONFIG_SND_OMAP_TSC2102 is not set
++# CONFIG_SND_OMAP24XX_EAC is not set
++
++#
++# SPI devices
++#
++
++#
++# USB devices
++#
++CONFIG_SND_USB_AUDIO=y
++# CONFIG_SND_USB_CAIAQ is not set
++
++#
++# System on Chip audio support
++#
++CONFIG_SND_SOC=y
++
++#
++# ALSA SoC audio for Freescale SOCs
++#
++
++#
++# SoC Audio for the Texas Instruments OMAP
++#
++CONFIG_SND_OMAP_SOC=y
++CONFIG_SND_OMAP_SOC_MCBSP=y
++CONFIG_SND_OMAP_SOC_OMAP3BEAGLE=y
++CONFIG_SND_SOC_TWL4030=y
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=y
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
+ # CONFIG_HID_SUPPORT is not set
+ CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
+index 0230d83..0def5ba 100644
+--- a/sound/soc/omap/Kconfig
++++ b/sound/soc/omap/Kconfig
+@@ -16,4 +16,12 @@ config SND_OMAP_SOC_N810
+       help
+         Say Y if you want to add support for SoC audio on Nokia N810.
++config SND_OMAP_SOC_OMAP3EVM
++      tristate "SoC Audio support for OMAP3 EVM"
++      depends on SND_OMAP_SOC && MACH_OMAP3EVM
++      select SND_OMAP_SOC_MCBSP
++      select SND_SOC_TWL4030
++      help
++        Say Y if you want to add support for SoC audio on the OMAP3 EVM.
++
+ endmenu
+diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
+index d8d8d58..985eddc 100644
+--- a/sound/soc/omap/Makefile
++++ b/sound/soc/omap/Makefile
+@@ -7,5 +7,8 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
+ # OMAP Machine Support
+ snd-soc-n810-objs := n810.o
++snd-soc-omap3evm-objs := omap3evm.o
+ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
++obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
++
+diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
+new file mode 100644
+index 0000000..d436bb4
+--- /dev/null
++++ b/sound/soc/omap/omap3evm.c
+@@ -0,0 +1,142 @@
++/*
++ * omap3evm.c  --  SoC audio for OMAP3 EVM
++ *
++ * Author: Steve Sakoman <steve@sakoman.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 <asm/arch/hardware.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/mcbsp.h>
++
++#include "omap-mcbsp.h"
++#include "omap-pcm.h"
++#include "../codecs/twl4030.h"
++
++static int omap3evm_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_codec_dai *codec_dai = rtd->dai->codec_dai;
++      struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
++      int ret;
++
++      /* Set codec DAI configuration */
++      ret = codec_dai->dai_ops.set_fmt(codec_dai,
++                                       SND_SOC_DAIFMT_I2S |
++                                       SND_SOC_DAIFMT_NB_NF |
++                                       SND_SOC_DAIFMT_CBM_CFM);
++      if (ret < 0) {
++      printk(KERN_INFO "can't set codec DAI configuration\n");
++              return ret;
++      }
++
++      /* Set cpu DAI configuration */
++      ret = cpu_dai->dai_ops.set_fmt(cpu_dai,
++                                     SND_SOC_DAIFMT_I2S |
++                                     SND_SOC_DAIFMT_NB_NF |
++                                     SND_SOC_DAIFMT_CBM_CFM);
++      if (ret < 0) {
++      printk(KERN_INFO "can't set cpu DAI configuration\n");
++              return ret;
++      }
++
++      return 0;
++}
++
++static struct snd_soc_ops omap3evm_ops = {
++      .hw_params = omap3evm_hw_params,
++};
++
++/* Digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link omap3evm_dai = {
++      .name = "TWL4030",
++      .stream_name = "TWL4030",
++      .cpu_dai = &omap_mcbsp_dai[0],
++      .codec_dai = &twl4030_dai,
++      .ops = &omap3evm_ops,
++};
++
++/* Audio machine driver */
++static struct snd_soc_machine snd_soc_machine_omap3evm = {
++      .name = "omap3evm",
++      .dai_link = &omap3evm_dai,
++      .num_links = 1,
++};
++
++/* Audio subsystem */
++static struct snd_soc_device omap3evm_snd_devdata = {
++      .machine = &snd_soc_machine_omap3evm,
++      .platform = &omap_soc_platform,
++      .codec_dev = &soc_codec_dev_twl4030,
++};
++
++static struct platform_device *omap3evm_snd_device;
++
++static int __init omap3evm_soc_init(void)
++{
++      int ret;
++
++      printk(KERN_INFO "OMAP3 EVM SoC init\n");
++      if (!machine_is_omap3evm()) {
++              printk(KERN_INFO "Not OMAP3 EVM!\n");
++              return -ENODEV;
++      }
++
++      omap3evm_snd_device = platform_device_alloc("soc-audio", -1);
++      if (!omap3evm_snd_device) {
++              printk(KERN_INFO "Platform device allocation failed\n");
++              return -ENOMEM;
++      }
++
++      platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata);
++      omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev;
++      *(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1; /* McBSP2 */
++
++      ret = platform_device_add(omap3evm_snd_device);
++      if (ret)
++              goto err1;
++
++      return 0;
++
++err1:
++      printk(KERN_INFO "Unable to add platform device\n");
++      platform_device_put(omap3evm_snd_device);
++
++      return ret;
++}
++
++static void __exit omap3evm_soc_exit(void)
++{
++      printk(KERN_INFO "OMAP3 EVM SoC exit\n");
++      platform_device_unregister(omap3evm_snd_device);
++}
++
++module_init(omap3evm_soc_init);
++module_exit(omap3evm_soc_exit);
++
++MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
++MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM");
++MODULE_LICENSE("GPL");
diff --git a/packages/linux/linux-omap2-git/beagleboard/ASoC-machine-driver-for_OMAP3-Beagle.patch b/packages/linux/linux-omap2-git/beagleboard/ASoC-machine-driver-for_OMAP3-Beagle.patch
new file mode 100644 (file)
index 0000000..9343a9c
--- /dev/null
@@ -0,0 +1,279 @@
+From: Steve Sakoman <steve@sakoman.com>
+Date: Fri, 18 Jul 2008 16:41:49 +0000 (-0700)
+Subject: ASoC machine driver for OMAP3 Beagle
+X-Git-Url: http://www.sakoman.net/cgi-bin/gitweb.cgi?p=linux-omap-2.6.git;a=commitdiff_plain;h=543a3a0cd4c6f68be6f084ccfe63ec5a514eba59
+
+ASoC machine driver for OMAP3 Beagle
+
+Add basic audio support for OMAP3 Beagle
+
+Signed-off-by: Steve Sakoman <steve@sakoman.com>
+---
+
+diff --git a/arch/arm/configs/omap3_evm_defconfig b/arch/arm/configs/omap3_evm_defconfig
+index 718c914..4ac730c 100644
+--- a/arch/arm/configs/omap3_evm_defconfig
++++ b/arch/arm/configs/omap3_evm_defconfig
+@@ -835,7 +835,82 @@ CONFIG_DUMMY_CONSOLE=y
+ #
+ # Sound
+ #
+-# CONFIG_SOUND is not set
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++CONFIG_SND_HWDEP=y
++CONFIG_SND_RAWMIDI=y
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_PCM_OSS_PLUGINS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++CONFIG_SND_VERBOSE_PRINTK=y
++CONFIG_SND_DEBUG=y
++CONFIG_SND_DEBUG_DETECT=y
++CONFIG_SND_PCM_XRUN_DEBUG=y
++
++#
++# Generic devices
++#
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++# CONFIG_SND_OMAP_AIC23 is not set
++# CONFIG_SND_OMAP_TSC2101 is not set
++# CONFIG_SND_SX1 is not set
++# CONFIG_SND_OMAP_TSC2102 is not set
++# CONFIG_SND_OMAP24XX_EAC is not set
++
++#
++# SPI devices
++#
++
++#
++# USB devices
++#
++CONFIG_SND_USB_AUDIO=y
++# CONFIG_SND_USB_CAIAQ is not set
++
++#
++# System on Chip audio support
++#
++CONFIG_SND_SOC=y
++
++#
++# ALSA SoC audio for Freescale SOCs
++#
++
++#
++# SoC Audio for the Texas Instruments OMAP
++#
++CONFIG_SND_OMAP_SOC=y
++CONFIG_SND_OMAP_SOC_MCBSP=y
++CONFIG_SND_OMAP_SOC_OMAP3EVM=y
++CONFIG_SND_SOC_TWL4030=y
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=y
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
++
+ # CONFIG_HID_SUPPORT is not set
+ # CONFIG_USB_SUPPORT is not set
+ # CONFIG_MMC is not set
+diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
+index 0def5ba..8703cea 100644
+--- a/sound/soc/omap/Kconfig
++++ b/sound/soc/omap/Kconfig
+@@ -24,4 +24,12 @@ config SND_OMAP_SOC_OMAP3EVM
+       help
+         Say Y if you want to add support for SoC audio on the OMAP3 EVM.
++config SND_OMAP_SOC_OMAP3BEAGLE
++      tristate "SoC Audio support for OMAP3 Beagle"
++      depends on SND_OMAP_SOC && MACH_OMAP3_BEAGLE
++      select SND_OMAP_SOC_MCBSP
++      select SND_SOC_TWL4030
++      help
++        Say Y if you want to add support for SoC audio on the OMAP3 Beagle.
++
+ endmenu
+diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
+index 985eddc..638a240 100644
+--- a/sound/soc/omap/Makefile
++++ b/sound/soc/omap/Makefile
+@@ -8,7 +8,9 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
+ # OMAP Machine Support
+ snd-soc-n810-objs := n810.o
+ snd-soc-omap3evm-objs := omap3evm.o
++snd-soc-omap3beagle-objs := omap3beagle.o
+ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+ obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
++obj-$(CONFIG_SND_OMAP_SOC_OMAP3BEAGLE) += snd-soc-omap3beagle.o
+diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
+new file mode 100644
+index 0000000..336d50a
+--- /dev/null
++++ b/sound/soc/omap/omap3beagle.c
+@@ -0,0 +1,142 @@
++/*
++ * omap3beagle.c  --  SoC audio for OMAP3 Beagle
++ *
++ * Author: Steve Sakoman <steve@sakoman.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 <asm/arch/hardware.h>
++#include <asm/arch/gpio.h>
++#include <asm/arch/mcbsp.h>
++
++#include "omap-mcbsp.h"
++#include "omap-pcm.h"
++#include "../codecs/twl4030.h"
++
++static int omap3beagle_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_codec_dai *codec_dai = rtd->dai->codec_dai;
++      struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
++      int ret;
++
++      /* Set codec DAI configuration */
++      ret = codec_dai->dai_ops.set_fmt(codec_dai,
++                                       SND_SOC_DAIFMT_I2S |
++                                       SND_SOC_DAIFMT_NB_NF |
++                                       SND_SOC_DAIFMT_CBM_CFM);
++      if (ret < 0) {
++      printk(KERN_INFO "can't set codec DAI configuration\n");
++              return ret;
++      }
++
++      /* Set cpu DAI configuration */
++      ret = cpu_dai->dai_ops.set_fmt(cpu_dai,
++                                     SND_SOC_DAIFMT_I2S |
++                                     SND_SOC_DAIFMT_NB_NF |
++                                     SND_SOC_DAIFMT_CBM_CFM);
++      if (ret < 0) {
++      printk(KERN_INFO "can't set cpu DAI configuration\n");
++              return ret;
++      }
++
++      return 0;
++}
++
++static struct snd_soc_ops omap3beagle_ops = {
++      .hw_params = omap3beagle_hw_params,
++};
++
++/* Digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link omap3beagle_dai = {
++      .name = "TWL4030",
++      .stream_name = "TWL4030",
++      .cpu_dai = &omap_mcbsp_dai[0],
++      .codec_dai = &twl4030_dai,
++      .ops = &omap3beagle_ops,
++};
++
++/* Audio machine driver */
++static struct snd_soc_machine snd_soc_machine_omap3beagle = {
++      .name = "omap3beagle",
++      .dai_link = &omap3beagle_dai,
++      .num_links = 1,
++};
++
++/* Audio subsystem */
++static struct snd_soc_device omap3beagle_snd_devdata = {
++      .machine = &snd_soc_machine_omap3beagle,
++      .platform = &omap_soc_platform,
++      .codec_dev = &soc_codec_dev_twl4030,
++};
++
++static struct platform_device *omap3beagle_snd_device;
++
++static int __init omap3beagle_soc_init(void)
++{
++      int ret;
++
++      printk(KERN_INFO "OMAP3 Beagle SoC init\n");
++      if (!machine_is_omap3_beagle()) {
++              printk(KERN_INFO "Not OMAP3 Beagle!\n");
++              return -ENODEV;
++      }
++
++      omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
++      if (!omap3beagle_snd_device) {
++              printk(KERN_INFO "Platform device allocation failed\n");
++              return -ENOMEM;
++      }
++
++      platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata);
++      omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
++      *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
++
++      ret = platform_device_add(omap3beagle_snd_device);
++      if (ret)
++              goto err1;
++
++      return 0;
++
++err1:
++      printk(KERN_INFO "Unable to add platform device\n");
++      platform_device_put(omap3beagle_snd_device);
++
++      return ret;
++}
++
++static void __exit omap3beagle_soc_exit(void)
++{
++      printk(KERN_INFO "OMAP3 Beagle SoC exit\n");
++      platform_device_unregister(omap3beagle_snd_device);
++}
++
++module_init(omap3beagle_soc_init);
++module_exit(omap3beagle_soc_exit);
++
++MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
++MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
++MODULE_LICENSE("GPL");
index 61fb288..670cd0f 100644 (file)
@@ -6,7 +6,7 @@ SRCREV = "d3b3ae0fe6c71641da19c8de466ec366d39847e3"
 
 PV = "2.6.26"
 #PV = "2.6.26+2.6.27-rc1+${PR}+git${SRCREV}"
-PR = "r53"
+PR = "r54"
 
 SRC_URI = "git://source.mvista.com/git/linux-omap-2.6.git;protocol=git \
           file://defconfig"
@@ -17,7 +17,9 @@ SRC_URI_append_beagleboard = " file://no-harry-potter.diff;patch=1 \
            file://0001-omap3-cpuidle.patch;patch=1 \ 
            file://0002-omap3-cpuidle.patch;patch=1 \
            file://timer-suppression.patch;patch=1 \
-           file://soc.patch;patch=1 \
+           file://ASoC-TWL4030-codec-driver.patch;patch=1 \
+           file://ASoC-machine-driver-for-OMAP3-EVM.patch;patch=1 \
+           file://ASoC-machine-driver-for_OMAP3-Beagle.patch;patch=1 \
            file://16bpp.patch;patch=1 \
            file://no-empty-flash-warnings.patch;patch=1 \
            file://logo_linux_clut224.ppm \