* [PATCH v5 1/3] ARM: at91: atmel-ssc: add pinctrl support
2012-11-12 7:40 [PATCH v5 0/3] Add pinctrl support and enable audio Bo Shen
@ 2012-11-12 7:40 ` Bo Shen
2012-11-13 8:50 ` Mark Brown
2012-11-12 7:40 ` [PATCH v5 2/3] ASoC: atmel-ssc-dai: register dai and pcm directly Bo Shen
2012-11-12 7:40 ` [PATCH 3/3] ASoC: at91sam9g20ek-wm8731: convert to dt support Bo Shen
2 siblings, 1 reply; 12+ messages in thread
From: Bo Shen @ 2012-11-12 7:40 UTC (permalink / raw)
To: broonie, plagnioj, nicolas.ferre
Cc: Bo Shen, devicetree-discuss, alsa-devel, linux-sound,
linux-arm-kernel
Add pinctrl support for atmel ssc peripheral
Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
Change since v4
- This is initial version
---
arch/arm/boot/dts/at91sam9260.dtsi | 18 ++++++++++++++++++
arch/arm/boot/dts/at91sam9263.dtsi | 36 ++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/at91sam9g45.dtsi | 36 ++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/at91sam9n12.dtsi | 26 ++++++++++++++++++++++++++
arch/arm/boot/dts/at91sam9x5.dtsi | 32 +++++++++++++++++++++++++-------
drivers/misc/atmel-ssc.c | 8 ++++++++
6 files changed, 149 insertions(+), 7 deletions(-)
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index 3164dcd..8e3fe92 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -217,6 +217,22 @@
};
};
+ ssc0 {
+ pinctrl_ssc0_tx: ssc0_tx-0 {
+ atmel,pins =
+ <1 16 0x1 0x1 /* PB16 periph A with pull up */
+ 1 17 0x1 0x1 /* PB17 periph A with pull up */
+ 1 18 0x1 0x1>; /* PB18 periph A with pull up */
+ };
+
+ pinctrl_ssc0_rx: ssc0_rx-0 {
+ atmel,pins =
+ <1 19 0x1 0x1 /* PB19 periph A with pull up */
+ 1 20 0x1 0x1 /* PB20 periph A with pull up */
+ 1 21 0x1 0x1>; /* PB21 periph A with pull up */
+ };
+ };
+
pioA: gpio@fffff400 {
compatible = "atmel,at91rm9200-gpio";
reg = <0xfffff400 0x200>;
@@ -350,6 +366,8 @@
compatible = "atmel,at91rm9200-ssc";
reg = <0xfffbc000 0x4000>;
interrupts = <14 4 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
status = "disable";
};
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index 96e0bc9..80e0811 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -165,6 +165,38 @@
};
};
+ ssc0 {
+ pinctrl_ssc0_tx: ssc0_tx-0 {
+ atmel,pins =
+ <1 0 0x2 0x1 /* PB0 periph B with pull up */
+ 1 1 0x2 0x1 /* PB1 periph B with pull up */
+ 1 2 0x2 0x1>; /* PB2 periph B with pull up */
+ };
+
+ pinctrl_ssc0_rx: ssc0_rx-0 {
+ atmel,pins =
+ <1 3 0x2 0x1 /* PB3 periph B with pull up */
+ 1 4 0x2 0x1 /* PB4 periph B with pull up */
+ 1 5 0x2 0x1>; /* PB5 periph B with pull up */
+ };
+ };
+
+ ssc1 {
+ pinctrl_ssc1_tx: ssc1_tx-0 {
+ atmel,pins =
+ <1 6 0x1 0x1 /* PB6 periph A with pull up */
+ 1 7 0x1 0x1 /* PB7 periph A with pull up */
+ 1 8 0x1 0x1>; /* PB8 periph A with pull up */
+ };
+
+ pinctrl_ssc1_rx: ssc1_rx-0 {
+ atmel,pins =
+ <1 9 0x1 0x1 /* PB9 periph A with pull up */
+ 1 10 0x1 0x1 /* PB10 periph A with pull up */
+ 1 11 0x1 0x1>; /* PB11 periph A with pull up */
+ };
+ };
+
pioA: gpio@fffff200 {
compatible = "atmel,at91rm9200-gpio";
reg = <0xfffff200 0x200>;
@@ -262,6 +294,8 @@
compatible = "atmel,at91rm9200-ssc";
reg = <0xfff98000 0x4000>;
interrupts = <16 4 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
status = "disable";
};
@@ -269,6 +303,8 @@
compatible = "atmel,at91rm9200-ssc";
reg = <0xfff9c000 0x4000>;
interrupts = <17 4 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
status = "disable";
};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index c40c3eb..b969247 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -198,6 +198,38 @@
};
};
+ ssc0 {
+ pinctrl_ssc0_tx: ssc0_tx-0 {
+ atmel,pins =
+ <3 0 0x1 0x1 /* PD0 periph A with pull up */
+ 3 1 0x1 0x1 /* PD1 periph A with pull up */
+ 3 2 0x1 0x1>; /* PD2 periph A with pull up */
+ };
+
+ pinctrl_ssc0_rx: ssc0_rx-0 {
+ atmel,pins =
+ <3 3 0x1 0x1 /* PD3 periph A with pull up */
+ 3 4 0x1 0x1 /* PD4 periph A with pull up */
+ 3 5 0x1 0x1>; /* PD5 periph A with pull up */
+ };
+ };
+
+ ssc1 {
+ pinctrl_ssc1_tx: ssc1_tx-0 {
+ atmel,pins =
+ <3 10 0x1 0x1 /* PD10 periph A with pull up */
+ 3 11 0x1 0x1 /* PD11 periph A with pull up */
+ 3 12 0x1 0x1>; /* PD12 periph A with pull up */
+ };
+
+ pinctrl_ssc1_rx: ssc1_rx-0 {
+ atmel,pins =
+ <3 13 0x1 0x1 /* PD13 periph A with pull up */
+ 3 14 0x1 0x1 /* PD14 periph A with pull up */
+ 3 15 0x1 0x1>; /* PD15 periph A with pull up */
+ };
+ };
+
pioA: gpio@fffff200 {
compatible = "atmel,at91rm9200-gpio";
reg = <0xfffff200 0x200>;
@@ -331,6 +363,8 @@
compatible = "atmel,at91sam9g45-ssc";
reg = <0xfff9c000 0x4000>;
interrupts = <16 4 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
status = "disable";
};
@@ -338,6 +372,8 @@
compatible = "atmel,at91sam9g45-ssc";
reg = <0xfffa0000 0x4000>;
interrupts = <17 4 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
status = "disable";
};
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index 7b644c5..f39ffa3 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -28,6 +28,7 @@
tcb1 = &tcb1;
i2c0 = &i2c0;
i2c1 = &i2c1;
+ ssc0 = &ssc0;
};
cpus {
cpu@0 {
@@ -199,6 +200,22 @@
};
};
+ ssc0 {
+ pinctrl_ssc0_tx: ssc0_tx-0 {
+ atmel,pins =
+ <0 24 0x1 0x1 /* PA24 periph A with pull up */
+ 0 25 0x1 0x1 /* PA25 periph A with pull up */
+ 0 26 0x1 0x1>; /* PA26 periph A with pull up */
+ };
+
+ pinctrl_ssc0_rx: ssc0_rx-0 {
+ atmel,pins =
+ <0 27 0x1 0x1 /* PA27 periph A with pull up */
+ 0 28 0x1 0x1 /* PA28 periph A with pull up */
+ 0 29 0x1 0x1>; /* PA29 periph A with pull up */
+ };
+ };
+
pioA: gpio@fffff400 {
compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffff400 0x200>;
@@ -249,6 +266,15 @@
status = "disabled";
};
+ ssc0: ssc@f0010000 {
+ compatible = "atmel,at91sam9g45-ssc";
+ reg = <0xf0010000 0x4000>;
+ interrupts = <28 4 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+ status = "disable";
+ };
+
usart0: serial@f801c000 {
compatible = "atmel,at91sam9260-usart";
reg = <0xf801c000 0x4000>;
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 1cb26c28..b60e15e 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -88,13 +88,6 @@
interrupts = <1 4 7>;
};
- ssc0: ssc@f0010000 {
- compatible = "atmel,at91sam9g45-ssc";
- reg = <0xf0010000 0x4000>;
- interrupts = <28 4 5>;
- status = "disable";
- };
-
tcb0: timer@f8008000 {
compatible = "atmel,at91sam9x5-tcb";
reg = <0xf8008000 0x100>;
@@ -214,6 +207,22 @@
};
};
+ ssc0 {
+ pinctrl_ssc0_tx: ssc0_tx-0 {
+ atmel,pins =
+ <0 24 0x1 0x1 /* PA24 periph A with pull up */
+ 0 25 0x1 0x1 /* PA25 periph A with pull up */
+ 0 26 0x1 0x1>; /* PA26 periph A with pull up */
+ };
+
+ pinctrl_ssc0_rx: ssc0_rx-0 {
+ atmel,pins =
+ <0 27 0x1 0x1 /* PA27 periph A with pull up */
+ 0 28 0x1 0x1 /* PA28 periph A with pull up */
+ 0 29 0x1 0x1>; /* PA29 periph A with pull up */
+ };
+ };
+
pioA: gpio@fffff400 {
compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
reg = <0xfffff400 0x200>;
@@ -266,6 +275,15 @@
status = "disabled";
};
+ ssc0: ssc@f0010000 {
+ compatible = "atmel,at91sam9g45-ssc";
+ reg = <0xf0010000 0x4000>;
+ interrupts = <28 4 5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+ status = "disable";
+ };
+
usart0: serial@f801c000 {
compatible = "atmel,at91sam9260-usart";
reg = <0xf801c000 0x200>;
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index a769719..3b3d0e0 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
/* Serialize access to ssc_list and user count */
static DEFINE_SPINLOCK(user_lock);
@@ -131,6 +132,13 @@ static int ssc_probe(struct platform_device *pdev)
struct resource *regs;
struct ssc_device *ssc;
const struct atmel_ssc_platform_data *plat_dat;
+ struct pinctrl *pinctrl;
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(&pdev->dev, "Failed to request pinctrl\n");
+ return PTR_ERR(pinctrl);
+ }
ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
if (!ssc) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v5 2/3] ASoC: atmel-ssc-dai: register dai and pcm directly
2012-11-12 7:40 [PATCH v5 0/3] Add pinctrl support and enable audio Bo Shen
2012-11-12 7:40 ` [PATCH v5 1/3] ARM: at91: atmel-ssc: add pinctrl support Bo Shen
@ 2012-11-12 7:40 ` Bo Shen
2012-11-13 8:30 ` Mark Brown
2012-11-12 7:40 ` [PATCH 3/3] ASoC: at91sam9g20ek-wm8731: convert to dt support Bo Shen
2 siblings, 1 reply; 12+ messages in thread
From: Bo Shen @ 2012-11-12 7:40 UTC (permalink / raw)
To: broonie, plagnioj, nicolas.ferre
Cc: linux-arm-kernel, devicetree-discuss, linux-sound, alsa-devel,
Bo Shen
change the method for register dai and pcm
- let the atmel-ssc-dai no longer as a standalone platform device
- remap ssc and then register dai directly
- register pcm from dai directly
Modify the code which related with this change
Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
Change since v4 RFC
- no change
Change since v3 RFC
- remap ssc and then register dai and pcm directly
Change since v2
- Register dai and pcm directly according to Mark Brown's suggestion
- using name to distinguish ssc register for audio or library
if for audio, the name with dai subfix
if for library, the name without dai subfix
- fix the issue for sam9g20-wm8731
- when register dai and pcm cause the sam9g20-wm8731 doesn't work,
so fix it
- Add device tree support
- Detail information reference atmel-ssc-dai.txt binding document
Change since v1
No change
---
arch/arm/mach-at91/at91sam9260_devices.c | 9 --
arch/arm/mach-at91/board-sam9g20ek.c | 8 +-
sound/soc/atmel/atmel-pcm.c | 23 +--
sound/soc/atmel/atmel-pcm.h | 3 +
sound/soc/atmel/atmel_ssc_dai.c | 228 +++++++-----------------------
sound/soc/atmel/atmel_ssc_dai.h | 1 +
sound/soc/atmel/sam9g20_wm8731.c | 13 +-
7 files changed, 76 insertions(+), 209 deletions(-)
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index df7bebf..6959fd2 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -768,14 +768,6 @@ static inline void configure_ssc_pins(unsigned pins)
at91_set_A_periph(AT91_PIN_PB21, 1);
}
-static struct platform_device at91sam9260_ssc_dai_device = {
- .name = "atmel-ssc-dai",
- .id = 0,
- .dev = {
- .parent = &(at91sam9260_ssc_device.dev),
- },
-};
-
/*
* SSC controllers are accessed through library code, instead of any
* kind of all-singing/all-dancing driver. For example one could be
@@ -800,7 +792,6 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins)
}
platform_device_register(pdev);
- platform_device_register(&at91sam9260_ssc_dai_device);
}
#else
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 5b6a6f9..f3faf54 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -353,19 +353,13 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
},
};
-static struct platform_device sam9g20ek_pcm_device = {
- .name = "atmel-pcm-audio",
- .id = -1,
-};
-
static struct platform_device sam9g20ek_audio_device = {
.name = "at91sam9g20ek-audio",
- .id = -1,
+ .id = 0,
};
static void __init ek_add_device_audio(void)
{
- platform_device_register(&sam9g20ek_pcm_device);
platform_device_register(&sam9g20ek_audio_device);
}
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index 9b84f98..40e17d1 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -473,28 +473,17 @@ static struct snd_soc_platform_driver atmel_soc_platform = {
.resume = atmel_pcm_resume,
};
-static int __devinit atmel_soc_platform_probe(struct platform_device *pdev)
+int atmel_pcm_platform_register(struct device *dev)
{
- return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform);
+ return snd_soc_register_platform(dev, &atmel_soc_platform);
}
+EXPORT_SYMBOL(atmel_pcm_platform_register);
-static int __devexit atmel_soc_platform_remove(struct platform_device *pdev)
+void atmel_pcm_platform_unregister(struct device *dev)
{
- snd_soc_unregister_platform(&pdev->dev);
- return 0;
+ snd_soc_unregister_platform(dev);
}
-
-static struct platform_driver atmel_pcm_driver = {
- .driver = {
- .name = "atmel-pcm-audio",
- .owner = THIS_MODULE,
- },
-
- .probe = atmel_soc_platform_probe,
- .remove = __devexit_p(atmel_soc_platform_remove),
-};
-
-module_platform_driver(atmel_pcm_driver);
+EXPORT_SYMBOL(atmel_pcm_platform_unregister);
MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
MODULE_DESCRIPTION("Atmel PCM module");
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h
index 5e0a95e..e6d67b3 100644
--- a/sound/soc/atmel/atmel-pcm.h
+++ b/sound/soc/atmel/atmel-pcm.h
@@ -80,4 +80,7 @@ struct atmel_pcm_dma_params {
#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
+int atmel_pcm_platform_register(struct device *dev);
+void atmel_pcm_platform_unregister(struct device *dev);
+
#endif /* _ATMEL_PCM_H */
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index 354341e..4435e19 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -47,13 +47,6 @@
#include "atmel-pcm.h"
#include "atmel_ssc_dai.h"
-
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
-#define NUM_SSC_DEVICES 1
-#else
-#define NUM_SSC_DEVICES 3
-#endif
-
/*
* SSC PDC registers required by the PCM DMA engine.
*/
@@ -96,63 +89,24 @@ static struct atmel_ssc_mask ssc_rx_mask = {
/*
* DMA parameters.
*/
-static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
- {{
- .name = "SSC0 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
+static struct atmel_pcm_dma_params ssc_dma_params[2] = {
{
- .name = "SSC0 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- } },
-#if NUM_SSC_DEVICES == 3
- {{
- .name = "SSC1 PCM out",
+ .name = "SSC PCM out",
.pdc = &pdc_tx_reg,
.mask = &ssc_tx_mask,
},
{
- .name = "SSC1 PCM in",
+ .name = "SSC PCM in",
.pdc = &pdc_rx_reg,
.mask = &ssc_rx_mask,
- } },
- {{
- .name = "SSC2 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
},
- {
- .name = "SSC2 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- } },
-#endif
};
-
-static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
- {
- .name = "ssc0",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
-#if NUM_SSC_DEVICES == 3
- {
- .name = "ssc1",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
+static struct atmel_ssc_info ssc_info = {
+ .name = "ssc",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info.lock),
.dir_mask = SSC_DIR_MASK_UNUSED,
.initialized = 0,
- },
- {
- .name = "ssc2",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
-#endif
};
@@ -205,7 +159,7 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
static int atmel_ssc_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+ struct atmel_ssc_info *ssc_p = &ssc_info;
int dir_mask;
pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
@@ -234,7 +188,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+ struct atmel_ssc_info *ssc_p = &ssc_info;
struct atmel_pcm_dma_params *dma_params;
int dir, dir_mask;
@@ -285,7 +239,7 @@ static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
- struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+ struct atmel_ssc_info *ssc_p = &ssc_info;
ssc_p->daifmt = fmt;
return 0;
@@ -297,7 +251,7 @@ static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
int div_id, int div)
{
- struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+ struct atmel_ssc_info *ssc_p = &ssc_info;
switch (div_id) {
case ATMEL_SSC_CMR_DIV:
@@ -336,8 +290,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
- int id = dai->id;
- struct atmel_ssc_info *ssc_p = &ssc_info[id];
+ struct atmel_ssc_info *ssc_p = &ssc_info;
struct atmel_pcm_dma_params *dma_params;
int dir, channels, bits;
u32 tfmr, rfmr, tcmr, rcmr;
@@ -354,7 +307,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
else
dir = 1;
- dma_params = &ssc_dma_params[id][dir];
+ dma_params = &ssc_dma_params[dir];
dma_params->ssc = ssc_p->ssc;
dma_params->substream = substream;
@@ -603,7 +556,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+ struct atmel_ssc_info *ssc_p = &ssc_info;
struct atmel_pcm_dma_params *dma_params;
int dir;
@@ -631,7 +584,7 @@ static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
if (!cpu_dai->active)
return 0;
- ssc_p = &ssc_info[cpu_dai->id];
+ ssc_p = &ssc_info;
/* Save the status register before disabling transmit and receive */
ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
@@ -660,7 +613,7 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
if (!cpu_dai->active)
return 0;
- ssc_p = &ssc_info[cpu_dai->id];
+ ssc_p = &ssc_info;
/* restore SSC register settings */
ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
@@ -689,28 +642,10 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
static int atmel_ssc_probe(struct snd_soc_dai *dai)
{
- struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
- int ret = 0;
+ struct atmel_ssc_info *ssc_p = &ssc_info;
snd_soc_dai_set_drvdata(dai, ssc_p);
- /*
- * Request SSC device
- */
- ssc_p->ssc = ssc_request(dai->id);
- if (IS_ERR(ssc_p->ssc)) {
- printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id);
- ret = PTR_ERR(ssc_p->ssc);
- }
-
- return ret;
-}
-
-static int atmel_ssc_remove(struct snd_soc_dai *dai)
-{
- struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai);
-
- ssc_free(ssc_p->ssc);
return 0;
}
@@ -728,11 +663,8 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
.set_clkdiv = atmel_ssc_set_dai_clkdiv,
};
-static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
- {
- .name = "atmel-ssc-dai.0",
+static struct snd_soc_dai_driver atmel_ssc_dai = {
.probe = atmel_ssc_probe,
- .remove = atmel_ssc_remove,
.suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume,
.playback = {
@@ -746,69 +678,37 @@ static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
.rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops,
- },
-#if NUM_SSC_DEVICES == 3
- {
- .name = "atmel-ssc-dai.1",
- .probe = atmel_ssc_probe,
- .remove = atmel_ssc_remove,
- .suspend = atmel_ssc_suspend,
- .resume = atmel_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .ops = &atmel_ssc_dai_ops,
- },
- {
- .name = "atmel-ssc-dai.2",
- .probe = atmel_ssc_probe,
- .remove = atmel_ssc_remove,
- .suspend = atmel_ssc_suspend,
- .resume = atmel_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .ops = &atmel_ssc_dai_ops,
- },
-#endif
};
-static __devinit int asoc_ssc_probe(struct platform_device *pdev)
+static int asoc_ssc_init(struct device *dev)
{
- BUG_ON(pdev->id < 0);
- BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai));
- return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]);
-}
+ int ret;
+
+ ret = snd_soc_register_dai(dev, &atmel_ssc_dai);
+ if (ret) {
+ dev_err(dev, "Could not register DAI: %d\n", ret);
+ goto err;
+ }
+
+ ret = atmel_pcm_platform_register(dev);
+ if (ret) {
+ dev_err(dev, "Could not register PCM: %d\n", ret);
+ goto err_unregister_dai;
+ };
-static int __devexit asoc_ssc_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_dai(&pdev->dev);
return 0;
-}
-static struct platform_driver asoc_ssc_driver = {
- .driver = {
- .name = "atmel-ssc-dai",
- .owner = THIS_MODULE,
- },
+err_unregister_dai:
+ snd_soc_unregister_dai(dev);
+err:
+ return ret;
+}
- .probe = asoc_ssc_probe,
- .remove = __devexit_p(asoc_ssc_remove),
-};
+static void asoc_ssc_exit(struct device *dev)
+{
+ atmel_pcm_platform_unregister(dev);
+ snd_soc_unregister_dai(dev);
+}
/**
* atmel_ssc_set_audio - Allocate the specified SSC for audio use.
@@ -816,50 +716,32 @@ static struct platform_driver asoc_ssc_driver = {
int atmel_ssc_set_audio(int ssc_id)
{
struct ssc_device *ssc;
- static struct platform_device *dma_pdev;
- struct platform_device *ssc_pdev;
int ret;
- if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai))
- return -EINVAL;
-
- /* Allocate a dummy device for DMA if we don't have one already */
- if (!dma_pdev) {
- dma_pdev = platform_device_alloc("atmel-pcm-audio", -1);
- if (!dma_pdev)
- return -ENOMEM;
-
- ret = platform_device_add(dma_pdev);
- if (ret < 0) {
- platform_device_put(dma_pdev);
- dma_pdev = NULL;
- return ret;
- }
- }
-
- ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id);
- if (!ssc_pdev)
- return -ENOMEM;
-
/* If we can grab the SSC briefly to parent the DAI device off it */
ssc = ssc_request(ssc_id);
- if (IS_ERR(ssc))
- pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n",
+ if (IS_ERR(ssc)) {
+ pr_err("Unable to parent ASoC SSC DAI on SSC: %ld\n",
PTR_ERR(ssc));
- else {
- ssc_pdev->dev.parent = &(ssc->pdev->dev);
- ssc_free(ssc);
+ return PTR_ERR(ssc);
+ } else {
+ ssc_info.ssc = ssc;
}
- ret = platform_device_add(ssc_pdev);
- if (ret < 0)
- platform_device_put(ssc_pdev);
+ ret = asoc_ssc_init(&ssc->pdev->dev);
return ret;
}
EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
-module_platform_driver(asoc_ssc_driver);
+void atmel_ssc_put_audio(void)
+{
+ struct ssc_device *ssc = ssc_info.ssc;
+
+ ssc_free(ssc);
+ asoc_ssc_exit(&ssc->pdev->dev);
+}
+EXPORT_SYMBOL_GPL(atmel_ssc_put_audio);
/* Module information */
MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
index 5d4f0f9..70c66dd 100644
--- a/sound/soc/atmel/atmel_ssc_dai.h
+++ b/sound/soc/atmel/atmel_ssc_dai.h
@@ -118,5 +118,6 @@ struct atmel_ssc_info {
};
int atmel_ssc_set_audio(int ssc);
+void atmel_ssc_put_audio(void);
#endif /* _AT91_SSC_DAI_H */
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 228ca6a..eef6eed 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -179,10 +179,10 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link at91sam9g20ek_dai = {
.name = "WM8731",
.stream_name = "WM8731 PCM",
- .cpu_dai_name = "atmel-ssc-dai.0",
+ .cpu_dai_name = "at91rm9200_ssc.0",
.codec_dai_name = "wm8731-hifi",
.init = at91sam9g20ek_wm8731_init,
- .platform_name = "atmel-pcm-audio",
+ .platform_name = "at91rm9200_ssc.0",
.codec_name = "wm8731.0-001b",
.ops = &at91sam9g20ek_ops,
};
@@ -204,6 +204,10 @@ static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
return -ENODEV;
+ ret = atmel_ssc_set_audio(pdev->id);
+ if (ret)
+ goto err;
+
/*
* Codec MCLK is supplied by PCK0 - set it up.
*/
@@ -211,7 +215,7 @@ static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
if (IS_ERR(mclk)) {
printk(KERN_ERR "ASoC: Failed to get MCLK\n");
ret = PTR_ERR(mclk);
- goto err;
+ goto err_ssc_put_audio;
}
pllb = clk_get(NULL, "pllb");
@@ -240,6 +244,8 @@ static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
err_mclk:
clk_put(mclk);
mclk = NULL;
+err_ssc_put_audio:
+ atmel_ssc_put_audio();
err:
return ret;
}
@@ -248,6 +254,7 @@ static int __devexit at91sam9g20ek_audio_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
+ atmel_ssc_put_audio();
snd_soc_unregister_card(card);
clk_put(mclk);
mclk = NULL;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/3] ASoC: at91sam9g20ek-wm8731: convert to dt support
2012-11-12 7:40 [PATCH v5 0/3] Add pinctrl support and enable audio Bo Shen
2012-11-12 7:40 ` [PATCH v5 1/3] ARM: at91: atmel-ssc: add pinctrl support Bo Shen
2012-11-12 7:40 ` [PATCH v5 2/3] ASoC: atmel-ssc-dai: register dai and pcm directly Bo Shen
@ 2012-11-12 7:40 ` Bo Shen
2 siblings, 0 replies; 12+ messages in thread
From: Bo Shen @ 2012-11-12 7:40 UTC (permalink / raw)
To: broonie, plagnioj, nicolas.ferre
Cc: linux-arm-kernel, devicetree-discuss, linux-sound, alsa-devel,
Bo Shen
convert at91sam9g20ek wm8731 to device tree support
Signed-off-by: Bo Shen <voice.shen@atmel.com>
---
Change since v4 RFC:
Using the full name of the EK which make it more clear
Change since v3 RFC:
Remove dai node, remap ssc in place
without pinctrl added, so don't modify the dtsi file, will be added
soon
Change since v2:
No change
Change since v1:
Add sam9g20-wm8731 binding document
---
.../sound/atmel-at91sam9g20ek-wm8731-audio.txt | 26 +++++++
arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 34 ++++++++-
sound/soc/atmel/Kconfig | 3 +-
sound/soc/atmel/sam9g20_wm8731.c | 78 +++++++++++++++++++-
4 files changed, 133 insertions(+), 8 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
diff --git a/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
new file mode 100644
index 0000000..9c5a994
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
@@ -0,0 +1,26 @@
+* Atmel at91sam9g20ek wm8731 audio complex
+
+Required properties:
+ - compatible: "atmel,at91sam9g20ek-wm8731-audio"
+ - atmel,model: The user-visible name of this sound complex.
+ - atmel,audio-routing: A list of the connections between audio components.
+ - atmel,ssc-controller: The phandle of the SSC controller
+ - atmel,audio-codec: The phandle of the WM8731 audio codec
+Optional properties:
+ - pinctrl-names, pinctrl-0: Please refer to pinctrl-bindings.txt
+
+Example:
+sound {
+ compatible = "atmel,at91sam9g20ek-wm8731-audio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+ atmel,model = "wm8731 @ AT91SAMG20EK";
+
+ atmel,audio-routing =
+ "Ext Spk", "LHPOUT",
+ "Int MIC", "MICIN";
+
+ atmel,ssc-controller = <&ssc0>;
+ atmel,audio-codec = <&wm8731>;
+};
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index 689323d..4c37546 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -30,6 +30,16 @@
ahb {
apb {
+ pinctrl@fffff400 {
+ board {
+ pinctrl_pck0_as_mck: pck0_as_mck {
+ atmel,pins =
+ <2 1 0x2 0x0>; /* PC1 periph B */
+ };
+
+ };
+ };
+
dbgu: serial@fffff200 {
status = "okay";
};
@@ -57,6 +67,11 @@
atmel,vbus-gpio = <&pioC 5 0>;
status = "okay";
};
+
+ ssc0: ssc@fffbc000 {
+ status = "okay";
+ pinctrl-0 = <&pinctrl_ssc0_tx>;
+ };
};
nand0: nand@40000000 {
@@ -120,8 +135,8 @@
reg = <0x50>;
};
- wm8731@1b {
- compatible = "wm8731";
+ wm8731: wm8731@1b {
+ compatible = "wlf,wm8731";
reg = <0x1b>;
};
};
@@ -145,4 +160,19 @@
gpio-key,wakeup;
};
};
+
+ sound {
+ compatible = "atmel,at91sam9g20ek-wm8731-audio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pck0_as_mck>;
+
+ atmel,model = "wm8731 @ AT91SAMG20EK";
+
+ atmel,audio-routing =
+ "Ext Spk", "LHPOUT",
+ "Int Mic", "MICIN";
+
+ atmel,ssc-controller = <&ssc0>;
+ atmel,audio-codec = <&wm8731>;
+ };
};
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 72b09cf..397ec75 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -16,8 +16,7 @@ config SND_ATMEL_SOC_SSC
config SND_AT91_SOC_SAM9G20_WM8731
tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
- depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \
- AT91_PROGRAMMABLE_CLOCKS
+ depends on ATMEL_SSC && SND_ATMEL_SOC && AT91_PROGRAMMABLE_CLOCKS
select SND_ATMEL_SOC_SSC
select SND_SOC_WM8731
help
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index eef6eed..6bb9446 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -38,6 +38,8 @@
#include <linux/platform_device.h>
#include <linux/i2c.h>
+#include <linux/pinctrl/consumer.h>
+
#include <linux/atmel-ssc.h>
#include <sound/core.h>
@@ -197,14 +199,37 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *codec_np, *cpu_np;
struct clk *pllb;
struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
- int ret;
+ struct pinctrl *pinctrl;
+ int ret, id;
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl)) {
+ dev_err(&pdev->dev, "Failed to request pinctrl\n");
+ return PTR_ERR(pinctrl);
+ }
- if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
- return -ENODEV;
+ if (np) {
+ cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "codec info missing\n");
+ return -EINVAL;
+ }
+
+ id = of_alias_get_id(cpu_np, "ssc");
+ of_node_put(cpu_np);
+ } else {
+ if (!(machine_is_at91sam9g20ek() ||
+ machine_is_at91sam9g20ek_2mmc()))
+ return -ENODEV;
+
+ id = pdev->id;
+ }
- ret = atmel_ssc_set_audio(pdev->id);
+ ret = atmel_ssc_set_audio(id);
if (ret)
goto err;
@@ -234,6 +259,42 @@ static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
clk_set_rate(mclk, MCLK_RATE);
card->dev = &pdev->dev;
+
+ /* Parse device node info */
+ if (np) {
+ ret = snd_soc_of_parse_card_name(card, "atmel,model");
+ if (ret)
+ goto err;
+
+ ret = snd_soc_of_parse_audio_routing(card,
+ "atmel,audio-routing");
+ if (ret)
+ goto err;
+
+ /* Parse codec info */
+ at91sam9g20ek_dai.codec_name = NULL;
+ codec_np = of_parse_phandle(np, "atmel,audio-codec", 0);
+ if (!codec_np) {
+ dev_err(&pdev->dev, "codec info missing\n");
+ return -EINVAL;
+ }
+ at91sam9g20ek_dai.codec_of_node = codec_np;
+
+ /* Parse dai and platform info */
+ at91sam9g20ek_dai.cpu_dai_name = NULL;
+ at91sam9g20ek_dai.platform_name = NULL;
+ cpu_np = of_parse_phandle(np, "atmel,ssc-controller", 0);
+ if (!cpu_np) {
+ dev_err(&pdev->dev, "dai and pcm info missing\n");
+ return -EINVAL;
+ }
+ at91sam9g20ek_dai.cpu_of_node = cpu_np;
+ at91sam9g20ek_dai.platform_of_node = cpu_np;
+
+ of_node_put(codec_np);
+ of_node_put(cpu_np);
+ }
+
ret = snd_soc_register_card(card);
if (ret) {
printk(KERN_ERR "ASoC: snd_soc_register_card() failed\n");
@@ -262,10 +323,19 @@ static int __devexit at91sam9g20ek_audio_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id at91sam9g20ek_wm8731_dt_ids[] = {
+ { .compatible = "atmel,at91sam9g20ek-wm8731-audio", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, at91sam9g20ek_wm8731_dt_ids);
+#endif
+
static struct platform_driver at91sam9g20ek_audio_driver = {
.driver = {
.name = "at91sam9g20ek-audio",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(at91sam9g20ek_wm8731_dt_ids),
},
.probe = at91sam9g20ek_audio_probe,
.remove = __devexit_p(at91sam9g20ek_audio_remove),
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread