diff mbox

[14/15] ARM: pxa: change SSP devices allocation

Message ID 20180402142656.26815-15-robert.jarzmik@free.fr (mailing list archive)
State New, archived
Headers show

Commit Message

Robert Jarzmik April 2, 2018, 2:26 p.m. UTC
In order to prepare for the dma_slave_map change for SSP DMA channels
allocation, the SSP platform devices will now include a platform data
structure which in turn selects which dma channel has to be used for
data transfers, especially the PCM ones.

Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 arch/arm/mach-pxa/devices.c            | 78 +++++++++++++++++++++++++++++-----
 arch/arm/mach-pxa/devices.h            | 14 ++----
 arch/arm/mach-pxa/include/mach/audio.h | 12 ++++++
 arch/arm/mach-pxa/pxa25x.c             |  4 +-
 arch/arm/mach-pxa/pxa27x.c             |  4 +-
 arch/arm/mach-pxa/pxa3xx.c             |  5 +--
 6 files changed, 86 insertions(+), 31 deletions(-)

Comments

Arnd Bergmann April 3, 2018, 7:06 a.m. UTC | #1
On Mon, Apr 2, 2018 at 4:26 PM, Robert Jarzmik <robert.jarzmik@free.fr> wrote:

>
> +static struct pxa_ssp_info pxa_ssp_infos[] = {
> +       { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
> +       { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
> +       { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
> +       { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
> +       { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
> +       { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
> +       { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
> +       { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
> +};

This part looks odd to me, you're adding an extra level of indirection to
do two stages of lookups in some form of platform data.

Why can't you just always use "rx" and "tx" as the names here?

(also, I don't see why each line is duplicated, but I'm sure there's
an easy answer for that).

       Arnd
Robert Jarzmik April 3, 2018, 3:32 p.m. UTC | #2
Arnd Bergmann <arnd@arndb.de> writes:

chop chop ... removed several mail recipients to leave only the ASoC / PXA
subset ...

> On Mon, Apr 2, 2018 at 4:26 PM, Robert Jarzmik <robert.jarzmik@free.fr> wrote:
>
>>
>> +static struct pxa_ssp_info pxa_ssp_infos[] = {
>> +       { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>> +       { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>> +       { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>> +       { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>> +       { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>> +       { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>> +       { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>> +       { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>> +};
>
> This part looks odd to me, you're adding an extra level of indirection to
> do two stages of lookups in some form of platform data.
That's unfortunately right.

> Why can't you just always use "rx" and "tx" as the names here?
Well I couldn't. I'll explain you why, and maybe you'll find a better solution.

That all is related to how ASoC and SSP interact.
If I remember correctly, here is how it works :
 - the DMA channel is requested in sound/arm/pxa2xx-pcm-lib.c:128
	return snd_dmaengine_pcm_open(
		substream, dma_request_slave_channel(rtd->platform->dev,
   The trick is that the device here is _not_ the SSP one, it's if memory serves
   me well the pxa-pcm-audio one.

   As a consequence, the device cannot be used to differenciate which SSP
   exactly is providing the sound samples stream. This information is
   nevertheless required to choose the correct requestor line, which is a 1-to-1
   match to the SSP port.

   The indirection in the channel name is used to choose the correct requestor
   line for a given SSP port providing the samples.

   It also must be underlined that this dma request serves both AC97 and SSP as
   sample providers.

> (also, I don't see why each line is duplicated, but I'm sure there's
> an easy answer for that).
Ahh that is an unfortunate rebase most probably :)

Cheers.
Arnd Bergmann April 3, 2018, 3:53 p.m. UTC | #3
On Tue, Apr 3, 2018 at 5:32 PM, Robert Jarzmik <robert.jarzmik@free.fr> wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
>
> chop chop ... removed several mail recipients to leave only the ASoC / PXA
> subset ...
>
>> On Mon, Apr 2, 2018 at 4:26 PM, Robert Jarzmik <robert.jarzmik@free.fr> wrote:
>>
>>>
>>> +static struct pxa_ssp_info pxa_ssp_infos[] = {
>>> +       { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>>> +       { .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
>>> +       { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>>> +       { .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
>>> +       { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>>> +       { .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
>>> +       { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>>> +       { .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
>>> +};
>>
>> This part looks odd to me, you're adding an extra level of indirection to
>> do two stages of lookups in some form of platform data.
> That's unfortunately right.
>
>> Why can't you just always use "rx" and "tx" as the names here?
> Well I couldn't. I'll explain you why, and maybe you'll find a better solution.
>
> That all is related to how ASoC and SSP interact.
> If I remember correctly, here is how it works :
>  - the DMA channel is requested in sound/arm/pxa2xx-pcm-lib.c:128
>         return snd_dmaengine_pcm_open(
>                 substream, dma_request_slave_channel(rtd->platform->dev,
>    The trick is that the device here is _not_ the SSP one, it's if memory serves
>    me well the pxa-pcm-audio one.
>
>    As a consequence, the device cannot be used to differenciate which SSP
>    exactly is providing the sound samples stream. This information is
>    nevertheless required to choose the correct requestor line, which is a 1-to-1
>    match to the SSP port.
>
>    The indirection in the channel name is used to choose the correct requestor
>    line for a given SSP port providing the samples.
>
>    It also must be underlined that this dma request serves both AC97 and SSP as
>    sample providers.

I'm still unable to follow through that code, but I understand now that
the device you pass to dma_request_slave_channel() is not the one
we'd like it to be here.

Where exactly does that call to dma_request_chan() happen? Is this
the one in dmaengine_pcm_new()? Could we perhaps put a
pointer to the SSP device into snd_dmaengine_dai_dma_data?

       Arnd
Robert Jarzmik April 5, 2018, 6:51 a.m. UTC | #4
Arnd Bergmann <arnd@arndb.de> writes:

> I'm still unable to follow through that code, but I understand now that
> the device you pass to dma_request_slave_channel() is not the one
> we'd like it to be here.
>
> Where exactly does that call to dma_request_chan() happen? Is this
> the one in dmaengine_pcm_new()? Could we perhaps put a
> pointer to the SSP device into snd_dmaengine_dai_dma_data?
This is a sample stack I captured with an added WARN_ON(1), triggered by a
userland "aplay Sultans_Of_Swing.wav" :)

[  299.216743] [<c0012e80>] (unwind_backtrace) from [<c000f55c>] (show_stack+0x20/0x24)
[  299.223986] [<c000f55c>] (show_stack) from [<c0529d68>] (dump_stack+0x20/0x28)
[  299.231321] [<c0529d68>] (dump_stack) from [<c001de34>] (__warn+0xf0/0x11c)
[  299.238183] [<c001de34>] (__warn) from [<c001df94>] (warn_slowpath_null+0x4c/0x58)
[  299.245234] [<c001df94>] (warn_slowpath_null) from [<c02a2d38>] (dma_request_chan+0x40/0x228)
[  299.252550] [<c02a2d38>] (dma_request_chan) from [<c02a2f38>] (dma_request_slave_channel+0x18/0x24)
[  299.259855] [<c02a2f38>] (dma_request_slave_channel) from [<c03f76f0>] (__pxa2xx_pcm_open+0xf4/0x110)
[  299.266789] [<c03f76f0>] (__pxa2xx_pcm_open) from [<c0409ed0>] (soc_pcm_open+0xf8/0x9c8)
[  299.273932] [<c0409ed0>] (soc_pcm_open) from [<c03db9d4>] (snd_pcm_open_substream+0x9c/0x134)
[  299.281290] [<c03db9d4>] (snd_pcm_open_substream) from [<c03dbb28>] (snd_pcm_open+0xbc/0x22c)
[  299.288255] [<c03dbb28>] (snd_pcm_open) from [<c03dbd58>] (snd_pcm_playback_open+0x50/0x88)
[  299.295468] [<c03dbd58>] (snd_pcm_playback_open) from [<c03c9708>] (snd_open+0x124/0x144)
[  299.302897] [<c03c9708>] (snd_open) from [<c0117de4>] (chrdev_open+0x1a0/0x1f0)
[  299.310296] [<c0117de4>] (chrdev_open) from [<c010f4cc>] (do_dentry_open.constprop.0+0x1d4/0x31c)
[  299.317345] [<c010f4cc>] (do_dentry_open.constprop.0) from [<c011061c>] (vfs_open+0x7c/0x80)
[  299.324597] [<c011061c>] (vfs_open) from [<c0123080>] (path_openat+0xbe8/0xf90)
[  299.332003] [<c0123080>] (path_openat) from [<c0124240>] (do_filp_open+0x80/0xe4)
[  299.339044] [<c0124240>] (do_filp_open) from [<c0110a08>] (do_sys_open+0x148/0x1f8)
[  299.346225] [<c0110a08>] (do_sys_open) from [<c0110ae4>] (SyS_open+0x2c/0x30)
[  299.353505] [<c0110ae4>] (SyS_open) from [<c0009000>] (ret_fast_syscall+0x0/0x28)

Cheers.
Arnd Bergmann April 5, 2018, 7:29 a.m. UTC | #5
On Thu, Apr 5, 2018 at 8:51 AM, Robert Jarzmik <robert.jarzmik@free.fr> wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
>
>> I'm still unable to follow through that code, but I understand now that
>> the device you pass to dma_request_slave_channel() is not the one
>> we'd like it to be here.
>>
>> Where exactly does that call to dma_request_chan() happen? Is this
>> the one in dmaengine_pcm_new()? Could we perhaps put a
>> pointer to the SSP device into snd_dmaengine_dai_dma_data?
> This is a sample stack I captured with an added WARN_ON(1), triggered by a
> userland "aplay Sultans_Of_Swing.wav" :)
>
> [  299.216743] [<c0012e80>] (unwind_backtrace) from [<c000f55c>] (show_stack+0x20/0x24)
> [  299.223986] [<c000f55c>] (show_stack) from [<c0529d68>] (dump_stack+0x20/0x28)
> [  299.231321] [<c0529d68>] (dump_stack) from [<c001de34>] (__warn+0xf0/0x11c)
> [  299.238183] [<c001de34>] (__warn) from [<c001df94>] (warn_slowpath_null+0x4c/0x58)
> [  299.245234] [<c001df94>] (warn_slowpath_null) from [<c02a2d38>] (dma_request_chan+0x40/0x228)
> [  299.252550] [<c02a2d38>] (dma_request_chan) from [<c02a2f38>] (dma_request_slave_channel+0x18/0x24)
> [  299.259855] [<c02a2f38>] (dma_request_slave_channel) from [<c03f76f0>] (__pxa2xx_pcm_open+0xf4/0x110)
> [  299.266789] [<c03f76f0>] (__pxa2xx_pcm_open) from [<c0409ed0>] (soc_pcm_open+0xf8/0x9c8)
> [  299.273932] [<c0409ed0>] (soc_pcm_open) from [<c03db9d4>] (snd_pcm_open_substream+0x9c/0x134)

Ok, so it seems we currently have a special case here that is only used by
pxa/mmp and omap, and you can simply open-code that by calling
dma_request_chan() from the pxa-specific __pxa2xx_pcm_open()
with any device pointer you like, it doesn't have to be the main audio
device.

I don't know exactly how the probing works, but I'd assume that we have
the correct device pointers in pxa2xx_ac97_dev_probe() and
asoc_ssp_probe(), or maybe in pxa2xx_ac97_*_startup() and
pxa_ssp_startup().

      Arnd
Robert Jarzmik April 8, 2018, 12:16 p.m. UTC | #6
Arnd Bergmann <arnd@arndb.de> writes:

> I don't know exactly how the probing works, but I'd assume that we have
> the correct device pointers in pxa2xx_ac97_dev_probe() and
> asoc_ssp_probe(), or maybe in pxa2xx_ac97_*_startup() and
> pxa_ssp_startup().

Yes, let's try this way, in the former patch

"ASoC: pxa: remove the dmaengine compat need" :
+++ b/sound/arm/pxa2xx-pcm-lib.c
@@ -126,7 +127,7 @@ int __pxa2xx_pcm_open(struct snd_pcm_substream *substream)
                return ret;
 
        return snd_dmaengine_pcm_open(
-               substream, dma_request_slave_channel(rtd->platform->dev,
+               substream, dma_request_slave_channel(rtd->cpu_dai->dev,
                                                     dma_params->chan_name));
 }

The cpu_dai device should be either pxa27x_ac97 or pxa-ssp-dai.<Id>, and amend
the dma slave map accordingly.

Cheers.
diff mbox

Patch

diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index c0b3c90fd67f..955d255dc4f4 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -481,6 +481,17 @@  void __init pxa_set_ac97_info(pxa2xx_audio_ops_t *ops)
 	pxa_register_device(&pxa_device_ac97, ops);
 }
 
+static struct pxa_ssp_info pxa_ssp_infos[] = {
+	{ .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
+	{ .dma_chan_rx_name = "ssp1_rx", .dma_chan_tx_name = "ssp1_tx", },
+	{ .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
+	{ .dma_chan_rx_name = "ssp2_rx", .dma_chan_tx_name = "ssp2_tx", },
+	{ .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
+	{ .dma_chan_rx_name = "ssp3_rx", .dma_chan_tx_name = "ssp3_tx", },
+	{ .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
+	{ .dma_chan_rx_name = "ssp4_rx", .dma_chan_tx_name = "ssp4_tx", },
+};
+
 #ifdef CONFIG_PXA25x
 
 static struct resource pxa25x_resource_pwm0[] = {
@@ -528,7 +539,7 @@  static struct resource pxa25x_resource_ssp[] = {
 	},
 };
 
-struct platform_device pxa25x_device_ssp = {
+static struct platform_device pxa25x_device_ssp = {
 	.name		= "pxa25x-ssp",
 	.id		= 0,
 	.dev		= {
@@ -554,7 +565,7 @@  static struct resource pxa25x_resource_nssp[] = {
 	},
 };
 
-struct platform_device pxa25x_device_nssp = {
+static struct platform_device pxa25x_device_nssp = {
 	.name		= "pxa25x-nssp",
 	.id		= 1,
 	.dev		= {
@@ -580,7 +591,7 @@  static struct resource pxa25x_resource_assp[] = {
 	},
 };
 
-struct platform_device pxa25x_device_assp = {
+static struct platform_device pxa25x_device_assp = {
 	/* ASSP is basically equivalent to NSSP */
 	.name		= "pxa25x-nssp",
 	.id		= 2,
@@ -591,6 +602,22 @@  struct platform_device pxa25x_device_assp = {
 	.resource	= pxa25x_resource_assp,
 	.num_resources	= ARRAY_SIZE(pxa25x_resource_assp),
 };
+
+static struct platform_device *pxa25x_device_ssps[] = {
+	&pxa25x_device_ssp,
+	&pxa25x_device_nssp,
+	&pxa25x_device_assp,
+};
+
+void __init pxa25x_set_ssp_info(void)
+{
+	int ssp;
+
+	for (ssp = 0; ssp < ARRAY_SIZE(pxa25x_device_ssps); ssp++)
+		pxa_register_device(pxa25x_device_ssps[ssp],
+				    &pxa_ssp_infos[ssp]);
+}
+
 #endif /* CONFIG_PXA25x */
 
 #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
@@ -698,7 +725,7 @@  static struct resource pxa27x_resource_ssp1[] = {
 	},
 };
 
-struct platform_device pxa27x_device_ssp1 = {
+static struct platform_device pxa27x_device_ssp1 = {
 	.name		= "pxa27x-ssp",
 	.id		= 0,
 	.dev		= {
@@ -724,7 +751,7 @@  static struct resource pxa27x_resource_ssp2[] = {
 	},
 };
 
-struct platform_device pxa27x_device_ssp2 = {
+static struct platform_device pxa27x_device_ssp2 = {
 	.name		= "pxa27x-ssp",
 	.id		= 1,
 	.dev		= {
@@ -750,7 +777,7 @@  static struct resource pxa27x_resource_ssp3[] = {
 	},
 };
 
-struct platform_device pxa27x_device_ssp3 = {
+static struct platform_device pxa27x_device_ssp3 = {
 	.name		= "pxa27x-ssp",
 	.id		= 2,
 	.dev		= {
@@ -761,6 +788,21 @@  struct platform_device pxa27x_device_ssp3 = {
 	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp3),
 };
 
+static struct platform_device *pxa27x_device_ssps[] = {
+	&pxa27x_device_ssp1,
+	&pxa27x_device_ssp2,
+	&pxa27x_device_ssp3,
+};
+
+void __init pxa27x_set_ssp_info(void)
+{
+	int ssp;
+
+	for (ssp = 0; ssp < ARRAY_SIZE(pxa27x_device_ssps); ssp++)
+		pxa_register_device(pxa27x_device_ssps[ssp],
+				    &pxa_ssp_infos[ssp]);
+}
+
 static struct resource pxa27x_resource_pwm0[] = {
 	[0] = {
 		.start	= 0x40b00000,
@@ -951,7 +993,7 @@  static struct resource pxa3xx_resource_ssp4[] = {
  * make the driver set the correct internal type, hence we provide specific
  * platform_devices for each of them.
  */
-struct platform_device pxa3xx_device_ssp1 = {
+static struct platform_device pxa3xx_device_ssp1 = {
 	.name		= "pxa3xx-ssp",
 	.id		= 0,
 	.dev		= {
@@ -962,7 +1004,7 @@  struct platform_device pxa3xx_device_ssp1 = {
 	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp1),
 };
 
-struct platform_device pxa3xx_device_ssp2 = {
+static struct platform_device pxa3xx_device_ssp2 = {
 	.name		= "pxa3xx-ssp",
 	.id		= 1,
 	.dev		= {
@@ -973,7 +1015,7 @@  struct platform_device pxa3xx_device_ssp2 = {
 	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp2),
 };
 
-struct platform_device pxa3xx_device_ssp3 = {
+static struct platform_device pxa3xx_device_ssp3 = {
 	.name		= "pxa3xx-ssp",
 	.id		= 2,
 	.dev		= {
@@ -984,7 +1026,7 @@  struct platform_device pxa3xx_device_ssp3 = {
 	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp3),
 };
 
-struct platform_device pxa3xx_device_ssp4 = {
+static struct platform_device pxa3xx_device_ssp4 = {
 	.name		= "pxa3xx-ssp",
 	.id		= 3,
 	.dev		= {
@@ -994,6 +1036,22 @@  struct platform_device pxa3xx_device_ssp4 = {
 	.resource	= pxa3xx_resource_ssp4,
 	.num_resources	= ARRAY_SIZE(pxa3xx_resource_ssp4),
 };
+
+static struct platform_device *pxa3xx_device_ssps[] = {
+	&pxa3xx_device_ssp1,
+	&pxa3xx_device_ssp2,
+	&pxa3xx_device_ssp3,
+	&pxa3xx_device_ssp4,
+};
+
+void __init pxa3xx_set_ssp_info(void)
+{
+	int ssp;
+
+	for (ssp = 0; ssp < ARRAY_SIZE(pxa3xx_device_ssps); ssp++)
+		pxa_register_device(pxa3xx_device_ssps[ssp],
+				    &pxa_ssp_infos[ssp]);
+}
 #endif /* CONFIG_PXA3xx */
 
 struct resource pxa_resource_gpio[] = {
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 11263f7c455b..5909805e7d84 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -22,17 +22,6 @@  extern struct platform_device pxa27x_device_i2c_power;
 extern struct platform_device pxa27x_device_ohci;
 extern struct platform_device pxa27x_device_keypad;
 
-extern struct platform_device pxa25x_device_ssp;
-extern struct platform_device pxa25x_device_nssp;
-extern struct platform_device pxa25x_device_assp;
-extern struct platform_device pxa27x_device_ssp1;
-extern struct platform_device pxa27x_device_ssp2;
-extern struct platform_device pxa27x_device_ssp3;
-extern struct platform_device pxa3xx_device_ssp1;
-extern struct platform_device pxa3xx_device_ssp2;
-extern struct platform_device pxa3xx_device_ssp3;
-extern struct platform_device pxa3xx_device_ssp4;
-
 extern struct platform_device pxa25x_device_pwm0;
 extern struct platform_device pxa25x_device_pwm1;
 extern struct platform_device pxa27x_device_pwm0;
@@ -65,3 +54,6 @@  extern void pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info);
 #ifdef CONFIG_PXA3xx
 extern void pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info);
 #endif
+void pxa25x_set_ssp_info(void);
+void pxa27x_set_ssp_info(void);
+void pxa3xx_set_ssp_info(void);
diff --git a/arch/arm/mach-pxa/include/mach/audio.h b/arch/arm/mach-pxa/include/mach/audio.h
index 7beebf7297b5..f1f6bc7673a1 100644
--- a/arch/arm/mach-pxa/include/mach/audio.h
+++ b/arch/arm/mach-pxa/include/mach/audio.h
@@ -28,4 +28,16 @@  typedef struct {
 
 extern void pxa_set_ac97_info(pxa2xx_audio_ops_t *ops);
 
+/*
+ * struct pxa_ssp_info - platform data for SSP devices
+ * @dma_chan_rx_name: name of the receive dma channel to query, see
+ *		      pxa_slave_map
+ * @dma_chan_tx_name: name of the transmit dma channel to query, see
+ *		      pxa_slave_map
+ */
+struct pxa_ssp_info {
+	const char *dma_chan_rx_name;
+	const char *dma_chan_tx_name;
+};
+
 #endif
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index ba431fad5c47..74779afbf200 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -193,9 +193,6 @@  static struct platform_device *pxa25x_devices[] __initdata = {
 	&pxa_device_pmu,
 	&pxa_device_i2s,
 	&sa1100_device_rtc,
-	&pxa25x_device_ssp,
-	&pxa25x_device_nssp,
-	&pxa25x_device_assp,
 	&pxa25x_device_pwm0,
 	&pxa25x_device_pwm1,
 	&pxa_device_asoc_platform,
@@ -219,6 +216,7 @@  static int __init pxa25x_init(void)
 			pxa_register_device(&pxa25x_device_gpio, &pxa25x_gpio_info);
 			ret = platform_add_devices(pxa25x_devices,
 						   ARRAY_SIZE(pxa25x_devices));
+			pxa25x_set_ssp_info();
 		}
 	}
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 0c06f383ad52..f3896d164fd3 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -290,9 +290,6 @@  static struct platform_device *devices[] __initdata = {
 	&pxa_device_asoc_ssp3,
 	&pxa_device_asoc_platform,
 	&pxa_device_rtc,
-	&pxa27x_device_ssp1,
-	&pxa27x_device_ssp2,
-	&pxa27x_device_ssp3,
 	&pxa27x_device_pwm0,
 	&pxa27x_device_pwm1,
 };
@@ -313,6 +310,7 @@  static int __init pxa27x_init(void)
 		if (!of_have_populated_dt()) {
 			pxa_register_device(&pxa27x_device_gpio,
 					    &pxa27x_gpio_info);
+			pxa27x_set_ssp_info();
 			pxa2xx_set_dmac_info(32, 75);
 			ret = platform_add_devices(devices,
 						   ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 4b8a0df8ea57..2a5044dd463e 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -413,10 +413,6 @@  static struct platform_device *devices[] __initdata = {
 	&pxa_device_asoc_ssp4,
 	&pxa_device_asoc_platform,
 	&pxa_device_rtc,
-	&pxa3xx_device_ssp1,
-	&pxa3xx_device_ssp2,
-	&pxa3xx_device_ssp3,
-	&pxa3xx_device_ssp4,
 	&pxa27x_device_pwm0,
 	&pxa27x_device_pwm1,
 };
@@ -456,6 +452,7 @@  static int __init pxa3xx_init(void)
 		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 		if (ret)
 			return ret;
+		pxa3xx_set_ssp_info();
 		if (cpu_is_pxa300() || cpu_is_pxa310() || cpu_is_pxa320()) {
 			platform_device_add_data(&pxa3xx_device_gpio,
 						 &pxa3xx_gpio_pdata,