ASoC: omap: rx51: Enable McBSP2 sidetone
[linux-2.6.git] / sound / soc / omap / n810.c
index d166b6b..83d213b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Nokia Corporation
  *
- * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ * Contact: Jarkko Nikula <jhnikula@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  */
 
 #include <linux/clk.h>
+#include <linux/i2c.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 <plat/mcbsp.h>
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
-#include "../codecs/tlv320aic3x.h"
 
 #define N810_HEADSET_AMP_GPIO  10
 #define N810_SPEAKER_AMP_GPIO  101
 
+enum {
+       N810_JACK_DISABLED,
+       N810_JACK_HP,
+       N810_JACK_HS,
+       N810_JACK_MIC,
+};
+
 static struct clk *sys_clkout2;
 static struct clk *sys_clkout2_src;
 static struct clk *func96m_clk;
@@ -50,28 +56,50 @@ static int n810_dmic_func;
 
 static void n810_ext_control(struct snd_soc_codec *codec)
 {
+       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       int hp = 0, line1l = 0;
+
+       switch (n810_jack_func) {
+       case N810_JACK_HS:
+               line1l = 1;
+       case N810_JACK_HP:
+               hp = 1;
+               break;
+       case N810_JACK_MIC:
+               line1l = 1;
+               break;
+       }
+
        if (n810_spk_func)
-               snd_soc_dapm_enable_pin(codec, "Ext Spk");
+               snd_soc_dapm_enable_pin(dapm, "Ext Spk");
        else
-               snd_soc_dapm_disable_pin(codec, "Ext Spk");
+               snd_soc_dapm_disable_pin(dapm, "Ext Spk");
 
-       if (n810_jack_func)
-               snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+       if (hp)
+               snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
        else
-               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
+       if (line1l)
+               snd_soc_dapm_enable_pin(dapm, "LINE1L");
+       else
+               snd_soc_dapm_disable_pin(dapm, "LINE1L");
 
        if (n810_dmic_func)
-               snd_soc_dapm_enable_pin(codec, "DMic");
+               snd_soc_dapm_enable_pin(dapm, "DMic");
        else
-               snd_soc_dapm_disable_pin(codec, "DMic");
+               snd_soc_dapm_disable_pin(dapm, "DMic");
 
-       snd_soc_dapm_sync(codec);
+       snd_soc_dapm_sync(dapm);
 }
 
 static int n810_startup(struct snd_pcm_substream *substream)
 {
+       struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->codec;
+       struct snd_soc_codec *codec = rtd->codec;
+
+       snd_pcm_hw_constraint_minmax(runtime,
+                                    SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
 
        n810_ext_control(codec);
        return clk_enable(sys_clkout2);
@@ -86,8 +114,8 @@ static int n810_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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
        /* Set codec DAI configuration */
@@ -225,7 +253,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
 };
 
 static const char *spk_function[] = {"Off", "On"};
-static const char *jack_function[] = {"Off", "Headphone"};
+static const char *jack_function[] = {"Off", "Headphone", "Headset", "Mic"};
 static const char *input_function[] = {"ADC", "Digital Mic"};
 static const struct soc_enum n810_enum[] = {
        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
@@ -242,31 +270,36 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = {
                     n810_get_input, n810_set_input),
 };
 
-static int n810_aic33_init(struct snd_soc_codec *codec)
+static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
 {
-       int i, err;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_dapm_context *dapm = &codec->dapm;
+       int 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(dapm, "MONO_LOUT");
+       snd_soc_dapm_nc_pin(dapm, "HPLCOM");
+       snd_soc_dapm_nc_pin(dapm, "HPRCOM");
+       snd_soc_dapm_nc_pin(dapm, "MIC3L");
+       snd_soc_dapm_nc_pin(dapm, "MIC3R");
+       snd_soc_dapm_nc_pin(dapm, "LINE1R");
+       snd_soc_dapm_nc_pin(dapm, "LINE2L");
+       snd_soc_dapm_nc_pin(dapm, "LINE2R");
 
        /* Add N810 specific controls */
-       for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
-               err = snd_ctl_add(codec->card,
-                       snd_soc_cnew(&aic33_n810_controls[i], codec, NULL));
-               if (err < 0)
-                       return err;
-       }
+       err = snd_soc_add_controls(codec, aic33_n810_controls,
+                               ARRAY_SIZE(aic33_n810_controls));
+       if (err < 0)
+               return err;
 
        /* Add N810 specific widgets */
-       snd_soc_dapm_new_controls(codec, aic33_dapm_widgets,
+       snd_soc_dapm_new_controls(dapm, aic33_dapm_widgets,
                                  ARRAY_SIZE(aic33_dapm_widgets));
 
        /* Set up N810 specific audio path audio_map */
-       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+       snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync(codec);
+       snd_soc_dapm_sync(dapm);
 
        return 0;
 }
@@ -275,35 +308,21 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link n810_dai = {
        .name = "TLV320AIC33",
        .stream_name = "AIC33",
-       .cpu_dai = &omap_mcbsp_dai[0],
-       .codec_dai = &aic3x_dai,
+       .cpu_dai_name = "omap-mcbsp-dai.1",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "tlv320aic3x-codec.2-0018",
+       .codec_dai_name = "tlv320aic3x-hifi",
        .init = n810_aic33_init,
        .ops = &n810_ops,
 };
 
 /* Audio machine driver */
-static struct snd_soc_machine snd_soc_machine_n810 = {
+static struct snd_soc_card snd_soc_n810 = {
        .name = "N810",
        .dai_link = &n810_dai,
        .num_links = 1,
 };
 
-/* Audio private data */
-static struct aic3x_setup_data n810_aic33_setup = {
-       .i2c_bus = 2,
-       .i2c_address = 0x18,
-       .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
-       .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device n810_snd_devdata = {
-       .machine = &snd_soc_machine_n810,
-       .platform = &omap_soc_platform,
-       .codec_dev = &soc_codec_dev_aic3x,
-       .codec_data = &n810_aic33_setup,
-};
-
 static struct platform_device *n810_snd_device;
 
 static int __init n810_soc_init(void)
@@ -318,9 +337,7 @@ static int __init n810_soc_init(void)
        if (!n810_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(n810_snd_device, &n810_snd_devdata);
-       n810_snd_devdata.dev = &n810_snd_device->dev;
-       *(unsigned int *)n810_dai.cpu_dai->private_data = 1; /* McBSP2 */
+       platform_set_drvdata(n810_snd_device, &snd_soc_n810);
        err = platform_device_add(n810_snd_device);
        if (err)
                goto err1;
@@ -352,10 +369,9 @@ static int __init n810_soc_init(void)
        clk_set_parent(sys_clkout2_src, func96m_clk);
        clk_set_rate(sys_clkout2, 12000000);
 
-       if (gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0)
-               BUG();
-       if (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0)
-               BUG();
+       BUG_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) ||
+              (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0));
+
        gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
        gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
 
@@ -386,6 +402,6 @@ static void __exit n810_soc_exit(void)
 module_init(n810_soc_init);
 module_exit(n810_soc_exit);
 
-MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
+MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
 MODULE_DESCRIPTION("ALSA SoC Nokia N810");
 MODULE_LICENSE("GPL");