Merge remote branch 'takashi/topic/asoc' into for-2.6.36
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index b0bae35..0a4b0fe 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -560,13 +560,16 @@
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		/* vref/mid, osc on, dac unmute */
+		reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \
+			TLV320AIC23_DAC_OFF);
 		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);
+		tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \
+			TLV320AIC23_CLK_OFF);
 		break;
 	case SND_SOC_BIAS_OFF:
 		/* everything off, dac mute, inactive */
@@ -615,7 +618,6 @@
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 	struct snd_soc_codec *codec = socdev->card->codec;
 
-	tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
 	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
 	return 0;
@@ -632,7 +634,6 @@
 		u16 val = tlv320aic23_read_reg_cache(codec, reg);
 		tlv320aic23_write(codec, reg, val);
 	}
-
 	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	return 0;
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 87ce842..9eecac1 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -43,12 +43,14 @@
 
 static struct regulator *omap3pandora_dac_reg;
 
-static int omap3pandora_cmn_hw_params(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params, unsigned int fmt)
+static int omap3pandora_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 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		  SND_SOC_DAIFMT_CBS_CFS;
 	int ret;
 
 	/* Set codec DAI configuration */
@@ -91,24 +93,6 @@
 	return 0;
 }
 
-static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params)
-{
-	return omap3pandora_cmn_hw_params(substream, params,
-					  SND_SOC_DAIFMT_I2S |
-					  SND_SOC_DAIFMT_IB_NF |
-					  SND_SOC_DAIFMT_CBS_CFS);
-}
-
-static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params)
-{
-	return omap3pandora_cmn_hw_params(substream, params,
-					  SND_SOC_DAIFMT_I2S |
-					  SND_SOC_DAIFMT_NB_NF |
-					  SND_SOC_DAIFMT_CBS_CFS);
-}
-
 static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *k, int event)
 {
@@ -231,12 +215,8 @@
 	return snd_soc_dapm_sync(codec);
 }
 
-static struct snd_soc_ops omap3pandora_out_ops = {
-	.hw_params = omap3pandora_out_hw_params,
-};
-
-static struct snd_soc_ops omap3pandora_in_ops = {
-	.hw_params = omap3pandora_in_hw_params,
+static struct snd_soc_ops omap3pandora_ops = {
+	.hw_params = omap3pandora_hw_params,
 };
 
 /* Digital audio interface glue - connects codec <--> CPU */
@@ -246,14 +226,14 @@
 		.stream_name = "HiFi Out",
 		.cpu_dai = &omap_mcbsp_dai[0],
 		.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
-		.ops = &omap3pandora_out_ops,
+		.ops = &omap3pandora_ops,
 		.init = omap3pandora_out_init,
 	}, {
 		.name = "TWL4030",
 		.stream_name = "Line/Mic In",
 		.cpu_dai = &omap_mcbsp_dai[1],
 		.codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
-		.ops = &omap3pandora_in_ops,
+		.ops = &omap3pandora_ops,
 		.init = omap3pandora_in_init,
 	}
 };
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 47d831e..88052d2 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -27,6 +27,7 @@
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <sound/core.h>
+#include <sound/jack.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
@@ -37,14 +38,22 @@
 #include "omap-pcm.h"
 #include "../codecs/tlv320aic3x.h"
 
+#define RX51_TVOUT_SEL_GPIO		40
+#define RX51_JACK_DETECT_GPIO		177
 /*
  * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This
  * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c
  */
 #define RX51_SPEAKER_AMP_TWL_GPIO	(192 + 7)
 
+enum {
+	RX51_JACK_DISABLED,
+	RX51_JACK_TVOUT,		/* tv-out */
+};
+
 static int rx51_spk_func;
 static int rx51_dmic_func;
+static int rx51_jack_func;
 
 static void rx51_ext_control(struct snd_soc_codec *codec)
 {
@@ -57,6 +66,9 @@
 	else
 		snd_soc_dapm_disable_pin(codec, "DMic");
 
+	gpio_set_value(RX51_TVOUT_SEL_GPIO,
+		       rx51_jack_func == RX51_JACK_TVOUT);
+
 	snd_soc_dapm_sync(codec);
 }
 
@@ -162,6 +174,40 @@
 	return 1;
 }
 
+static int rx51_get_jack(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = rx51_jack_func;
+
+	return 0;
+}
+
+static int rx51_set_jack(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	if (rx51_jack_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	rx51_jack_func = ucontrol->value.integer.value[0];
+	rx51_ext_control(codec);
+
+	return 1;
+}
+
+static struct snd_soc_jack rx51_av_jack;
+
+static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
+	{
+		.gpio = RX51_JACK_DETECT_GPIO,
+		.name = "avdet-gpio",
+		.report = SND_JACK_VIDEOOUT,
+		.invert = 1,
+		.debounce_time = 200,
+	},
+};
+
 static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
 	SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
 	SND_SOC_DAPM_MIC("DMic", NULL),
@@ -177,10 +223,12 @@
 
 static const char *spk_function[] = {"Off", "On"};
 static const char *input_function[] = {"ADC", "Digital Mic"};
+static const char *jack_function[] = {"Off", "TV-OUT"};
 
 static const struct soc_enum rx51_enum[] = {
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
 };
 
 static const struct snd_kcontrol_new aic34_rx51_controls[] = {
@@ -188,10 +236,13 @@
 		     rx51_get_spk, rx51_set_spk),
 	SOC_ENUM_EXT("Input Select",  rx51_enum[1],
 		     rx51_get_input, rx51_set_input),
+	SOC_ENUM_EXT("Jack Function", rx51_enum[2],
+		     rx51_get_jack, rx51_set_jack),
 };
 
 static int rx51_aic34_init(struct snd_soc_codec *codec)
 {
+	struct snd_soc_card *card = codec->socdev->card;
 	int err;
 
 	/* Set up NC codec pins */
@@ -214,7 +265,16 @@
 
 	snd_soc_dapm_sync(codec);
 
-	return 0;
+	/* AV jack detection */
+	err = snd_soc_jack_new(card, "AV Jack",
+			       SND_JACK_VIDEOOUT, &rx51_av_jack);
+	if (err)
+		return err;
+	err = snd_soc_jack_add_gpios(&rx51_av_jack,
+				     ARRAY_SIZE(rx51_av_jack_gpios),
+				     rx51_av_jack_gpios);
+
+	return err;
 }
 
 /* Digital audio interface glue - connects codec <--> CPU */
@@ -259,6 +319,11 @@
 	if (!machine_is_nokia_rx51())
 		return -ENODEV;
 
+	err = gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel");
+	if (err)
+		goto err_gpio_tvout_sel;
+	gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0);
+
 	rx51_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!rx51_snd_device) {
 		err = -ENOMEM;
@@ -277,13 +342,19 @@
 err2:
 	platform_device_put(rx51_snd_device);
 err1:
+	gpio_free(RX51_TVOUT_SEL_GPIO);
+err_gpio_tvout_sel:
 
 	return err;
 }
 
 static void __exit rx51_soc_exit(void)
 {
+	snd_soc_jack_free_gpios(&rx51_av_jack, ARRAY_SIZE(rx51_av_jack_gpios),
+				rx51_av_jack_gpios);
+
 	platform_device_unregister(rx51_snd_device);
+	gpio_free(RX51_TVOUT_SEL_GPIO);
 }
 
 module_init(rx51_soc_init);