All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo
@ 2009-03-11 18:16 Philipp Zabel
  2009-03-11 18:16 ` [PATCH 2/3][RFC] ASoC: Add Magician machine support Philipp Zabel
                   ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Philipp Zabel @ 2009-03-11 18:16 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, Philipp Zabel

Please advise how this behaviour could be made configurable. I guess
the only machines that will ever need this are HTC Magician, Blueangel
and Himalaya.

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
---
 sound/soc/pxa/pxa-ssp.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 569c0a6..bc9d306 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -634,8 +635,14 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
 	/* select correct DMA params */
 	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
 		dma = 1; /* capture DMA offset is 1,3 */
-	if (chn == 2)
-		dma += 2; /* stereo DMA offset is 2, mono is 0 */
+	/* FIXME: Magician needs a way to configure 16-bit DMA for stereo */
+	if (machine_is_magician()) {
+		if (width == 32)
+			dma += 2; /* 32-bit DMA offset is 2, 16-bit is 0 */
+	} else {
+		if (chn == 2)
+			dma += 2; /* stereo DMA offset is 2, mono is 0 */
+	}
 	cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
 
 	dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
-- 
1.6.2

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 2/3][RFC] ASoC: Add Magician machine support.
  2009-03-11 18:16 [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo Philipp Zabel
@ 2009-03-11 18:16 ` Philipp Zabel
  2009-03-11 19:02   ` Liam Girdwood
  2009-03-11 22:25   ` Mark Brown
  2009-03-11 18:17 ` [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR Philipp Zabel
  2009-03-12 15:57 ` [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo Mark Brown
  2 siblings, 2 replies; 25+ messages in thread
From: Philipp Zabel @ 2009-03-11 18:16 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, Philipp Zabel

HTC Magician has a Philips UDA1380 codec connected via
SSP1 (playback) and I2S (capture).
There is a flip-flop between the SSP frame clock output
and the codec's word select input pin. To make the codec
see proper I2S input, the SSP has to send two frames per
sample.

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
---
 sound/soc/pxa/Kconfig    |   10 +
 sound/soc/pxa/Makefile   |    2 +
 sound/soc/pxa/magician.c |  563 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 575 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/pxa/magician.c

diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 5998ab3..ad8a10f 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -116,6 +116,16 @@ config SND_SOC_ZYLONITE
 	  Say Y if you want to add support for SoC audio on the
 	  Marvell Zylonite reference platform.
 
+config SND_PXA2XX_SOC_MAGICIAN
+	tristate "SoC Audio support for HTC Magician"
+	depends on SND_PXA2XX_SOC && MACH_MAGICIAN
+	select SND_PXA2XX_SOC_I2S
+	select SND_PXA_SOC_SSP
+	select SND_SOC_UDA1380
+	help
+	  Say Y if you want to add support for SoC audio on the
+	  HTC Magician.
+
 config SND_PXA2XX_SOC_MIOA701
         tristate "SoC Audio support for MIO A701"
         depends on SND_PXA2XX_SOC && MACH_MIOA701
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 8ed881c..4b90c3c 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -20,6 +20,7 @@ snd-soc-spitz-objs := spitz.o
 snd-soc-em-x270-objs := em-x270.o
 snd-soc-palm27x-objs := palm27x.o
 snd-soc-zylonite-objs := zylonite.o
+snd-soc-magician-objs := magician.o
 snd-soc-mioa701-objs := mioa701_wm9713.o
 
 obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
@@ -31,5 +32,6 @@ obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
 obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
 obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
 obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
+obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
 obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
 obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
new file mode 100644
index 0000000..e986e77
--- /dev/null
+++ b/sound/soc/pxa/magician.c
@@ -0,0 +1,563 @@
+/*
+ * SoC audio for HTC Magician
+ *
+ * Copyright (c) 2006-2009 Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * based on spitz.c,
+ * 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/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <mach/pxa-regs.h>
+#include <mach/hardware.h>
+#include <mach/magician.h>
+#include <asm/mach-types.h>
+#include "../codecs/uda1380.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-i2s.h"
+#include "pxa-ssp.h"
+
+#define MAGICIAN_MIC       0
+#define MAGICIAN_MIC_EXT   1
+
+static int magician_hp_switch;
+static int magician_spk_switch = 1;
+static int magician_in_sel = MAGICIAN_MIC;
+
+static void magician_ext_control(struct snd_soc_codec *codec)
+{
+	if (magician_spk_switch)
+		snd_soc_dapm_enable_pin(codec, "Speaker");
+	else
+		snd_soc_dapm_disable_pin(codec, "Speaker");
+	if (magician_hp_switch)
+		snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+	else
+		snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+
+	switch (magician_in_sel) {
+	case MAGICIAN_MIC:
+		snd_soc_dapm_disable_pin(codec, "Headset Mic");
+		snd_soc_dapm_enable_pin(codec, "Call Mic");
+		break;
+	case MAGICIAN_MIC_EXT:
+		snd_soc_dapm_disable_pin(codec, "Call Mic");
+		snd_soc_dapm_enable_pin(codec, "Headset Mic");
+		break;
+	}
+
+	snd_soc_dapm_sync(codec);
+}
+
+static int magician_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->socdev->card->codec;
+
+	/* check the jack status at stream startup */
+	magician_ext_control(codec);
+
+	return 0;
+}
+
+/*
+ * Magician uses SSP port for playback.
+ */
+static int magician_playback_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;
+	unsigned int acps, acds, width, rate;
+	unsigned int div4 = PXA_SSP_CLK_SCDB_4;
+	int ret = 0;
+
+	rate = params_rate(params);
+	width = snd_pcm_format_physical_width(params_format(params));
+
+	/*
+	 * rate = SSPSCLK / (2 * width(16 or 32))
+	 * SSPSCLK = (ACPS / ACDS) / SSPSCLKDIV(div4 or div1)
+	 */
+	switch (params_rate(params)) {
+	case 8000:
+		/* off by a factor of 2: bug in the PXA27x audio clock? */
+		acps = 32842000;
+		switch (width) {
+		case 16:
+			/* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_16;
+			break;
+		case 32:
+			/* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_8;
+		}
+		break;
+	case 11025:
+		acps = 5622000;
+		switch (width) {
+		case 16:
+			/* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_4;
+			break;
+		case 32:
+			/* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+		}
+		break;
+	case 22050:
+		acps = 5622000;
+		switch (width) {
+		case 16:
+			/* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+			break;
+		case 32:
+			/* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_1;
+		}
+		break;
+	case 44100:
+		acps = 5622000;
+		switch (width) {
+		case 16:
+			/* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+			break;
+		case 32:
+			/* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_1;
+		}
+		break;
+	case 48000:
+		acps = 12235000;
+		switch (width) {
+		case 16:
+			/* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+			break;
+		case 32:
+			/* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_1;
+		}
+		break;
+	case 96000:
+		acps = 12235000;
+		switch (width) {
+		case 16:
+			/* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_1;
+			break;
+		case 32:
+			/* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+			div4 = PXA_SSP_CLK_SCDB_1;
+			break;
+		}
+		break;
+	}
+
+	/* set codec DAI configuration */
+	ret = snd_soc_dai_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 = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+			SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	/* set audio clock as clock source */
+	ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0,
+			SND_SOC_CLOCK_OUT);
+	if (ret < 0)
+		return ret;
+
+	/* set the SSP audio system clock ACDS divider */
+	ret = snd_soc_dai_set_clkdiv(cpu_dai,
+			PXA_SSP_AUDIO_DIV_ACDS, acds);
+	if (ret < 0)
+		return ret;
+
+	/* set the SSP audio system clock SCDB divider4 */
+	ret = snd_soc_dai_set_clkdiv(cpu_dai,
+			PXA_SSP_AUDIO_DIV_SCDB, div4);
+	if (ret < 0)
+		return ret;
+
+	/* set SSP audio pll clock */
+	ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, acps);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Magician uses I2S for capture.
+ */
+static int magician_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_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+	int ret = 0;
+
+	/* set codec DAI configuration */
+	ret = snd_soc_dai_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 = snd_soc_dai_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 = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+			SND_SOC_CLOCK_OUT);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops magician_capture_ops = {
+	.startup = magician_startup,
+	.hw_params = magician_capture_hw_params,
+};
+
+static struct snd_soc_ops magician_playback_ops = {
+	.startup = magician_startup,
+	.hw_params = magician_playback_hw_params,
+};
+
+static int magician_get_hp(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = magician_hp_switch;
+	return 0;
+}
+
+static int magician_set_hp(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	if (magician_hp_switch == ucontrol->value.integer.value[0])
+		return 0;
+
+	magician_hp_switch = ucontrol->value.integer.value[0];
+	magician_ext_control(codec);
+	return 1;
+}
+
+static int magician_get_spk(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = magician_spk_switch;
+	return 0;
+}
+
+static int magician_set_spk(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	if (magician_spk_switch == ucontrol->value.integer.value[0])
+		return 0;
+
+	magician_spk_switch = ucontrol->value.integer.value[0];
+	magician_ext_control(codec);
+	return 1;
+}
+
+static int magician_get_input(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = magician_in_sel;
+	return 0;
+}
+
+static int magician_set_input(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	if (magician_in_sel == ucontrol->value.integer.value[0])
+		return 0;
+
+	magician_in_sel = ucontrol->value.integer.value[0];
+
+	switch (magician_in_sel) {
+	case MAGICIAN_MIC:
+		gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 1);
+		break;
+	case MAGICIAN_MIC_EXT:
+		gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 0);
+	}
+
+	return 1;
+}
+
+static int magician_spk_power(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, SND_SOC_DAPM_EVENT_ON(event));
+	return 0;
+}
+
+static int magician_hp_power(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	gpio_set_value(EGPIO_MAGICIAN_EP_POWER, SND_SOC_DAPM_EVENT_ON(event));
+	return 0;
+}
+
+static int magician_mic_bias(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, SND_SOC_DAPM_EVENT_ON(event));
+	return 0;
+}
+
+/* magician machine dapm widgets */
+static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", magician_hp_power),
+	SND_SOC_DAPM_SPK("Speaker", magician_spk_power),
+	SND_SOC_DAPM_MIC("Call Mic", magician_mic_bias),
+	SND_SOC_DAPM_MIC("Headset Mic", magician_mic_bias),
+};
+
+/* magician machine audio_map */
+static const struct snd_soc_dapm_route audio_map[] = {
+
+	/* Headphone connected to VOUTL, VOUTR */
+	{"Headphone Jack", NULL, "VOUTL"},
+	{"Headphone Jack", NULL, "VOUTR"},
+
+	/* Speaker connected to VOUTL, VOUTR */
+	{"Speaker", NULL, "VOUTL"},
+	{"Speaker", NULL, "VOUTR"},
+
+	/* Mics are connected to VINM */
+	{"VINM", NULL, "Headset Mic"},
+	{"VINM", NULL, "Call Mic"},
+};
+
+static const char *input_select[] = {"Call Mic", "Headset Mic"};
+static const struct soc_enum magician_in_sel_enum =
+	SOC_ENUM_SINGLE_EXT(2, input_select);
+
+static const struct snd_kcontrol_new uda1380_magician_controls[] = {
+	SOC_SINGLE_BOOL_EXT("Headphone Switch",
+			(unsigned long)&magician_hp_switch,
+			magician_get_hp, magician_set_hp),
+	SOC_SINGLE_BOOL_EXT("Speaker Switch",
+			(unsigned long)&magician_spk_switch,
+			magician_get_spk, magician_set_spk),
+	SOC_ENUM_EXT("Input Select", magician_in_sel_enum,
+			magician_get_input, magician_set_input),
+};
+
+/*
+ * Logic for a uda1380 as connected on a HTC Magician
+ */
+static int magician_uda1380_init(struct snd_soc_codec *codec)
+{
+	int i, err;
+
+	/* NC codec pins */
+	snd_soc_dapm_disable_pin(codec, "VOUTLHP");
+	snd_soc_dapm_disable_pin(codec, "VOUTRHP");
+
+	/* FIXME: is anything connected here? */
+	snd_soc_dapm_disable_pin(codec, "VINL");
+	snd_soc_dapm_disable_pin(codec, "VINR");
+
+	/* Add magician specific controls */
+	for (i = 0; i < ARRAY_SIZE(uda1380_magician_controls); i++) {
+		err = snd_ctl_add(codec->card,
+				  snd_soc_cnew(&uda1380_magician_controls[i],
+						codec, NULL));
+		if (err < 0)
+			return err;
+	}
+
+	/* Add magician specific widgets */
+	snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
+				  ARRAY_SIZE(uda1380_dapm_widgets));
+
+	/* Set up magician specific audio path interconnects */
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+	snd_soc_dapm_sync(codec);
+	return 0;
+}
+
+/* magician digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link magician_dai[] = {
+{
+	.name = "uda1380",
+	.stream_name = "UDA1380 Playback",
+	.cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1],
+	.codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK],
+	.init = magician_uda1380_init,
+	.ops = &magician_playback_ops,
+},
+{
+	.name = "uda1380",
+	.stream_name = "UDA1380 Capture",
+	.cpu_dai = &pxa_i2s_dai,
+	.codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE],
+	.ops = &magician_capture_ops,
+}
+};
+
+/* magician audio machine driver */
+static struct snd_soc_card snd_soc_card_magician = {
+	.name = "Magician",
+	.dai_link = magician_dai,
+	.num_links = ARRAY_SIZE(magician_dai),
+	.platform = &pxa2xx_soc_platform,
+};
+
+/* magician audio private data */
+static struct uda1380_setup_data magician_uda1380_setup = {
+	.i2c_address = 0x18,
+	.dac_clk = UDA1380_DAC_CLK_WSPLL,
+};
+
+/* magician audio subsystem */
+static struct snd_soc_device magician_snd_devdata = {
+	.card = &snd_soc_card_magician,
+	.codec_dev = &soc_codec_dev_uda1380,
+	.codec_data = &magician_uda1380_setup,
+};
+
+static struct platform_device *magician_snd_device;
+
+static int __init magician_init(void)
+{
+	int ret;
+
+	if (!machine_is_magician())
+		return -ENODEV;
+
+	ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER");
+	if (ret)
+		goto err_request_power;
+	ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET");
+	if (ret)
+		goto err_request_reset;
+	ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER");
+	if (ret)
+		goto err_request_spk;
+	ret = gpio_request(EGPIO_MAGICIAN_EP_POWER, "EP_POWER");
+	if (ret)
+		goto err_request_ep;
+	ret = gpio_request(EGPIO_MAGICIAN_MIC_POWER, "MIC_POWER");
+	if (ret)
+		goto err_request_mic;
+	ret = gpio_request(EGPIO_MAGICIAN_IN_SEL0, "IN_SEL0");
+	if (ret)
+		goto err_request_in_sel0;
+	ret = gpio_request(EGPIO_MAGICIAN_IN_SEL1, "IN_SEL1");
+	if (ret)
+		goto err_request_in_sel1;
+
+	gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1);
+	gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0);
+
+	/* we may need to have the clock running here - pH5 */
+	gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1);
+	udelay(5);
+	gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0);
+
+	magician_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!magician_snd_device) {
+		ret = -ENOMEM;
+		goto err_pdev;
+	}
+
+	platform_set_drvdata(magician_snd_device, &magician_snd_devdata);
+	magician_snd_devdata.dev = &magician_snd_device->dev;
+	ret = platform_device_add(magician_snd_device);
+	if (ret) {
+		platform_device_put(magician_snd_device);
+		goto err_pdev;
+	}
+
+	return 0;
+
+err_pdev:
+	gpio_free(EGPIO_MAGICIAN_IN_SEL1);
+err_request_in_sel1:
+	gpio_free(EGPIO_MAGICIAN_IN_SEL0);
+err_request_in_sel0:
+	gpio_free(EGPIO_MAGICIAN_MIC_POWER);
+err_request_mic:
+	gpio_free(EGPIO_MAGICIAN_EP_POWER);
+err_request_ep:
+	gpio_free(EGPIO_MAGICIAN_SPK_POWER);
+err_request_spk:
+	gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
+err_request_reset:
+	gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
+err_request_power:
+	return ret;
+}
+
+static void __exit magician_exit(void)
+{
+	platform_device_unregister(magician_snd_device);
+
+	gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0);
+	gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0);
+	gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0);
+	gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0);
+
+	gpio_free(EGPIO_MAGICIAN_IN_SEL1);
+	gpio_free(EGPIO_MAGICIAN_IN_SEL0);
+	gpio_free(EGPIO_MAGICIAN_MIC_POWER);
+	gpio_free(EGPIO_MAGICIAN_EP_POWER);
+	gpio_free(EGPIO_MAGICIAN_SPK_POWER);
+	gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
+	gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
+}
+
+module_init(magician_init);
+module_exit(magician_exit);
+
+MODULE_AUTHOR("Philipp Zabel");
+MODULE_DESCRIPTION("ALSA SoC Magician");
+MODULE_LICENSE("GPL");
-- 
1.6.2

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-11 18:16 [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo Philipp Zabel
  2009-03-11 18:16 ` [PATCH 2/3][RFC] ASoC: Add Magician machine support Philipp Zabel
@ 2009-03-11 18:17 ` Philipp Zabel
  2009-03-11 18:44   ` Daniel Mack
  2009-03-11 22:27   ` Mark Brown
  2009-03-12 15:57 ` [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo Mark Brown
  2 siblings, 2 replies; 25+ messages in thread
From: Philipp Zabel @ 2009-03-11 18:17 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, Philipp Zabel

As soon as CONFIG_PXA25x is enabled, those macros only handle the PXA25x_SSP
case, which is wrong most of the time (and always wrong on >=PXA27x).

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>

Conflicts:

	sound/soc/pxa/pxa-ssp.c
---
 sound/soc/pxa/pxa-ssp.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index bc9d306..2a2c322 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -287,10 +287,17 @@ static void ssp_set_scr(struct ssp_priv *priv, u32 div)
 {
 	struct ssp_dev *dev = &priv->dev;
 	struct ssp_device *ssp = dev->ssp;
-	u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
+	u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0);
 
 	priv->scr_div = div;
-	ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
+	if (ssp->type == PXA25x_SSP) {
+		sscr0 &= ~0x0000ff00;        /* SSCR0_SCR */
+		sscr0 |= ((div - 2)/2) << 8; /* SSCR0_SerClkDiv(div) */
+	} else {
+		sscr0 &= ~0x000fff00;        /* SSCR0_SCR */
+		sscr0 |= (div - 1) << 8;     /* SSCR0_SerClkDiv(div) */
+	}
+	ssp_write_reg(ssp, SSCR0, sscr0);
 }
 
 /*
-- 
1.6.2

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-11 18:17 ` [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR Philipp Zabel
@ 2009-03-11 18:44   ` Daniel Mack
  2009-03-11 21:10     ` pHilipp Zabel
  2009-03-11 22:27   ` Mark Brown
  1 sibling, 1 reply; 25+ messages in thread
From: Daniel Mack @ 2009-03-11 18:44 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: alsa-devel, Mark Brown

On Wed, Mar 11, 2009 at 07:17:00PM +0100, Philipp Zabel wrote:
> As soon as CONFIG_PXA25x is enabled, those macros only handle the PXA25x_SSP
> case, which is wrong most of the time (and always wrong on >=PXA27x).

Ah, I just (while reading this header file) wondered how this is
supposed to work :)

> @@ -287,10 +287,17 @@ static void ssp_set_scr(struct ssp_priv *priv, u32 div)
>  {
>  	struct ssp_dev *dev = &priv->dev;
>  	struct ssp_device *ssp = dev->ssp;
> -	u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
> +	u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0);
>  
>  	priv->scr_div = div;
> -	ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
> +	if (ssp->type == PXA25x_SSP) {
> +		sscr0 &= ~0x0000ff00;        /* SSCR0_SCR */
> +		sscr0 |= ((div - 2)/2) << 8; /* SSCR0_SerClkDiv(div) */
> +	} else {
> +		sscr0 &= ~0x000fff00;        /* SSCR0_SCR */
> +		sscr0 |= (div - 1) << 8;     /* SSCR0_SerClkDiv(div) */
> +	}
> +	ssp_write_reg(ssp, SSCR0, sscr0);
>  }

Then we need something like ssp_get_scr() as well to cover my special
case which uses SSCR0_SCR and SSCR0_SerClkDiv() again as you proposed ;)

Daniel

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3][RFC] ASoC: Add Magician machine support.
  2009-03-11 18:16 ` [PATCH 2/3][RFC] ASoC: Add Magician machine support Philipp Zabel
@ 2009-03-11 19:02   ` Liam Girdwood
  2009-03-11 21:03     ` pHilipp Zabel
  2009-03-11 22:25   ` Mark Brown
  1 sibling, 1 reply; 25+ messages in thread
From: Liam Girdwood @ 2009-03-11 19:02 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: alsa-devel, Mark Brown

Overall looks good. One very minor issue :-

On Wed, 2009-03-11 at 19:16 +0100, Philipp Zabel wrote:
> HTC Magician has a Philips UDA1380 codec connected via
> SSP1 (playback) and I2S (capture).
> There is a flip-flop between the SSP frame clock output
> and the codec's word select input pin. To make the codec
> see proper I2S input, the SSP has to send two frames per
> sample.
> 
> Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
> ---
>  sound/soc/pxa/Kconfig    |   10 +
>  sound/soc/pxa/Makefile   |    2 +
>  sound/soc/pxa/magician.c |  563 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 575 insertions(+), 0 deletions(-)
>  create mode 100644 sound/soc/pxa/magician.c
> 

snip

> --- /dev/null
> +++ b/sound/soc/pxa/magician.c
> @@ -0,0 +1,563 @@
> +/*
> + * SoC audio for HTC Magician
> + *
> + * Copyright (c) 2006-2009 Philipp Zabel <philipp.zabel@gmail.com>
> + *
> + * based on spitz.c,
> + * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>

This address is no longer valid. Could you change to the address I'm
sending with.

Thanks

Liam

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3][RFC] ASoC: Add Magician machine support.
  2009-03-11 19:02   ` Liam Girdwood
@ 2009-03-11 21:03     ` pHilipp Zabel
  0 siblings, 0 replies; 25+ messages in thread
From: pHilipp Zabel @ 2009-03-11 21:03 UTC (permalink / raw)
  To: Liam Girdwood; +Cc: alsa-devel, Mark Brown

On Wed, Mar 11, 2009 at 8:02 PM, Liam Girdwood <lrg@slimlogic.co.uk> wrote:
> Overall looks good. One very minor issue :-
>
> On Wed, 2009-03-11 at 19:16 +0100, Philipp Zabel wrote:
>> HTC Magician has a Philips UDA1380 codec connected via
>> SSP1 (playback) and I2S (capture).
>> There is a flip-flop between the SSP frame clock output
>> and the codec's word select input pin. To make the codec
>> see proper I2S input, the SSP has to send two frames per
>> sample.
>>
>> Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
>> ---
>>  sound/soc/pxa/Kconfig    |   10 +
>>  sound/soc/pxa/Makefile   |    2 +
>>  sound/soc/pxa/magician.c |  563 ++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 575 insertions(+), 0 deletions(-)
>>  create mode 100644 sound/soc/pxa/magician.c
>>
>
> snip
>
>> --- /dev/null
>> +++ b/sound/soc/pxa/magician.c
>> @@ -0,0 +1,563 @@
>> +/*
>> + * SoC audio for HTC Magician
>> + *
>> + * Copyright (c) 2006-2009 Philipp Zabel <philipp.zabel@gmail.com>
>> + *
>> + * based on spitz.c,
>> + * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
>
> This address is no longer valid. Could you change to the address I'm
> sending with.

Of course, thanks. Will resend tomorrow with the address corrected.

regards
Philipp

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-11 18:44   ` Daniel Mack
@ 2009-03-11 21:10     ` pHilipp Zabel
  2009-03-12  0:46       ` Daniel Mack
  0 siblings, 1 reply; 25+ messages in thread
From: pHilipp Zabel @ 2009-03-11 21:10 UTC (permalink / raw)
  To: Daniel Mack; +Cc: alsa-devel, Mark Brown

On Wed, Mar 11, 2009 at 7:44 PM, Daniel Mack <daniel@caiaq.de> wrote:
> On Wed, Mar 11, 2009 at 07:17:00PM +0100, Philipp Zabel wrote:
>> As soon as CONFIG_PXA25x is enabled, those macros only handle the PXA25x_SSP
>> case, which is wrong most of the time (and always wrong on >=PXA27x).
>
> Ah, I just (while reading this header file) wondered how this is
> supposed to work :)
>
>> @@ -287,10 +287,17 @@ static void ssp_set_scr(struct ssp_priv *priv, u32 div)
>>  {
>>       struct ssp_dev *dev = &priv->dev;
>>       struct ssp_device *ssp = dev->ssp;
>> -     u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
>> +     u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0);
>>
>>       priv->scr_div = div;
>> -     ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
>> +     if (ssp->type == PXA25x_SSP) {
>> +             sscr0 &= ~0x0000ff00;        /* SSCR0_SCR */
>> +             sscr0 |= ((div - 2)/2) << 8; /* SSCR0_SerClkDiv(div) */
>> +     } else {
>> +             sscr0 &= ~0x000fff00;        /* SSCR0_SCR */
>> +             sscr0 |= (div - 1) << 8;     /* SSCR0_SerClkDiv(div) */
>> +     }
>> +     ssp_write_reg(ssp, SSCR0, sscr0);
>>  }
>
> Then we need something like ssp_get_scr() as well to cover my special
> case which uses SSCR0_SCR and SSCR0_SerClkDiv() again as you proposed ;)

Aren't I clever... How about something like this:

---
 sound/soc/pxa/pxa-ssp.c |   30 ++++++++++++++++++++++++++----
 1 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 3cde686..245063b 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -284,9 +284,30 @@ static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
 static void ssp_set_scr(struct ssp_dev *dev, u32 div)
 {
 	struct ssp_device *ssp = dev->ssp;
-	u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
+	u32 sscr0 = ssp_read_reg(ssp, SSCR0);
+
+	if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP) {
+		sscr0 &= ~0x0000ff00;
+		sscr0 |= ((div - 2)/2) << 8;
+	} else {
+		sscr0 &= ~0x000fff00;
+		sscr0 |= (div - 1) << 8;
+	}
+	ssp_write_reg(ssp, SSCR0, sscr0);
+}

-	ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
+/**
+ * ssp_get_clkdiv - get SSP clock divider
+ */
+static u32 ssp_get_scr(struct ssp_dev *dev)
+{
+	struct ssp_device *ssp = dev->ssp;
+	u32 sscr0 = ssp_read_reg(ssp, SSCR0);
+
+	if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP)
+		return ((sscr0 >> 8) & 0xff) * 2 + 2;
+	else
+		return ((sscr0 >> 8) & 0xfff) + 1;
 }

 /*
@@ -668,8 +689,7 @@ static int pxa_ssp_hw_params(struct
snd_pcm_substream *substream,
 	case SND_SOC_DAIFMT_I2S:
 	       sspsp = ssp_read_reg(ssp, SSPSP);

-		if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) &&
-		     (width == 16)) {
+		if (ssp_get_scr(ssp) == 4) && (width == 16)) {
 			/* This is a special case where the bitclk is 64fs
 			* and we're not dealing with 2*32 bits of audio
 			* samples.
-- 
1.6.2

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3][RFC] ASoC: Add Magician machine support.
  2009-03-11 18:16 ` [PATCH 2/3][RFC] ASoC: Add Magician machine support Philipp Zabel
  2009-03-11 19:02   ` Liam Girdwood
@ 2009-03-11 22:25   ` Mark Brown
  2009-03-11 22:38     ` Liam Girdwood
  2009-03-12 10:06     ` [PATCH] ASoC: Add Magician machine support Philipp Zabel
  1 sibling, 2 replies; 25+ messages in thread
From: Mark Brown @ 2009-03-11 22:25 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: alsa-devel

On Wed, Mar 11, 2009 at 07:16:59PM +0100, Philipp Zabel wrote:

This is all good except you're missing updates for a few new APIs:

> +	/* NC codec pins */
> +	snd_soc_dapm_disable_pin(codec, "VOUTLHP");
> +	snd_soc_dapm_disable_pin(codec, "VOUTRHP");

snd_soc_dapm_nc_pin() (currently a synonym but hopefully in the future
it will gain support for things like masking out controls for that path
from the UI.

> +	/* Add magician specific controls */
> +	for (i = 0; i < ARRAY_SIZE(uda1380_magician_controls); i++) {
> +		err = snd_ctl_add(codec->card,
> +				  snd_soc_cnew(&uda1380_magician_controls[i],
> +						codec, NULL));
> +		if (err < 0)
> +			return err;
> +	}

snd_soc_add_controls()

> +	ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET");
> +	if (ret)
> +		goto err_request_reset;

Someone needs to write a bulk GPIO request API...  not an issue for
merging this patch, though.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-11 18:17 ` [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR Philipp Zabel
  2009-03-11 18:44   ` Daniel Mack
@ 2009-03-11 22:27   ` Mark Brown
  2009-03-11 22:29     ` Mark Brown
  1 sibling, 1 reply; 25+ messages in thread
From: Mark Brown @ 2009-03-11 22:27 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: alsa-devel

On Wed, Mar 11, 2009 at 07:17:00PM +0100, Philipp Zabel wrote:
> As soon as CONFIG_PXA25x is enabled, those macros only handle the PXA25x_SSP
> case, which is wrong most of the time (and always wrong on >=PXA27x).
> 
> Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>

Applied, thanks.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-11 22:27   ` Mark Brown
@ 2009-03-11 22:29     ` Mark Brown
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2009-03-11 22:29 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: alsa-devel

On Wed, Mar 11, 2009 at 10:27:24PM +0000, Mark Brown wrote:
> On Wed, Mar 11, 2009 at 07:17:00PM +0100, Philipp Zabel wrote:
> > As soon as CONFIG_PXA25x is enabled, those macros only handle the PXA25x_SSP
> > case, which is wrong most of the time (and always wrong on >=PXA27x).
> > 
> > Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>

> Applied, thanks.

Or not, sorry - wires crossed there.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3][RFC] ASoC: Add Magician machine support.
  2009-03-11 22:25   ` Mark Brown
@ 2009-03-11 22:38     ` Liam Girdwood
  2009-03-11 22:44       ` Mark Brown
  2009-03-12 10:06     ` [PATCH] ASoC: Add Magician machine support Philipp Zabel
  1 sibling, 1 reply; 25+ messages in thread
From: Liam Girdwood @ 2009-03-11 22:38 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, Philipp Zabel

On Wed, 2009-03-11 at 22:25 +0000, Mark Brown wrote:
> On Wed, Mar 11, 2009 at 07:16:59PM +0100, Philipp Zabel wrote:
> 
> This is all good except you're missing updates for a few new APIs:
> 
> > +	/* NC codec pins */
> > +	snd_soc_dapm_disable_pin(codec, "VOUTLHP");
> > +	snd_soc_dapm_disable_pin(codec, "VOUTRHP");
> 
> snd_soc_dapm_nc_pin() (currently a synonym but hopefully in the future
> it will gain support for things like masking out controls for that path
> from the UI.
> 
> > +	/* Add magician specific controls */
> > +	for (i = 0; i < ARRAY_SIZE(uda1380_magician_controls); i++) {
> > +		err = snd_ctl_add(codec->card,
> > +				  snd_soc_cnew(&uda1380_magician_controls[i],
> > +						codec, NULL));
> > +		if (err < 0)
> > +			return err;
> > +	}
> 
> snd_soc_add_controls()

I'm thinking we should probably make snd_soc_cnew() static now. It's far
more convenient to use snd_soc_add_controls().

> 
> > +	ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET");
> > +	if (ret)
> > +		goto err_request_reset;
> 
> Someone needs to write a bulk GPIO request API...  not an issue for
> merging this patch, though.

My thoughts exactly :)

Liam

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/3][RFC] ASoC: Add Magician machine support.
  2009-03-11 22:38     ` Liam Girdwood
@ 2009-03-11 22:44       ` Mark Brown
  2009-03-12 10:07         ` [PATCH 3/5] ASoC: Replace remaining uses of snd_soc_cnew with snd_soc_add_controls Philipp Zabel
  0 siblings, 1 reply; 25+ messages in thread
From: Mark Brown @ 2009-03-11 22:44 UTC (permalink / raw)
  To: Liam Girdwood; +Cc: alsa-devel, Philipp Zabel

On Wed, Mar 11, 2009 at 10:38:12PM +0000, Liam Girdwood wrote:
> On Wed, 2009-03-11 at 22:25 +0000, Mark Brown wrote:

> > snd_soc_add_controls()

> I'm thinking we should probably make snd_soc_cnew() static now. It's far
> more convenient to use snd_soc_add_controls().

Yup, I was intending to do that after the merge window - add_controls is
new for .30 and there hasn't been too much API change this merge window
so it seemed helpful to keep it around for the time being.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-11 21:10     ` pHilipp Zabel
@ 2009-03-12  0:46       ` Daniel Mack
  2009-03-12 10:23         ` Mark Brown
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Mack @ 2009-03-12  0:46 UTC (permalink / raw)
  To: pHilipp Zabel; +Cc: alsa-devel, Mark Brown

On Wed, Mar 11, 2009 at 10:10:27PM +0100, pHilipp Zabel wrote:
> > Then we need something like ssp_get_scr() as well to cover my special
> > case which uses SSCR0_SCR and SSCR0_SerClkDiv() again as you proposed ;)
> 
> Aren't I clever... How about something like this:

Jep, look good to me.

(Just for the reference - this one needs to be applied on top of my last
 'network vs psp mode' patch, otherwise the second hunk won't apply).

Thanks,
Daniel


> ---
>  sound/soc/pxa/pxa-ssp.c |   30 ++++++++++++++++++++++++++----
>  1 files changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
> index 3cde686..245063b 100644
> --- a/sound/soc/pxa/pxa-ssp.c
> +++ b/sound/soc/pxa/pxa-ssp.c
> @@ -284,9 +284,30 @@ static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
>  static void ssp_set_scr(struct ssp_dev *dev, u32 div)
>  {
>  	struct ssp_device *ssp = dev->ssp;
> -	u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
> +	u32 sscr0 = ssp_read_reg(ssp, SSCR0);
> +
> +	if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP) {
> +		sscr0 &= ~0x0000ff00;
> +		sscr0 |= ((div - 2)/2) << 8;
> +	} else {
> +		sscr0 &= ~0x000fff00;
> +		sscr0 |= (div - 1) << 8;
> +	}
> +	ssp_write_reg(ssp, SSCR0, sscr0);
> +}
> 
> -	ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
> +/**
> + * ssp_get_clkdiv - get SSP clock divider
> + */
> +static u32 ssp_get_scr(struct ssp_dev *dev)
> +{
> +	struct ssp_device *ssp = dev->ssp;
> +	u32 sscr0 = ssp_read_reg(ssp, SSCR0);
> +
> +	if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP)
> +		return ((sscr0 >> 8) & 0xff) * 2 + 2;
> +	else
> +		return ((sscr0 >> 8) & 0xfff) + 1;
>  }
> 
>  /*
> @@ -668,8 +689,7 @@ static int pxa_ssp_hw_params(struct
> snd_pcm_substream *substream,
>  	case SND_SOC_DAIFMT_I2S:
>  	       sspsp = ssp_read_reg(ssp, SSPSP);
> 
> -		if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) &&
> -		     (width == 16)) {
> +		if (ssp_get_scr(ssp) == 4) && (width == 16)) {
>  			/* This is a special case where the bitclk is 64fs
>  			* and we're not dealing with 2*32 bits of audio
>  			* samples.
> -- 
> 1.6.2

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH] ASoC: Add Magician machine support.
  2009-03-11 22:25   ` Mark Brown
  2009-03-11 22:38     ` Liam Girdwood
@ 2009-03-12 10:06     ` Philipp Zabel
  2009-03-12 15:58       ` Mark Brown
  1 sibling, 1 reply; 25+ messages in thread
From: Philipp Zabel @ 2009-03-12 10:06 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, Philipp Zabel, Liam Girdwood

HTC Magician has a Philips UDA1380 codec connected via
SSP1 (playback) and I2S (capture).
There is a flip-flop between the SSP frame clock output
and the codec's word select input pin. To make the codec
see proper I2S input, the SSP has to send two frames per
sample.

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
---
 sound/soc/pxa/Kconfig    |   10 +
 sound/soc/pxa/Makefile   |    2 +
 sound/soc/pxa/magician.c |  560 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 572 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/pxa/magician.c

diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 5998ab3..ad8a10f 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -116,6 +116,16 @@ config SND_SOC_ZYLONITE
 	  Say Y if you want to add support for SoC audio on the
 	  Marvell Zylonite reference platform.
 
+config SND_PXA2XX_SOC_MAGICIAN
+	tristate "SoC Audio support for HTC Magician"
+	depends on SND_PXA2XX_SOC && MACH_MAGICIAN
+	select SND_PXA2XX_SOC_I2S
+	select SND_PXA_SOC_SSP
+	select SND_SOC_UDA1380
+	help
+	  Say Y if you want to add support for SoC audio on the
+	  HTC Magician.
+
 config SND_PXA2XX_SOC_MIOA701
         tristate "SoC Audio support for MIO A701"
         depends on SND_PXA2XX_SOC && MACH_MIOA701
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 8ed881c..4b90c3c 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -20,6 +20,7 @@ snd-soc-spitz-objs := spitz.o
 snd-soc-em-x270-objs := em-x270.o
 snd-soc-palm27x-objs := palm27x.o
 snd-soc-zylonite-objs := zylonite.o
+snd-soc-magician-objs := magician.o
 snd-soc-mioa701-objs := mioa701_wm9713.o
 
 obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
@@ -31,5 +32,6 @@ obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
 obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
 obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
 obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
+obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
 obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
 obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
new file mode 100644
index 0000000..f7c4544
--- /dev/null
+++ b/sound/soc/pxa/magician.c
@@ -0,0 +1,560 @@
+/*
+ * SoC audio for HTC Magician
+ *
+ * Copyright (c) 2006 Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * based on spitz.c,
+ * 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
+ *  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/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <mach/pxa-regs.h>
+#include <mach/hardware.h>
+#include <mach/magician.h>
+#include <asm/mach-types.h>
+#include "../codecs/uda1380.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-i2s.h"
+#include "pxa-ssp.h"
+
+#define MAGICIAN_MIC       0
+#define MAGICIAN_MIC_EXT   1
+
+static int magician_hp_switch;
+static int magician_spk_switch = 1;
+static int magician_in_sel = MAGICIAN_MIC;
+
+static void magician_ext_control(struct snd_soc_codec *codec)
+{
+	if (magician_spk_switch)
+		snd_soc_dapm_enable_pin(codec, "Speaker");
+	else
+		snd_soc_dapm_disable_pin(codec, "Speaker");
+	if (magician_hp_switch)
+		snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+	else
+		snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+
+	switch (magician_in_sel) {
+	case MAGICIAN_MIC:
+		snd_soc_dapm_disable_pin(codec, "Headset Mic");
+		snd_soc_dapm_enable_pin(codec, "Call Mic");
+		break;
+	case MAGICIAN_MIC_EXT:
+		snd_soc_dapm_disable_pin(codec, "Call Mic");
+		snd_soc_dapm_enable_pin(codec, "Headset Mic");
+		break;
+	}
+
+	snd_soc_dapm_sync(codec);
+}
+
+static int magician_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->socdev->card->codec;
+
+	/* check the jack status at stream startup */
+	magician_ext_control(codec);
+
+	return 0;
+}
+
+/*
+ * Magician uses SSP port for playback.
+ */
+static int magician_playback_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;
+	unsigned int acps, acds, width, rate;
+	unsigned int div4 = PXA_SSP_CLK_SCDB_4;
+	int ret = 0;
+
+	rate = params_rate(params);
+	width = snd_pcm_format_physical_width(params_format(params));
+
+	/*
+	 * rate = SSPSCLK / (2 * width(16 or 32))
+	 * SSPSCLK = (ACPS / ACDS) / SSPSCLKDIV(div4 or div1)
+	 */
+	switch (params_rate(params)) {
+	case 8000:
+		/* off by a factor of 2: bug in the PXA27x audio clock? */
+		acps = 32842000;
+		switch (width) {
+		case 16:
+			/* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_16;
+			break;
+		case 32:
+			/* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_8;
+		}
+		break;
+	case 11025:
+		acps = 5622000;
+		switch (width) {
+		case 16:
+			/* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_4;
+			break;
+		case 32:
+			/* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+		}
+		break;
+	case 22050:
+		acps = 5622000;
+		switch (width) {
+		case 16:
+			/* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+			break;
+		case 32:
+			/* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_1;
+		}
+		break;
+	case 44100:
+		acps = 5622000;
+		switch (width) {
+		case 16:
+			/* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+			break;
+		case 32:
+			/* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_1;
+		}
+		break;
+	case 48000:
+		acps = 12235000;
+		switch (width) {
+		case 16:
+			/* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+			break;
+		case 32:
+			/* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_1;
+		}
+		break;
+	case 96000:
+		acps = 12235000;
+		switch (width) {
+		case 16:
+			/* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_1;
+			break;
+		case 32:
+			/* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */
+			acds = PXA_SSP_CLK_AUDIO_DIV_2;
+			div4 = PXA_SSP_CLK_SCDB_1;
+			break;
+		}
+		break;
+	}
+
+	/* set codec DAI configuration */
+	ret = snd_soc_dai_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 = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+			SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBS_CFS);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	/* set audio clock as clock source */
+	ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0,
+			SND_SOC_CLOCK_OUT);
+	if (ret < 0)
+		return ret;
+
+	/* set the SSP audio system clock ACDS divider */
+	ret = snd_soc_dai_set_clkdiv(cpu_dai,
+			PXA_SSP_AUDIO_DIV_ACDS, acds);
+	if (ret < 0)
+		return ret;
+
+	/* set the SSP audio system clock SCDB divider4 */
+	ret = snd_soc_dai_set_clkdiv(cpu_dai,
+			PXA_SSP_AUDIO_DIV_SCDB, div4);
+	if (ret < 0)
+		return ret;
+
+	/* set SSP audio pll clock */
+	ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, acps);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * Magician uses I2S for capture.
+ */
+static int magician_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_dai *codec_dai = rtd->dai->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+	int ret = 0;
+
+	/* set codec DAI configuration */
+	ret = snd_soc_dai_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 = snd_soc_dai_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 = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+			SND_SOC_CLOCK_OUT);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct snd_soc_ops magician_capture_ops = {
+	.startup = magician_startup,
+	.hw_params = magician_capture_hw_params,
+};
+
+static struct snd_soc_ops magician_playback_ops = {
+	.startup = magician_startup,
+	.hw_params = magician_playback_hw_params,
+};
+
+static int magician_get_hp(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = magician_hp_switch;
+	return 0;
+}
+
+static int magician_set_hp(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	if (magician_hp_switch == ucontrol->value.integer.value[0])
+		return 0;
+
+	magician_hp_switch = ucontrol->value.integer.value[0];
+	magician_ext_control(codec);
+	return 1;
+}
+
+static int magician_get_spk(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = magician_spk_switch;
+	return 0;
+}
+
+static int magician_set_spk(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	if (magician_spk_switch == ucontrol->value.integer.value[0])
+		return 0;
+
+	magician_spk_switch = ucontrol->value.integer.value[0];
+	magician_ext_control(codec);
+	return 1;
+}
+
+static int magician_get_input(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = magician_in_sel;
+	return 0;
+}
+
+static int magician_set_input(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	if (magician_in_sel == ucontrol->value.integer.value[0])
+		return 0;
+
+	magician_in_sel = ucontrol->value.integer.value[0];
+
+	switch (magician_in_sel) {
+	case MAGICIAN_MIC:
+		gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 1);
+		break;
+	case MAGICIAN_MIC_EXT:
+		gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 0);
+	}
+
+	return 1;
+}
+
+static int magician_spk_power(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, SND_SOC_DAPM_EVENT_ON(event));
+	return 0;
+}
+
+static int magician_hp_power(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	gpio_set_value(EGPIO_MAGICIAN_EP_POWER, SND_SOC_DAPM_EVENT_ON(event));
+	return 0;
+}
+
+static int magician_mic_bias(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *k, int event)
+{
+	gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, SND_SOC_DAPM_EVENT_ON(event));
+	return 0;
+}
+
+/* magician machine dapm widgets */
+static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
+	SND_SOC_DAPM_HP("Headphone Jack", magician_hp_power),
+	SND_SOC_DAPM_SPK("Speaker", magician_spk_power),
+	SND_SOC_DAPM_MIC("Call Mic", magician_mic_bias),
+	SND_SOC_DAPM_MIC("Headset Mic", magician_mic_bias),
+};
+
+/* magician machine audio_map */
+static const struct snd_soc_dapm_route audio_map[] = {
+
+	/* Headphone connected to VOUTL, VOUTR */
+	{"Headphone Jack", NULL, "VOUTL"},
+	{"Headphone Jack", NULL, "VOUTR"},
+
+	/* Speaker connected to VOUTL, VOUTR */
+	{"Speaker", NULL, "VOUTL"},
+	{"Speaker", NULL, "VOUTR"},
+
+	/* Mics are connected to VINM */
+	{"VINM", NULL, "Headset Mic"},
+	{"VINM", NULL, "Call Mic"},
+};
+
+static const char *input_select[] = {"Call Mic", "Headset Mic"};
+static const struct soc_enum magician_in_sel_enum =
+	SOC_ENUM_SINGLE_EXT(2, input_select);
+
+static const struct snd_kcontrol_new uda1380_magician_controls[] = {
+	SOC_SINGLE_BOOL_EXT("Headphone Switch",
+			(unsigned long)&magician_hp_switch,
+			magician_get_hp, magician_set_hp),
+	SOC_SINGLE_BOOL_EXT("Speaker Switch",
+			(unsigned long)&magician_spk_switch,
+			magician_get_spk, magician_set_spk),
+	SOC_ENUM_EXT("Input Select", magician_in_sel_enum,
+			magician_get_input, magician_set_input),
+};
+
+/*
+ * Logic for a uda1380 as connected on a HTC Magician
+ */
+static int magician_uda1380_init(struct snd_soc_codec *codec)
+{
+	int err;
+
+	/* NC codec pins */
+	snd_soc_dapm_nc_pin(codec, "VOUTLHP");
+	snd_soc_dapm_nc_pin(codec, "VOUTRHP");
+
+	/* FIXME: is anything connected here? */
+	snd_soc_dapm_nc_pin(codec, "VINL");
+	snd_soc_dapm_nc_pin(codec, "VINR");
+
+	/* Add magician specific controls */
+	err = snd_soc_add_controls(codec, uda1380_magician_controls,
+				ARRAY_SIZE(uda1380_magician_controls));
+	if (err < 0)
+		return err;
+
+	/* Add magician specific widgets */
+	snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
+				  ARRAY_SIZE(uda1380_dapm_widgets));
+
+	/* Set up magician specific audio path interconnects */
+	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+	snd_soc_dapm_sync(codec);
+	return 0;
+}
+
+/* magician digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link magician_dai[] = {
+{
+	.name = "uda1380",
+	.stream_name = "UDA1380 Playback",
+	.cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1],
+	.codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK],
+	.init = magician_uda1380_init,
+	.ops = &magician_playback_ops,
+},
+{
+	.name = "uda1380",
+	.stream_name = "UDA1380 Capture",
+	.cpu_dai = &pxa_i2s_dai,
+	.codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE],
+	.ops = &magician_capture_ops,
+}
+};
+
+/* magician audio machine driver */
+static struct snd_soc_card snd_soc_card_magician = {
+	.name = "Magician",
+	.dai_link = magician_dai,
+	.num_links = ARRAY_SIZE(magician_dai),
+	.platform = &pxa2xx_soc_platform,
+};
+
+/* magician audio private data */
+static struct uda1380_setup_data magician_uda1380_setup = {
+	.i2c_address = 0x18,
+	.dac_clk = UDA1380_DAC_CLK_WSPLL,
+};
+
+/* magician audio subsystem */
+static struct snd_soc_device magician_snd_devdata = {
+	.card = &snd_soc_card_magician,
+	.codec_dev = &soc_codec_dev_uda1380,
+	.codec_data = &magician_uda1380_setup,
+};
+
+static struct platform_device *magician_snd_device;
+
+static int __init magician_init(void)
+{
+	int ret;
+
+	if (!machine_is_magician())
+		return -ENODEV;
+
+	ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER");
+	if (ret)
+		goto err_request_power;
+	ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET");
+	if (ret)
+		goto err_request_reset;
+	ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER");
+	if (ret)
+		goto err_request_spk;
+	ret = gpio_request(EGPIO_MAGICIAN_EP_POWER, "EP_POWER");
+	if (ret)
+		goto err_request_ep;
+	ret = gpio_request(EGPIO_MAGICIAN_MIC_POWER, "MIC_POWER");
+	if (ret)
+		goto err_request_mic;
+	ret = gpio_request(EGPIO_MAGICIAN_IN_SEL0, "IN_SEL0");
+	if (ret)
+		goto err_request_in_sel0;
+	ret = gpio_request(EGPIO_MAGICIAN_IN_SEL1, "IN_SEL1");
+	if (ret)
+		goto err_request_in_sel1;
+
+	gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1);
+	gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0);
+
+	/* we may need to have the clock running here - pH5 */
+	gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1);
+	udelay(5);
+	gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0);
+
+	magician_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!magician_snd_device) {
+		ret = -ENOMEM;
+		goto err_pdev;
+	}
+
+	platform_set_drvdata(magician_snd_device, &magician_snd_devdata);
+	magician_snd_devdata.dev = &magician_snd_device->dev;
+	ret = platform_device_add(magician_snd_device);
+	if (ret) {
+		platform_device_put(magician_snd_device);
+		goto err_pdev;
+	}
+
+	return 0;
+
+err_pdev:
+	gpio_free(EGPIO_MAGICIAN_IN_SEL1);
+err_request_in_sel1:
+	gpio_free(EGPIO_MAGICIAN_IN_SEL0);
+err_request_in_sel0:
+	gpio_free(EGPIO_MAGICIAN_MIC_POWER);
+err_request_mic:
+	gpio_free(EGPIO_MAGICIAN_EP_POWER);
+err_request_ep:
+	gpio_free(EGPIO_MAGICIAN_SPK_POWER);
+err_request_spk:
+	gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
+err_request_reset:
+	gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
+err_request_power:
+	return ret;
+}
+
+static void __exit magician_exit(void)
+{
+	platform_device_unregister(magician_snd_device);
+
+	gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0);
+	gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0);
+	gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0);
+	gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0);
+
+	gpio_free(EGPIO_MAGICIAN_IN_SEL1);
+	gpio_free(EGPIO_MAGICIAN_IN_SEL0);
+	gpio_free(EGPIO_MAGICIAN_MIC_POWER);
+	gpio_free(EGPIO_MAGICIAN_EP_POWER);
+	gpio_free(EGPIO_MAGICIAN_SPK_POWER);
+	gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
+	gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
+}
+
+module_init(magician_init);
+module_exit(magician_exit);
+
+MODULE_AUTHOR("Philipp Zabel");
+MODULE_DESCRIPTION("ALSA SoC Magician");
+MODULE_LICENSE("GPL");
-- 
1.6.2

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 3/5] ASoC: Replace remaining uses of snd_soc_cnew with snd_soc_add_controls.
  2009-03-11 22:44       ` Mark Brown
@ 2009-03-12 10:07         ` Philipp Zabel
  2009-03-12 10:11           ` Mark Brown
  0 siblings, 1 reply; 25+ messages in thread
From: Philipp Zabel @ 2009-03-12 10:07 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, Philipp Zabel, Liam Girdwood

The drivers are basically duplicating the same code over and over.
As snd_soc_cnew is going to be made static some time after the next
merge window, we might as well convert them now.

Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
---
 sound/soc/codecs/cs4270.c          |   23 +++++------------------
 sound/soc/codecs/tlv320aic26.c     |   11 ++++-------
 sound/soc/codecs/wm8400.c          |   12 ++----------
 sound/soc/omap/n810.c              |   12 +++++-------
 sound/soc/pxa/corgi.c              |   12 +++++-------
 sound/soc/pxa/palm27x.c            |   13 +++++--------
 sound/soc/pxa/poodle.c             |   12 +++++-------
 sound/soc/pxa/spitz.c              |   12 +++++-------
 sound/soc/pxa/tosa.c               |   12 +++++-------
 sound/soc/s3c24xx/neo1973_wm8753.c |   13 +++++--------
 10 files changed, 46 insertions(+), 86 deletions(-)

diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 0e0c23e..8e58c81 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -538,7 +538,6 @@ static int cs4270_probe(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 	struct snd_soc_codec *codec = cs4270_codec;
-	unsigned int i;
 	int ret;
 
 	/* Connect the codec to the socdev.  snd_soc_new_pcms() needs this. */
@@ -552,23 +551,11 @@ static int cs4270_probe(struct platform_device *pdev)
 	}
 
 	/* Add the non-DAPM controls */
-	for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) {
-		struct snd_kcontrol *kctrl;
-
-		kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL);
-		if (!kctrl) {
-			dev_err(codec->dev, "error creating control '%s'\n",
-			       cs4270_snd_controls[i].name);
-			ret = -ENOMEM;
-			goto error_free_pcms;
-		}
-
-		ret = snd_ctl_add(codec->card, kctrl);
-		if (ret < 0) {
-			dev_err(codec->dev, "error adding control '%s'\n",
-			       cs4270_snd_controls[i].name);
-			goto error_free_pcms;
-		}
+	ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+				ARRAY_SIZE(cs4270_snd_controls));
+	if (ret < 0) {
+		dev_err(codec->dev, "failed to add controls\n");
+		goto error_free_pcms;
 	}
 
 	/* And finally, register the socdev */
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 229e464..633bc4b 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -322,9 +322,8 @@ static int aic26_probe(struct platform_device *pdev)
 {
 	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 	struct snd_soc_codec *codec;
-	struct snd_kcontrol *kcontrol;
 	struct aic26 *aic26;
-	int i, ret, err;
+	int ret, err;
 
 	dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n");
 	dev_dbg(&pdev->dev, "socdev=%p\n", socdev);
@@ -351,11 +350,9 @@ static int aic26_probe(struct platform_device *pdev)
 
 	/* register controls */
 	dev_dbg(&pdev->dev, "Registering controls\n");
-	for (i = 0; i < ARRAY_SIZE(aic26_snd_controls); i++) {
-		kcontrol = snd_soc_cnew(&aic26_snd_controls[i], codec, NULL);
-		err = snd_ctl_add(codec->card, kcontrol);
-		WARN_ON(err < 0);
-	}
+	err = snd_soc_add_controls(codec, aic26_snd_controls,
+			ARRAY_SIZE(aic26_snd_controls));
+	WARN_ON(err < 0);
 
 	/* CODEC is setup, we can register the card now */
 	dev_dbg(&pdev->dev, "Registering card\n");
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 9cb73d9..3269121 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -351,16 +351,8 @@ SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
 /* add non dapm controls */
 static int wm8400_add_controls(struct snd_soc_codec *codec)
 {
-	int err, i;
-
-	for (i = 0; i < ARRAY_SIZE(wm8400_snd_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&wm8400_snd_controls[i],codec,
-					NULL));
-		if (err < 0)
-			return err;
-	}
-	return 0;
+	return snd_soc_add_controls(codec, wm8400_snd_controls,
+				ARRAY_SIZE(wm8400_snd_controls));
 }
 
 /*
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 9f037cd..86471fd 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -248,7 +248,7 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = {
 
 static int n810_aic33_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	/* Not connected */
 	snd_soc_dapm_nc_pin(codec, "MONO_LOUT");
@@ -256,12 +256,10 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
 	snd_soc_dapm_nc_pin(codec, "HPRCOM");
 
 	/* 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,
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 146973a..02263e5 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -276,18 +276,16 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
  */
 static int corgi_wm8731_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	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++) {
-		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&wm8731_corgi_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, wm8731_corgi_controls,
+				ARRAY_SIZE(wm8731_corgi_controls));
+	if (err < 0)
+		return err;
 
 	/* Add corgi specific widgets */
 	snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 29958cd..48a73f6 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -146,19 +146,16 @@ static const struct snd_kcontrol_new palm27x_controls[] = {
 
 static int palm27x_ac97_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	snd_soc_dapm_nc_pin(codec, "OUT3");
 	snd_soc_dapm_nc_pin(codec, "MONOOUT");
 
 	/* add palm27x specific controls */
-	for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&palm27x_controls[i],
-						codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, palm27x_controls,
+				ARRAY_SIZE(palm27x_controls));
+	if (err < 0)
+		return err;
 
 	/* add palm27x specific widgets */
 	snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index fb17a0a..ef7c6c8 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -241,19 +241,17 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = {
  */
 static int poodle_wm8731_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	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 */
-	for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
-		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&wm8731_poodle_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, wm8731_poodle_controls,
+				ARRAY_SIZE(wm8731_poodle_controls));
+	if (err < 0)
+		return err;
 
 	/* Add poodle specific widgets */
 	snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index 1aafd8c..6ca9f53 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -278,7 +278,7 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = {
  */
 static int spitz_wm8750_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	/* NC codec pins */
 	snd_soc_dapm_nc_pin(codec, "RINPUT1");
@@ -290,12 +290,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
 	snd_soc_dapm_nc_pin(codec, "MONO1");
 
 	/* Add spitz specific controls */
-	for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
-		err = snd_ctl_add(codec->card,
-			snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, wm8750_spitz_controls,
+				ARRAY_SIZE(wm8750_spitz_controls));
+	if (err < 0)
+		return err;
 
 	/* Add spitz specific widgets */
 	snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 09b5bad..fc78137 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -188,18 +188,16 @@ static const struct snd_kcontrol_new tosa_controls[] = {
 
 static int tosa_ac97_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	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++) {
-		err = snd_ctl_add(codec->card,
-				snd_soc_cnew(&tosa_controls[i],codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, tosa_controls,
+				ARRAY_SIZE(tosa_controls));
+	if (err < 0)
+		return err;
 
 	/* add tosa specific widgets */
 	snd_soc_dapm_new_controls(codec, tosa_dapm_widgets,
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 5f6aeec..289fadf 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -498,7 +498,7 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
  */
 static int neo1973_wm8753_init(struct snd_soc_codec *codec)
 {
-	int i, err;
+	int err;
 
 	pr_debug("Entered %s\n", __func__);
 
@@ -518,13 +518,10 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
 	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,
-				snd_soc_cnew(&wm8753_neo1973_controls[i],
-				codec, NULL));
-		if (err < 0)
-			return err;
-	}
+	err = snd_soc_add_controls(codec, wm8753_neo1973_controls,
+				ARRAY_SIZE(8753_neo1973_controls));
+	if (err < 0)
+		return err;
 
 	/* set up neo1973 specific audio routes */
 	err = snd_soc_dapm_add_routes(codec, dapm_routes,
-- 
1.6.2

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/5] ASoC: Replace remaining uses of snd_soc_cnew with snd_soc_add_controls.
  2009-03-12 10:07         ` [PATCH 3/5] ASoC: Replace remaining uses of snd_soc_cnew with snd_soc_add_controls Philipp Zabel
@ 2009-03-12 10:11           ` Mark Brown
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2009-03-12 10:11 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: alsa-devel, Liam Girdwood

On Thu, Mar 12, 2009 at 11:07:54AM +0100, Philipp Zabel wrote:
> The drivers are basically duplicating the same code over and over.
> As snd_soc_cnew is going to be made static some time after the next
> merge window, we might as well convert them now.

> Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>

Applied, thanks.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-12  0:46       ` Daniel Mack
@ 2009-03-12 10:23         ` Mark Brown
  2009-03-12 10:27           ` Daniel Mack
  0 siblings, 1 reply; 25+ messages in thread
From: Mark Brown @ 2009-03-12 10:23 UTC (permalink / raw)
  To: Daniel Mack; +Cc: alsa-devel, pHilipp Zabel

On Thu, Mar 12, 2009 at 01:46:39AM +0100, Daniel Mack wrote:

> (Just for the reference - this one needs to be applied on top of my last
>  'network vs psp mode' patch, otherwise the second hunk won't apply).

Could you please resubmit the most current versions of your outstanding
patches?  There's too many versions of patches floating around in the
middle of threads and I want to make sure I'm looking at the most
current versions.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-12 10:23         ` Mark Brown
@ 2009-03-12 10:27           ` Daniel Mack
  2009-03-12 10:29             ` Mark Brown
                               ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: Daniel Mack @ 2009-03-12 10:27 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, pHilipp Zabel

On Thu, Mar 12, 2009 at 10:23:56AM +0000, Mark Brown wrote:
> On Thu, Mar 12, 2009 at 01:46:39AM +0100, Daniel Mack wrote:
> 
> > (Just for the reference - this one needs to be applied on top of my last
> >  'network vs psp mode' patch, otherwise the second hunk won't apply).
> 
> Could you please resubmit the most current versions of your outstanding
> patches?  There's too many versions of patches floating around in the
> middle of threads and I want to make sure I'm looking at the most
> current versions.

Sorry. See below. There's only one left now and this one shrunk a lot.

Daniel


>From ad8734e93eed130a55482b0e937729578e6d93c8 Mon Sep 17 00:00:00 2001
From: Daniel Mack <daniel@caiaq.de>
Date: Wed, 11 Mar 2009 19:38:15 +0100
Subject: [PATCH] pxa-ssp: switch from network mode to PSP

This switches the pxa ssp port usage from network mode to PSP mode.
Removed some comments and checks for configured TDM channels.
A special case is added to support configuration where BCLK = 64fs. We
need to do some black magic in this case which doesn't look nice but
there is unfortunately no other option than that.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
---
 sound/soc/pxa/pxa-ssp.c |   44 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 52d97c4..3cde686 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -558,18 +558,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
-		sscr0 |= SSCR0_MOD | SSCR0_PSP;
+		sscr0 |= SSCR0_PSP;
 		sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
 
 		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 		case SND_SOC_DAIFMT_NB_NF:
-			sspsp |= SSPSP_FSRT;
 			break;
 		case SND_SOC_DAIFMT_NB_IF:
-			sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
+			sspsp |= SSPSP_SFRMP;
 			break;
 		case SND_SOC_DAIFMT_IB_IF:
-			sspsp |= SSPSP_SFRMP;
+			sspsp |= SSPSP_SFRMP | SSPSP_SCMODE(3);
 			break;
 		default:
 			return -EINVAL;
@@ -655,33 +654,56 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
 			sscr0 |= SSCR0_FPCKE;
 #endif
 		sscr0 |= SSCR0_DataSize(16);
-		/* use network mode (2 slots) for 16 bit stereo */
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
 		sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
-		/* we must be in network mode (2 slots) for 24 bit stereo */
 		break;
 	case SNDRV_PCM_FORMAT_S32_LE:
 		sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
-		/* we must be in network mode (2 slots) for 32 bit stereo */
 		break;
 	}
 	ssp_write_reg(ssp, SSCR0, sscr0);
 
 	switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_I2S:
-		/* Cleared when the DAI format is set */
-		sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width);
+	       sspsp = ssp_read_reg(ssp, SSPSP);
+
+		if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) &&
+		     (width == 16)) {
+			/* This is a special case where the bitclk is 64fs
+			* and we're not dealing with 2*32 bits of audio
+			* samples.
+			*
+			* The SSP values used for that are all found out by
+			* trying and failing a lot; some of the registers
+			* needed for that mode are only available on PXA3xx.
+			*/
+
+#ifdef CONFIG_PXA3xx
+			if (!cpu_is_pxa3xx())
+				return -EINVAL;
+
+			sspsp |= SSPSP_SFRMWDTH(width * 2);
+			sspsp |= SSPSP_SFRMDLY(width * 4);
+			sspsp |= SSPSP_EDMYSTOP(3);
+			sspsp |= SSPSP_DMYSTOP(3);
+			sspsp |= SSPSP_DMYSTRT(1);
+#else
+			return -EINVAL;
+#endif
+		} else
+			sspsp |= SSPSP_SFRMWDTH(width);
+
 		ssp_write_reg(ssp, SSPSP, sspsp);
 		break;
 	default:
 		break;
 	}
 
-	/* We always use a network mode so we always require TDM slots
+	/* When we use a network mode, we always require TDM slots
 	 * - complain loudly and fail if they've not been set up yet.
 	 */
-	if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) {
+	if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) {
 		dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
 		return -EINVAL;
 	}
-- 
1.6.2

^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-12 10:27           ` Daniel Mack
@ 2009-03-12 10:29             ` Mark Brown
  2009-03-12 10:36             ` Daniel Mack
  2009-03-12 19:09             ` pHilipp Zabel
  2 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2009-03-12 10:29 UTC (permalink / raw)
  To: Daniel Mack; +Cc: alsa-devel, pHilipp Zabel

On Thu, Mar 12, 2009 at 11:27:49AM +0100, Daniel Mack wrote:
> Sorry. See below. There's only one left now and this one shrunk a lot.

Oh, thanks - I had that one, from what you wrote I thought there were
more that I'd dropped on the floor.  I'll review later today.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-12 10:27           ` Daniel Mack
  2009-03-12 10:29             ` Mark Brown
@ 2009-03-12 10:36             ` Daniel Mack
  2009-03-12 19:09             ` pHilipp Zabel
  2 siblings, 0 replies; 25+ messages in thread
From: Daniel Mack @ 2009-03-12 10:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, pHilipp Zabel

On Thu, Mar 12, 2009 at 11:27:49AM +0100, Daniel Mack wrote:
> On Thu, Mar 12, 2009 at 10:23:56AM +0000, Mark Brown wrote:
> > On Thu, Mar 12, 2009 at 01:46:39AM +0100, Daniel Mack wrote:
> > 
> > > (Just for the reference - this one needs to be applied on top of my last
> > >  'network vs psp mode' patch, otherwise the second hunk won't apply).
> > 
> > Could you please resubmit the most current versions of your outstanding
> > patches?  There's too many versions of patches floating around in the
> > middle of threads and I want to make sure I'm looking at the most
> > current versions.
> 
> Sorry. See below. There's only one left now and this one shrunk a lot.

Forgot one credit to this one.

> From ad8734e93eed130a55482b0e937729578e6d93c8 Mon Sep 17 00:00:00 2001
> From: Daniel Mack <daniel@caiaq.de>
> Date: Wed, 11 Mar 2009 19:38:15 +0100
> Subject: [PATCH] pxa-ssp: switch from network mode to PSP
> 
> This switches the pxa ssp port usage from network mode to PSP mode.
> Removed some comments and checks for configured TDM channels.
> A special case is added to support configuration where BCLK = 64fs. We
> need to do some black magic in this case which doesn't look nice but
> there is unfortunately no other option than that.
> 
> Signed-off-by: Daniel Mack <daniel@caiaq.de>

Diagnosed-by: Tim Ruetz <tim@caiaq.de>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo
  2009-03-11 18:16 [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo Philipp Zabel
  2009-03-11 18:16 ` [PATCH 2/3][RFC] ASoC: Add Magician machine support Philipp Zabel
  2009-03-11 18:17 ` [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR Philipp Zabel
@ 2009-03-12 15:57 ` Mark Brown
  2 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2009-03-12 15:57 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: alsa-devel

On Wed, Mar 11, 2009 at 07:16:58PM +0100, Philipp Zabel wrote:
> Please advise how this behaviour could be made configurable. I guess
> the only machines that will ever need this are HTC Magician, Blueangel
> and Himalaya.

Mmm...  fun.  :/

For configurability I'd suggest using one of the ops that the DAI
exports to allow you to flip a variable somewhere.  That variable can
then be checked instead of your machine_is_() check.  Not terribly nice
but as you say I don't see this being needed terribly often.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH] ASoC: Add Magician machine support.
  2009-03-12 10:06     ` [PATCH] ASoC: Add Magician machine support Philipp Zabel
@ 2009-03-12 15:58       ` Mark Brown
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Brown @ 2009-03-12 15:58 UTC (permalink / raw)
  To: Philipp Zabel; +Cc: alsa-devel, Liam Girdwood

On Thu, Mar 12, 2009 at 11:06:50AM +0100, Philipp Zabel wrote:
> HTC Magician has a Philips UDA1380 codec connected via
> SSP1 (playback) and I2S (capture).
> There is a flip-flop between the SSP frame clock output
> and the codec's word select input pin. To make the codec
> see proper I2S input, the SSP has to send two frames per
> sample.

> Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>

This all looks good.  I'll hold off on applying until we've got the SSP
change resolved since it's needed for the driver to work properly.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-12 10:27           ` Daniel Mack
  2009-03-12 10:29             ` Mark Brown
  2009-03-12 10:36             ` Daniel Mack
@ 2009-03-12 19:09             ` pHilipp Zabel
  2009-03-12 19:18               ` Mark Brown
  2 siblings, 1 reply; 25+ messages in thread
From: pHilipp Zabel @ 2009-03-12 19:09 UTC (permalink / raw)
  To: Daniel Mack; +Cc: alsa-devel, Mark Brown

On Thu, Mar 12, 2009 at 11:27 AM, Daniel Mack <daniel@caiaq.de> wrote:
> On Thu, Mar 12, 2009 at 10:23:56AM +0000, Mark Brown wrote:
>> On Thu, Mar 12, 2009 at 01:46:39AM +0100, Daniel Mack wrote:
>>
>> > (Just for the reference - this one needs to be applied on top of my last
>> >  'network vs psp mode' patch, otherwise the second hunk won't apply).
>>
>> Could you please resubmit the most current versions of your outstanding
>> patches?  There's too many versions of patches floating around in the
>> middle of threads and I want to make sure I'm looking at the most
>> current versions.
>
> Sorry. See below. There's only one left now and this one shrunk a lot.
>
> Daniel
>
>
> From ad8734e93eed130a55482b0e937729578e6d93c8 Mon Sep 17 00:00:00 2001
> From: Daniel Mack <daniel@caiaq.de>
> Date: Wed, 11 Mar 2009 19:38:15 +0100
> Subject: [PATCH] pxa-ssp: switch from network mode to PSP
>
> This switches the pxa ssp port usage from network mode to PSP mode.
> Removed some comments and checks for configured TDM channels.
> A special case is added to support configuration where BCLK = 64fs. We
> need to do some black magic in this case which doesn't look nice but
> there is unfortunately no other option than that.
>
> Signed-off-by: Daniel Mack <daniel@caiaq.de>
> ---
>  sound/soc/pxa/pxa-ssp.c |   44 +++++++++++++++++++++++++++++++++-----------
>  1 files changed, 33 insertions(+), 11 deletions(-)
>
> diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
> index 52d97c4..3cde686 100644
> --- a/sound/soc/pxa/pxa-ssp.c
> +++ b/sound/soc/pxa/pxa-ssp.c
> @@ -558,18 +558,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
>
>        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
>        case SND_SOC_DAIFMT_I2S:
> -               sscr0 |= SSCR0_MOD | SSCR0_PSP;
> +               sscr0 |= SSCR0_PSP;

There is one more thing I didn't think about yet. Disabling network
mode here unconditionally should break Zylonite as is, unless it can
also be changed to use that special 64fs mode.
This code is found in zylonite_voice_hw_params right now:

        /* Use network mode for stereo, one slot per channel. */
        if (params_channels(params) > 1)
                ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 2);
        else
                ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1);
        if (ret < 0)
                return ret;

And I realize I don't quite understand why it handles the mono case at
all - isn't I2S always stereo?

>                sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
>
>                switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
>                case SND_SOC_DAIFMT_NB_NF:
> -                       sspsp |= SSPSP_FSRT;
>                        break;
>                case SND_SOC_DAIFMT_NB_IF:
> -                       sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
> +                       sspsp |= SSPSP_SFRMP;
>                        break;
>                case SND_SOC_DAIFMT_IB_IF:
> -                       sspsp |= SSPSP_SFRMP;
> +                       sspsp |= SSPSP_SFRMP | SSPSP_SCMODE(3);
>                        break;
>                default:
>                        return -EINVAL;
> @@ -655,33 +654,56 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
>                        sscr0 |= SSCR0_FPCKE;
>  #endif
>                sscr0 |= SSCR0_DataSize(16);
> -               /* use network mode (2 slots) for 16 bit stereo */
>                break;
>        case SNDRV_PCM_FORMAT_S24_LE:
>                sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
> -               /* we must be in network mode (2 slots) for 24 bit stereo */
>                break;
>        case SNDRV_PCM_FORMAT_S32_LE:
>                sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
> -               /* we must be in network mode (2 slots) for 32 bit stereo */
>                break;
>        }
>        ssp_write_reg(ssp, SSCR0, sscr0);
>
>        switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
>        case SND_SOC_DAIFMT_I2S:
> -               /* Cleared when the DAI format is set */
> -               sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width);
> +              sspsp = ssp_read_reg(ssp, SSPSP);
> +
> +               if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) &&
> +                    (width == 16)) {
> +                       /* This is a special case where the bitclk is 64fs
> +                       * and we're not dealing with 2*32 bits of audio
> +                       * samples.
> +                       *
> +                       * The SSP values used for that are all found out by
> +                       * trying and failing a lot; some of the registers
> +                       * needed for that mode are only available on PXA3xx.
> +                       */
> +
> +#ifdef CONFIG_PXA3xx
> +                       if (!cpu_is_pxa3xx())
> +                               return -EINVAL;
> +
> +                       sspsp |= SSPSP_SFRMWDTH(width * 2);
> +                       sspsp |= SSPSP_SFRMDLY(width * 4);
> +                       sspsp |= SSPSP_EDMYSTOP(3);
> +                       sspsp |= SSPSP_DMYSTOP(3);
> +                       sspsp |= SSPSP_DMYSTRT(1);
> +#else
> +                       return -EINVAL;
> +#endif
> +               } else
> +                       sspsp |= SSPSP_SFRMWDTH(width);
> +
>                ssp_write_reg(ssp, SSPSP, sspsp);
>                break;
>        default:
>                break;
>        }
>
> -       /* We always use a network mode so we always require TDM slots
> +       /* When we use a network mode, we always require TDM slots
>         * - complain loudly and fail if they've not been set up yet.
>         */
> -       if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) {
> +       if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) {
>                dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
>                return -EINVAL;
>        }
> --
> 1.6.2
>
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-12 19:09             ` pHilipp Zabel
@ 2009-03-12 19:18               ` Mark Brown
  2009-03-12 23:46                 ` Daniel Mack
  0 siblings, 1 reply; 25+ messages in thread
From: Mark Brown @ 2009-03-12 19:18 UTC (permalink / raw)
  To: pHilipp Zabel; +Cc: alsa-devel

On Thu, Mar 12, 2009 at 08:09:21PM +0100, pHilipp Zabel wrote:

> There is one more thing I didn't think about yet. Disabling network
> mode here unconditionally should break Zylonite as is, unless it can
> also be changed to use that special 64fs mode.
> This code is found in zylonite_voice_hw_params right now:

Yes, it completely hoses zylonite.  I'm currently trying to come up with
a non-networked configuration for Zylonite though.

> And I realize I don't quite understand why it handles the mono case at
> all - isn't I2S always stereo?

It's moderately common to transmit mono data in one channel of the
stereo I2S stream.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR
  2009-03-12 19:18               ` Mark Brown
@ 2009-03-12 23:46                 ` Daniel Mack
  0 siblings, 0 replies; 25+ messages in thread
From: Daniel Mack @ 2009-03-12 23:46 UTC (permalink / raw)
  To: Mark Brown; +Cc: alsa-devel, pHilipp Zabel

On Thu, Mar 12, 2009 at 07:18:03PM +0000, Mark Brown wrote:
> > There is one more thing I didn't think about yet. Disabling network
> > mode here unconditionally should break Zylonite as is, unless it can
> > also be changed to use that special 64fs mode.
> > This code is found in zylonite_voice_hw_params right now:
> 
> Yes, it completely hoses zylonite.  I'm currently trying to come up with
> a non-networked configuration for Zylonite though.

Ok, thanks. However, if you're unable to get that running, I could also
strip the patch down to explictly disable network mode for my special
case. I hoped to get a straight approach working for everyone, but when
we end up having more trouble fixing all the boards then, I would go the
other way.

Daniel

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2009-03-12 23:46 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-11 18:16 [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo Philipp Zabel
2009-03-11 18:16 ` [PATCH 2/3][RFC] ASoC: Add Magician machine support Philipp Zabel
2009-03-11 19:02   ` Liam Girdwood
2009-03-11 21:03     ` pHilipp Zabel
2009-03-11 22:25   ` Mark Brown
2009-03-11 22:38     ` Liam Girdwood
2009-03-11 22:44       ` Mark Brown
2009-03-12 10:07         ` [PATCH 3/5] ASoC: Replace remaining uses of snd_soc_cnew with snd_soc_add_controls Philipp Zabel
2009-03-12 10:11           ` Mark Brown
2009-03-12 10:06     ` [PATCH] ASoC: Add Magician machine support Philipp Zabel
2009-03-12 15:58       ` Mark Brown
2009-03-11 18:17 ` [PATCH 3/3][RFC] ASoC: pxa-ssp: Don't use SSCR0_SerClkDiv and SSCR0_SCR Philipp Zabel
2009-03-11 18:44   ` Daniel Mack
2009-03-11 21:10     ` pHilipp Zabel
2009-03-12  0:46       ` Daniel Mack
2009-03-12 10:23         ` Mark Brown
2009-03-12 10:27           ` Daniel Mack
2009-03-12 10:29             ` Mark Brown
2009-03-12 10:36             ` Daniel Mack
2009-03-12 19:09             ` pHilipp Zabel
2009-03-12 19:18               ` Mark Brown
2009-03-12 23:46                 ` Daniel Mack
2009-03-11 22:27   ` Mark Brown
2009-03-11 22:29     ` Mark Brown
2009-03-12 15:57 ` [PATCH 1/3][RFC] ASoC: pxa-ssp: Use 16-bit DMA for magician stereo Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.