rendered paste bodyIndex: blueangel.c
===================================================================
RCS file: /cvs/linux/kernel26/sound/soc/pxa/blueangel.c,v
retrieving revision 1.1
diff -u -r1.1 blueangel.c
--- blueangel.c 6 Dec 2006 21:24:47 -0000 1.1
+++ blueangel.c 12 Apr 2007 20:48:01 -0000
@@ -1,13 +1,12 @@
/*
- * SoC audio for HTC Blueangel
+ * SoC audio for HTC Magician
+ *
+ * Copyright (c) 2006 Philipp Zabel <philipp.zabel@gmail.com>
*
* based on spitz.c,
* Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
* Richard Purdie <richard@openedhand.com>
*
- * based on magician.c,
- * Author: Luke Kenneth Casson Leighton <lkcl@lkcl.net>
- *
* 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
@@ -15,12 +14,11 @@
*
*/
-#include <linux/delay.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -30,91 +28,83 @@
#include <asm/hardware/scoop.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/hardware.h>
-#include <asm/arch-pxa/htcblueangel-asic.h>
-#include <asm/arch-pxa/htcblueangel-gpio.h>
+#include <asm/arch/htcblueangel-asic.h>
+#include <asm/arch/htcblueangel-gpio.h>
#include <asm/mach-types.h>
#include "../codecs/uda1380.h"
#include "pxa2xx-pcm.h"
+#include "pxa2xx-i2s.h"
+#include "pxa2xx-ssp.h"
-#include <asm/hardware/ipaq-asic3.h>
-#include <linux/soc/asic3_base.h>
+#define BLUEANGEL_HP_OFF 0
+#define BLUEANGEL_HEADSET 1
+#define BLUEANGEL_HP 2
-#define BLUEANGEL_HP 0
-#define BLUEANGEL_MIC 1
-#define BLUEANGEL_LINE 2
-#define BLUEANGEL_HEADSET 3
-#define BLUEANGEL_HP_OFF 4
#define BLUEANGEL_SPK_ON 0
#define BLUEANGEL_SPK_OFF 1
-static int blueangel_jack_func = 0;
-static int blueangel_spk_func = 0;
+#define BLUEANGEL_MIC 0
+#define BLUEANGEL_MIC_EXT 1
+#define BLUEANGEL_BT_HS 2
-extern struct platform_device blueangel_asic3;
+/*
+ * SSP GPIO's
+ */
+#define GPIO27_SSP_EXT_CLK (27 | GPIO_ALT_FN_1_IN)
-static irqreturn_t earphone_isr(int irq, void *irq_desc)
-{
- printk("earphone irq. GPIO99 = %d\n", GPLR(99) & GPIO_bit(99)); // EXT_MIC_DETECT, EARPHONE_DET
-// printk("earphone irq. cpld18 = %d\n", blueangel_cpld18()); // is_earphone_connected
- return IRQ_HANDLED;
-}
+static int blueangel_jack_func = BLUEANGEL_HP_OFF;
+static int blueangel_spk_func = BLUEANGEL_SPK_ON;
+static int blueangel_in_sel = BLUEANGEL_MIC;
+
+extern struct platform_device blueangel_asic3;
static void blueangel_ext_control(struct snd_soc_codec *codec)
{
-printk("blueangel_ext_control(spk_func = %d, jack_func = %d)", blueangel_spk_func, blueangel_jack_func);
-
- asic3_set_gpio_out_b(&blueangel_asic3.dev, 1<<15, 1<<15); /* reset on? */
- udelay(15);
- asic3_set_gpio_out_a(&blueangel_asic3.dev, 1<<15, 1<<15); /* power? */
- udelay(30);
- /* now gpio 23 gets sent and also egpio14?? */
- udelay(15);
- asic3_set_gpio_out_b(&blueangel_asic3.dev, 1<<15, 0); /* reset off? */
+ asic3_set_gpio_out_b(&blueangel_asic3.dev, 1<<GPIOB_CODEC_RESET, 1<<GPIOB_CODEC_RESET); /* reset on? */
+ asic3_set_clock_cdex (&blueangel_asic3.dev, 1<<CLOCK_CDEX_EX1, 1 << CLOCK_CDEX_EX1);
+ udelay(1000);
+ asic3_set_clock_cdex (&blueangel_asic3.dev, 1 << 0, 0 ); // Source 0
+ asic3_set_clock_cdex (&blueangel_asic3.dev, 1 << 1, 1 << 1); // Source 1
+ asic3_set_clock_cdex (&blueangel_asic3.dev, 1<<CLOCK_CDEX_CONTROL_CX, CLOCK_CDEX_CONTROL_CX);
+ asic3_set_gpio_out_a(&blueangel_asic3.dev, 1<<GPIOA_CODEC_PWR_ON, 1<<GPIOA_CODEC_PWR_ON); /* power? */
+ /* now gpio 23 gets sent and also egpio14?? */
+ udelay(15);
+ asic3_set_gpio_out_b(&blueangel_asic3.dev, 1<<GPIOB_CODEC_RESET, 0); /* reset off? */
if (blueangel_spk_func == BLUEANGEL_SPK_ON)
- snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
+ snd_soc_dapm_set_endpoint(codec, "Speaker", 1);
else
- snd_soc_dapm_set_endpoint(codec, "Ext Spk", 0);
+ snd_soc_dapm_set_endpoint(codec, "Speaker", 0);
-#if 0
/* set up jack connection */
- switch(blueangel_jack_func) {
+ switch (blueangel_jack_func) {
case BLUEANGEL_HP:
/* enable and unmute hp jack, disable mic bias */
- snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
- snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
- blueangel_egpio_disable(&blueangel_cpld, EGPIO_NR_BLUEANGEL_SPK_POWER);
- blueangel_egpio_enable(&blueangel_cpld, EGPIO_NR_BLUEANGEL_EP_POWER);
- break;
- case BLUEANGEL_MIC:
- /* enable mic jack and bias, mute hp */
- snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
- snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
- snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
- snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
-// reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
-// reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
break;
case BLUEANGEL_HEADSET:
- /* enable and unmute headset jack enable mic bias, mute L hp */
- snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
+ /* enable mic jack and bias, mute hp */
+ snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
- snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
- snd_soc_dapm_set_endpoint(codec, "Headset Jack", 1);
- blueangel_egpio_enable(&blueangel_cpld, EGPIO_NR_BLUEANGEL_EP_POWER);
- blueangel_egpio_disable(&blueangel_cpld, EGPIO_NR_BLUEANGEL_SPK_POWER);
break;
case BLUEANGEL_HP_OFF:
-
/* jack removed, everything off */
snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
- snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
- snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
- blueangel_egpio_disable(&blueangel_cpld, EGPIO_NR_BLUEANGEL_EP_POWER);
- blueangel_egpio_enable(&blueangel_cpld, EGPIO_NR_BLUEANGEL_SPK_POWER);
+ break;
+ }
+#if 0
+ /* fixme pH5, can we detect and config the correct Mic type ? */
+ switch(blueangel_in_sel) {
+ case BLUEANGEL_IN_MIC:
+ snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
+ break;
+ case BLUEANGEL_IN_MIC_EXT:
+ snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
+ break;
+ case BLUEANGEL_IN_BT_HS:
+ snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
break;
}
#endif
@@ -129,188 +119,377 @@
/* check the jack status at stream startup */
blueangel_ext_control(codec);
- /* GPIO 99 is EXT_MIC / EARPHONE detect */
- /* cpld+0x18 & 0x2 = is_earphone_plugged_in */
- // EGPIO_NR_BLUEANGEL_CODEC_POWER = 0x0c000004,0x40(1<<6)
return 0;
}
-static void blueangel_shutdown(snd_pcm_substream_t *substream)
+/*
+ * Magician uses SSP port for playback.
+ */
+static int blueangel_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- asic3_set_gpio_out_a(&blueangel_asic3.dev, 1<<15, 0); /* power? */
+ 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;
+ unsigned int acps, acds, div4;
+ int ret = 0;
+
+ /*
+ * Rate = SSPSCLK / (word size(16))
+ * SSPSCLK = (ACPS / ACDS) / SSPSCLKDIV(div4 or div1)
+ */
+ switch (params_rate(params)) {
+ case 8000:
+ acps = 32842000;
+ acds = PXA2XX_SSP_CLK_AUDIO_DIV_32; /* wrong - 32 bits/sample */
+ div4 = PXA2XX_SSP_CLK_SCDB_4;
+ break;
+ case 11025:
+ acps = 5622000;
+ acds = PXA2XX_SSP_CLK_AUDIO_DIV_8; /* 16 bits/sample, 1 slot */
+ div4 = PXA2XX_SSP_CLK_SCDB_4;
+ break;
+ case 22050:
+ acps = 5622000;
+ acds = PXA2XX_SSP_CLK_AUDIO_DIV_4;
+ div4 = PXA2XX_SSP_CLK_SCDB_4;
+ break;
+ case 44100:
+ acps = 11345000;
+ acds = PXA2XX_SSP_CLK_AUDIO_DIV_4;
+ div4 = PXA2XX_SSP_CLK_SCDB_4;
+ break;
+ case 48000:
+ acps = 12235000;
+ acds = PXA2XX_SSP_CLK_AUDIO_DIV_4;
+ div4 = PXA2XX_SSP_CLK_SCDB_4;
+ break;
+ }
+
+ /* set codec DAI configuration */
+ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_MSB |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_MSB |
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* set audio clock as clock source */
+ ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_SSP_CLK_AUDIO, 0,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ /* set the SSP audio system clock ACDS divider */
+ ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
+ PXA2XX_SSP_AUDIO_DIV_ACDS, acds);
+ if (ret < 0)
+ return ret;
+
+ /* set the SSP audio system clock SCDB divider4 */
+ ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
+ PXA2XX_SSP_AUDIO_DIV_SCDB, div4);
+ if (ret < 0)
+ return ret;
+
+ /* set SSP audio pll clock */
+ ret = cpu_dai->dai_ops.set_pll(cpu_dai, 0, 0, acps);
+ if (ret < 0)
+ return ret;
return 0;
}
-static struct snd_soc_ops blueangel_ops = {
+/*
+ * We have to enable the SSP port early so the UDA1380 can flush
+ * it's register cache. The UDA1380 can only write it's interpolator and
+ * decimator registers when the link is running.
+ */
+static int blueangel_playback_prepare(struct snd_pcm_substream *substream)
+{
+ /* enable SSP clock - is this needed ? */
+ SSCR0_P(1) |= SSCR0_SSE;
+
+ /* FIXME: ENABLE I2S */
+ SACR0 |= SACR0_BCKD;
+ SACR0 |= SACR0_ENB;
+ pxa_set_cken(CKEN8_I2S, 1);
+
+ return 0;
+}
+
+static int blueangel_playback_hw_free(struct snd_pcm_substream *substream)
+{
+ /* FIXME: DISABLE I2S */
+ SACR0 &= ~SACR0_ENB;
+ SACR0 &= ~SACR0_BCKD;
+ pxa_set_cken(CKEN8_I2S, 0);
+ return 0;
+}
+
+/*
+ * Magician uses I2S for capture.
+ */
+static int blueangel_capture_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 = 0;
+
+ /* set codec DAI configuration */
+ ret = codec_dai->dai_ops.set_fmt(codec_dai,
+ SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai,
+ SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ return ret;
+
+ /* set the I2S system clock as output */
+ ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * We have to enable the I2S port early so the UDA1380 can flush
+ * it's register cache. The UDA1380 can only write it's interpolator and
+ * decimator registers when the link is running.
+ */
+static int blueangel_capture_prepare(struct snd_pcm_substream *substream)
+{
+ SACR0 |= SACR0_ENB;
+ return 0;
+}
+
+static struct snd_soc_ops blueangel_capture_ops = {
.startup = blueangel_startup,
- .shutdown = blueangel_shutdown,
+ .hw_params = blueangel_capture_hw_params,
+ .prepare = blueangel_capture_prepare,
};
-static int blueangel_get_jack(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static struct snd_soc_ops blueangel_playback_ops = {
+ .startup = blueangel_startup,
+ .hw_params = blueangel_playback_hw_params,
+ .prepare = blueangel_playback_prepare,
+ .hw_free = blueangel_playback_hw_free,
+};
+
+static int blueangel_get_jack(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
{
ucontrol->value.integer.value[0] = blueangel_jack_func;
return 0;
}
-static int blueangel_set_jack(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int blueangel_set_jack(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
{
-
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (blueangel_jack_func == ucontrol->value.integer.value[0])
+ return 0;
+
blueangel_jack_func = ucontrol->value.integer.value[0];
blueangel_ext_control(codec);
- return 0;
+ return 1;
}
-static int blueangel_get_spk(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int blueangel_get_spk(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
{
ucontrol->value.integer.value[0] = blueangel_spk_func;
return 0;
}
-static int blueangel_set_spk(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int blueangel_set_spk(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (blueangel_spk_func == ucontrol->value.integer.value[0])
+ return 0;
+
blueangel_spk_func = ucontrol->value.integer.value[0];
blueangel_ext_control(codec);
+ return 1;
+}
+
+static int blueangel_get_input(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ucontrol->value.integer.value[0] = blueangel_in_sel;
+ return 0;
+}
+
+static int blueangel_set_input(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (blueangel_in_sel == ucontrol->value.integer.value[0])
+ return 0;
+
+ blueangel_in_sel = ucontrol->value.integer.value[0];
+
+ switch (blueangel_in_sel) {
+ case BLUEANGEL_MIC:
+ asic3_set_gpio_out_a(&blueangel_asic3.dev, 1<<GPIOA_MIC_PWR_ON, 1<<GPIOA_MIC_PWR_ON);
+ break;
+ case BLUEANGEL_MIC_EXT:
+ break;
+ }
+
+ return 1;
+}
+
+static int blueangel_spk_power(struct snd_soc_dapm_widget *w, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ asic3_set_gpio_out_a(&blueangel_asic3.dev, 1<<15, 1<<15);
+ else
+ asic3_set_gpio_out_a(&blueangel_asic3.dev, 1<<15, 0);
return 0;
}
-static int blueangel_mic_bias(struct snd_soc_dapm_widget* w, int power)
+static int blueangel_hp_power(struct snd_soc_dapm_widget *w, int event)
{
- asic3_set_gpio_out_a(&blueangel_asic3.dev, 1<<GPIOA_MIC_PWR_ON, power ? (1<<GPIOA_MIC_PWR_ON) : 0);
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ asic3_set_gpio_out_b(&blueangel_asic3.dev, 1 << 10, 1 << 10);
+ else
+ asic3_set_gpio_out_b(&blueangel_asic3.dev, 1 << 10, 0);
+ return 0;
+}
+static int blueangel_mic_bias(struct snd_soc_dapm_widget *w, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ asic3_set_gpio_out_a(&blueangel_asic3.dev, 1 << 8 , 1 << 8 );
+ else
+ asic3_set_gpio_out_a(&blueangel_asic3.dev, 1 << 8 , 0);
return 0;
}
/* blueangel machine dapm widgets */
static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
- SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_HP("Headphone Jack", blueangel_hp_power),
SND_SOC_DAPM_MIC("Mic Jack", blueangel_mic_bias),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
- SND_SOC_DAPM_LINE("Line Jack", NULL),
-
- /* headset is a mic and mono headphone */
- SND_SOC_DAPM_HP("Headset Jack", NULL),
+ SND_SOC_DAPM_SPK("Speaker", blueangel_spk_power),
};
/* blueangel machine audio_map */
-static const char* audio_map[][3] = {
+static const char *audio_map[][3] = {
- /* headphone connected to LOUT1, ROUT1 */
+ /* headphone connected to VOUTLHP, VOUTRHP */
{"Headphone Jack", NULL, "VOUTLHP"},
{"Headphone Jack", NULL, "VOUTRHP"},
- /* headset connected to ROUT1 and LINPUT1 with bias (def below) */
- {"Headset Jack", NULL, "ROUT1"},
-
- /* ext speaker connected to LOUT2, ROUT2 */
- {"Ext Spk", NULL , "VOUTR"},
- {"Ext Spk", NULL , "VOUTL"},
-
- /* mic is connected to input 1 - with bias */
- {"LINPUT1", NULL, "Mic Bias"},
- {"Mic Bias", NULL, "Mic Jack"},
-
- /* line is connected to input 1 - no bias */
- {"LINPUT1", NULL, "Line Jack"},
+ /* ext speaker connected to VOUTL, VOUTR */
+ {"Speaker", NULL, "VOUTL"},
+ {"Speaker", NULL, "VOUTR"},
+
+ /* mic is connected to VINM */
+ {"VINM", NULL, "Mic Jack"},
+
+ /* line is connected to VINL, VINR */
+ {"VINL", NULL, "Line Jack"},
+ {"VINR", NULL, "Line Jack"},
{NULL, NULL, NULL},
};
-static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset", "Off"};
-static const char *spk_function[] = {"On", "Off"};
+static const char *jack_function[] = { "Off", "Headset", "Headphone" };
+static const char *spk_function[] = { "On", "Off" };
+static const char *input_select[] = { "Internal Mic", "External Mic" };
static const struct soc_enum blueangel_enum[] = {
- SOC_ENUM_SINGLE_EXT(5, jack_function),
+ SOC_ENUM_SINGLE_EXT(4, jack_function),
SOC_ENUM_SINGLE_EXT(2, spk_function),
+ SOC_ENUM_SINGLE_EXT(2, input_select),
};
static const struct snd_kcontrol_new uda1380_blueangel_controls[] = {
- SOC_ENUM_EXT("Jack Function", blueangel_enum[0], blueangel_get_jack, blueangel_set_jack),
- SOC_ENUM_EXT("Speaker Function", blueangel_enum[1], blueangel_get_spk, blueangel_set_spk),
+ SOC_ENUM_EXT("Jack Function", blueangel_enum[0], blueangel_get_jack,
+ blueangel_set_jack),
+ SOC_ENUM_EXT("Speaker Function", blueangel_enum[1], blueangel_get_spk,
+ blueangel_set_spk),
+ SOC_ENUM_EXT("Input Select", blueangel_enum[2], blueangel_get_input,
+ blueangel_set_input),
};
/*
- * Logic for a uda1380 as connected on a HTC Blueangel
+ * Logic for a uda1380 as connected on a HTC Magician
*/
static int blueangel_uda1380_init(struct snd_soc_codec *codec)
{
int i, err;
- printk("blueangel_uda1380_init\n");
+ //pxa2xx_ssp_set_clock(&pxa_ssp_dai[0], PXA2XX_SSP_CLK_AUDIO);
- pxa2xx_ssp_set_clock(&pxa_ssp_dai[0], PXA2XX_SSP_CLK_AUDIO);
+ /* NC codec pins */
+ snd_soc_dapm_set_endpoint(codec, "VOUTLHP", 0);
+ snd_soc_dapm_set_endpoint(codec, "VOUTRHP", 0);
- snd_soc_dapm_set_endpoint(codec, "Int Mic", 1);
- snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
- /* NC codec pins */
- /*
- snd_soc_dapm_set_endpoint(codec, "RINPUT1", 0);
- snd_soc_dapm_set_endpoint(codec, "LINPUT2", 0);
- snd_soc_dapm_set_endpoint(codec, "RINPUT2", 0);
- snd_soc_dapm_set_endpoint(codec, "LINPUT3", 0);
- snd_soc_dapm_set_endpoint(codec, "RINPUT3", 0);
- snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
- snd_soc_dapm_set_endpoint(codec, "MONO", 0);
- */
/* Add blueangel specific controls */
for (i = 0; i < ARRAY_SIZE(uda1380_blueangel_controls); i++) {
if ((err = snd_ctl_add(codec->card,
- snd_soc_cnew(&uda1380_blueangel_controls[i], codec, NULL))) < 0)
+ snd_soc_cnew(&uda1380_blueangel_controls[i],
+ codec, NULL))) < 0)
return err;
}
/* Add blueangel specific widgets */
- for(i = 0; i < ARRAY_SIZE(uda1380_dapm_widgets); i++) {
+ for (i = 0; i < ARRAY_SIZE(uda1380_dapm_widgets); i++) {
snd_soc_dapm_new_control(codec, &uda1380_dapm_widgets[i]);
}
/* Set up blueangel specific audio path interconnects */
- for(i = 0; audio_map[i][0] != NULL; i++) {
- snd_soc_dapm_connect_input(codec, audio_map[i][0], audio_map[i][1],
- audio_map[i][2]);
+ for (i = 0; audio_map[i][0] != NULL; i++) {
+ snd_soc_dapm_connect_input(codec, audio_map[i][0],
+ audio_map[i][1], audio_map[i][2]);
}
+
snd_soc_dapm_sync_endpoints(codec);
return 0;
}
-unsigned int blueangel_config_sysclk(struct snd_soc_pcm_runtime *rtd,
- struct snd_soc_clock_info *info)
-{
-
-printk("snd-soc-blueangel config-sysclk rate=%d, fs=%d\n", info->rate, info->fs);
-
- /* config pxa i2s or SSP0 as master */
- return rtd->cpu_dai->config_sysclk(rtd->cpu_dai, info, 0);
-}
-
/* blueangel digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link blueangel_dai[] = {
{
.name = "uda1380",
.stream_name = "UDA1380 Playback",
.cpu_dai = &pxa_ssp_dai[0],
- .codec_dai = &uda1380_dai[1],
+ .codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK],
.init = blueangel_uda1380_init,
- .config_sysclk = blueangel_config_sysclk,
+ .ops = &blueangel_playback_ops,
},
{
.name = "uda1380",
.stream_name = "UDA1380 Capture",
.cpu_dai = &pxa_i2s_dai,
- .codec_dai = &uda1380_dai[2],
- .config_sysclk = blueangel_config_sysclk,
-},
+ .codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE],
+ .ops = &blueangel_capture_ops,
+}
};
/* blueangel audio machine driver */
static struct snd_soc_machine snd_soc_machine_blueangel = {
- .name = "Blueangel",
+ .name = "Magician",
.dai_link = blueangel_dai,
.num_links = ARRAY_SIZE(blueangel_dai),
- .ops = &blueangel_ops,
};
/* blueangel audio private data */
@@ -335,10 +514,16 @@
if (!machine_is_blueangel())
return -ENODEV;
+
+ asic3_set_gpio_out_b(&blueangel_asic3.dev, 1<<GPIOB_CODEC_RESET, 1<<GPIOB_CODEC_RESET); /* reset on? */
+ udelay(15);
+ asic3_set_gpio_out_a(&blueangel_asic3.dev, 1<<GPIOA_CODEC_PWR_ON, 1<<GPIOA_CODEC_PWR_ON); /* power? */
+ /* we may need to have the clock running here - pH5 */
+ udelay(5);
+ asic3_set_gpio_out_b(&blueangel_asic3.dev, 1<<GPIOB_CODEC_RESET, 0); /* reset on? */
-printk("snd-soc-blueangel init\n");
-
-// pxa_gpio_mode(BLUEANGEL_GPIO_AK_INT | GPIO_IN); // audio connector interrupt?
+ /* correct place? we'll need it to talk to the uda1380 */
+ request_module("i2c-pxa");
blueangel_snd_device = platform_device_alloc("soc-audio", -1);
if (!blueangel_snd_device)
@@ -351,12 +536,15 @@
if (ret)
platform_device_put(blueangel_snd_device);
+ pxa_gpio_mode(GPIO27_SSP_EXT_CLK);
+
return ret;
}
static void __exit blueangel_exit(void)
{
platform_device_unregister(blueangel_snd_device);
+
}
module_init(blueangel_init);
Index: pxa2xx-ssp.c
===================================================================
RCS file: /cvs/linux/kernel26/sound/soc/pxa/pxa2xx-ssp.c,v
retrieving revision 1.5
diff -u -r1.5 pxa2xx-ssp.c
--- pxa2xx-ssp.c 13 Feb 2007 20:28:38 -0000 1.5
+++ pxa2xx-ssp.c 12 Apr 2007 20:48:01 -0000
@@ -284,6 +284,7 @@
int port = cpu_dai->id + 1;
switch (div_id) {
+#ifdef CONFIG_PXA27x
case PXA2XX_SSP_AUDIO_DIV_ACDS:
SSACD_P(port) &= ~ 0x7;
SSACD_P(port) |= SSACD_ACDS(div);
@@ -293,6 +294,7 @@
if (div == PXA2XX_SSP_CLK_SCDB_1)
SSACD_P(port) |= SSACD_SCDB;
break;
+#endif
case PXA2XX_SSP_DIV_SCR:
SSCR0_P(port) &= ~SSCR0_SCR;
SSCR0_P(port) |= SSCR0_SerClkDiv(div);
@@ -310,6 +312,7 @@
static int pxa2xx_ssp_set_dai_pll(struct snd_soc_cpu_dai *cpu_dai,
int pll_id, unsigned int freq_in, unsigned int freq_out)
{
+#ifdef CONFIG_PXA27x
int port = cpu_dai->id + 1;
SSACD_P(port) &= ~0x70;
@@ -332,6 +335,7 @@
SSACD_P(port) |= (0x5 << 4);
break;
}
+#endif
return 0;
}
@@ -341,6 +345,7 @@
static int pxa2xx_ssp_set_dai_tdm_slot(struct snd_soc_cpu_dai *cpu_dai,
unsigned int mask, int slots)
{
+#ifdef CONFIG_PXA27x
int port = cpu_dai->id + 1;
SSCR0_P(port) &= ~SSCR0_SlotsPerFrm(7);
@@ -351,6 +356,7 @@
/* set active slot mask */
SSTSA_P(port) = mask;
SSRSA_P(port) = mask;
+#endif
return 0;
}