[alsa-devel] [PATCH v5 0/3] Add pinctrl support and enable audio
This patch set is based on linux next master branch The detail information as following: Git: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git Branch: master Commit ID: 75e0ebabd87048b91e4189b90d4af8ef565115db
Detail information about implement as following: - atmel ssc: add pinctrl support - atmel ssc dai: register dai and pcm directly - at91sam9g20ek wm8731: convert to dt support
Bo Shen (3): ARM: at91: atmel-ssc: add pinctrl support ASoC: atmel-ssc-dai: register dai and pcm directly ASoC: at91sam9g20ek-wm8731: convert to dt support
.../sound/atmel-at91sam9g20ek-wm8731-audio.txt | 26 +++ arch/arm/boot/dts/at91sam9260.dtsi | 18 ++ arch/arm/boot/dts/at91sam9263.dtsi | 36 ++++ arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 34 ++- arch/arm/boot/dts/at91sam9g45.dtsi | 36 ++++ arch/arm/boot/dts/at91sam9n12.dtsi | 26 +++ arch/arm/boot/dts/at91sam9x5.dtsi | 32 ++- arch/arm/mach-at91/at91sam9260_devices.c | 9 - arch/arm/mach-at91/board-sam9g20ek.c | 8 +- drivers/misc/atmel-ssc.c | 8 + sound/soc/atmel/Kconfig | 3 +- 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 | 89 +++++++- 16 files changed, 357 insertions(+), 223 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt
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) {
On Mon, Nov 12, 2012 at 03:40:25PM +0800, Bo Shen wrote:
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 */
};
Do we really want the pull ups here? Normally CMOS devices don't have pulls, or the pulls are disabled during normal operation, as otherwise when the logic level is different to whatever the pull is doing power is wasted driving against the resistor.
Hi Mark,
On 11/13/2012 16:50, Mark Brown wrote:
On Mon, Nov 12, 2012 at 03:40:25PM +0800, Bo Shen wrote:
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 */
};
Do we really want the pull ups here? Normally CMOS devices don't have pulls, or the pulls are disabled during normal operation, as otherwise when the logic level is different to whatever the pull is doing power is wasted driving against the resistor.
After checking with internal, it does not need pull up. I will correct this in next version.
Thanks.
Best Regards, 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;
On Mon, Nov 12, 2012 at 03:40:26PM +0800, Bo Shen wrote:
static struct platform_device sam9g20ek_audio_device = { .name = "at91sam9g20ek-audio",
- .id = -1,
- .id = 0,
};
Why are you changing this? Single devices are supposed to specify -1 as their 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;
This seems like a very big step backwards, there's now a single global variable for the ssc_info which presumably means there can be only one SSC active in the system at once. That's changing a lot more than just the registration...
Hi Mark,
On 11/13/2012 16:30, Mark Brown wrote:
On Mon, Nov 12, 2012 at 03:40:26PM +0800, Bo Shen wrote:
static struct platform_device sam9g20ek_audio_device = { .name = "at91sam9g20ek-audio",
- .id = -1,
- .id = 0, };
Why are you changing this? Single devices are supposed to specify -1 as their id.
This is for non-dt support, using the id to tell which ssc will be used to remap into audio subsystem. Maybe this is a mixed up usage, however I can not find good solution, any suggestions?
This is a similar implement as 7840487cd6298f9f931103b558290d8d98d41c49
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;
This seems like a very big step backwards, there's now a single global variable for the ssc_info which presumably means there can be only one SSC active in the system at once. That's changing a lot more than just the registration...
This change won't broke other subsystem using ssc, only broke the audio subsystem if there are two codecs co-exist in a system. I will fix this in next version.
Yes, this patch is a little more than registration, however when change the registration method, the related code will be affected, so also clean up them in this patch, do I need to split this patch?
Thanks.
Best Regards, Bo Shen
On Tue, Nov 13, 2012 at 05:10:26PM +0800, Bo Shen wrote:
On 11/13/2012 16:30, Mark Brown wrote:
Why are you changing this? Single devices are supposed to specify -1 as their id.
This is for non-dt support, using the id to tell which ssc will be used to remap into audio subsystem. Maybe this is a mixed up usage, however I can not find good solution, any suggestions?
The machine driver should know which SSC it is using all by itself, it's specific to a particular machine. This is how it's been doing it since it was written...
This is a similar implement as 7840487cd6298f9f931103b558290d8d98d41c49
Don't quote raw commit IDs, they're not legible by humans.
Yes, this patch is a little more than registration, however when change the registration method, the related code will be affected, so also clean up them in this patch, do I need to split this patch?
Yes, one change per patch. Having many unrelated changes in one patch makes it very difficult to review anything.
On 11/13/2012 17:20, Mark Brown wrote:
On Tue, Nov 13, 2012 at 05:10:26PM +0800, Bo Shen wrote:
On 11/13/2012 16:30, Mark Brown wrote:
Why are you changing this? Single devices are supposed to specify -1 as their id.
This is for non-dt support, using the id to tell which ssc will be used to remap into audio subsystem. Maybe this is a mixed up usage, however I can not find good solution, any suggestions?
The machine driver should know which SSC it is using all by itself, it's specific to a particular machine. This is how it's been doing it since it was written...
So, you mean, I should hard code this into machine driver, am I right?
This is a similar implement as 7840487cd6298f9f931103b558290d8d98d41c49
Don't quote raw commit IDs, they're not legible by humans.
Yes, this patch is a little more than registration, however when change the registration method, the related code will be affected, so also clean up them in this patch, do I need to split this patch?
Yes, one change per patch. Having many unrelated changes in one patch makes it very difficult to review anything.
OK, I will split this patch.
Best Regards, Bo Shen
On Tue, Nov 13, 2012 at 05:38:04PM +0800, Bo Shen wrote:
On 11/13/2012 17:20, Mark Brown wrote:
The machine driver should know which SSC it is using all by itself, it's specific to a particular machine. This is how it's been doing it since it was written...
So, you mean, I should hard code this into machine driver, am I right?
Yes, exactly.
On 11/13/2012 17:41, Mark Brown wrote:
On Tue, Nov 13, 2012 at 05:38:04PM +0800, Bo Shen wrote:
On 11/13/2012 17:20, Mark Brown wrote:
The machine driver should know which SSC it is using all by itself, it's specific to a particular machine. This is how it's been doing it since it was written...
So, you mean, I should hard code this into machine driver, am I right?
Yes, exactly.
Ok, I will hard code it. Thanks.
Best Regards, 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),
participants (2)
-
Bo Shen
-
Mark Brown