Re: 3.11-rc3+git: __divdi3 undefined on powerpc (from radeon)

2013-08-04 Thread Guenter Roeck
On Sat, Aug 03, 2013 at 03:44:26PM +0300, Meelis Roos wrote:
> While trying to compile v3.11-rc3-288-gabe0308 on powerpc 32-bit, 
> it failed with the following linking error:
> 
> ERROR: "__divdi3" [drivers/gpu/drm/radeon/radeon.ko] undefined!
> 
> Some new 64-bit division in radeon that is not implemented on 32-bit 
> powerpc?
> 
> This is new - 3.11-rc3 worked fine.
> 
Not only powerpc - i386 builds fail with the same error.

Guenter
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] drivers/crypto/nx: saves chaining value from co-processor

2013-08-04 Thread Michael Ellerman
On Fri, Aug 02, 2013 at 05:16:56PM -0500, Fionnuala Gunter wrote:
> On Sat, 2013-08-03 at 07:59 +1000, Benjamin Herrenschmidt wrote:
> > On Fri, 2013-08-02 at 16:55 -0500, Fionnuala Gunter wrote:
> > > Sorry, I thought linuxppc-dev was the right tree since the patch is
> > > for
> > > a ppc driver and you've carried previous nx driver submissions
> > > upstream. 
> > > 
> > > I want to submit to the proper place, so what is your preference?
> > 
> > Well, that's the right place if you want me to merge it, which seems to
> > be what Marcelo is also expecting...
> 
> Please merge this patch, it fixes a hot bug.

You don't actually mention that anywhere in the changelog.

The description implies that it's probably a bug, but doesn't describe
the symptoms in any way - does it make it completely non-functional or
just break in certain corner cases.

And you make no mention of when this bug appeared, has it always been
there, or was it introduced by a particular commit? That's important
because it helps determine whether the patch should go into any of the
stable trees.

cheers
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 2/8] Mark powerpc memory resources as busy

2013-08-04 Thread Michael Ellerman
On Fri, Aug 02, 2013 at 02:05:57PM -0500, Nathan Fontenot wrote:
> On 08/01/2013 09:28 PM, Michael Ellerman wrote:
> > On Wed, Jul 24, 2013 at 01:36:34PM -0500, Nathan Fontenot wrote:
> >> Memory I/O resources need to be marked as busy or else we cannot remove
> >> them when doing memory hot remove.
> > 
> > I would have thought it was the opposite?
> 
> Me too.
> 
> As it turns out the code in kernel/resource.c checks to make sure the
> IORESOURCE_BUSY flag is set when trying to release a resource.

OK, I guess there's probably some sane reason, but it does seem
backward.

cheers
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH 3/8] Add all memory via sysfs probe interface at once

2013-08-04 Thread Michael Ellerman
On Fri, Aug 02, 2013 at 02:13:06PM -0500, Nathan Fontenot wrote:
> On 08/01/2013 09:32 PM, Michael Ellerman wrote:
> > On Wed, Jul 24, 2013 at 01:37:47PM -0500, Nathan Fontenot wrote:
> >> When doing memory hot add via the 'probe' interface in sysfs we do not
> >> need to loop through and add memory one section at a time. I think this
> >> was originally done for powerpc, but is not needed. This patch removes
> >> the loop and just calls add_memory for all of the memory to be added.
> > 
> > Looks like memory hot add is supported on ia64, x86, sh, powerpc and
> > s390. Have you tested on any?
> 
> I have tested on powerpc. I would love to say I tested on the other
> platforms... but I haven't.  I should be able to get a x86 box to test
> on but the other architectures may not be possible.

Is the rest of your series dependent on this patch? Or is it sort of
incidental?

If possible it might be worth pulling this one out and sticking it in
linux-next for a cycle to give people a chance to test it. Unless
someone who knows the code well is comfortable with it.

cheers
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] powerpc: Implement __get_user_pages_fast()

2013-08-04 Thread Paul Mackerras
Other architectures have a __get_user_pages_fast(), in addition to the
regular get_user_pages_fast(), which doesn't call get_user_pages() on
failure, and thus doesn't attempt to fault pages in or COW them.  The
generic KVM code uses __get_user_pages_fast() to detect whether a page
for which we have only requested read access is actually writable.

This provides an implementation of __get_user_pages_fast() by
splitting the existing get_user_pages_fast() in two.  With this, the
generic KVM code will get the right answer instead of always
considering such pages non-writable.

Signed-off-by: Paul Mackerras 
---
 arch/powerpc/mm/gup.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c
index 49822d9..6936547 100644
--- a/arch/powerpc/mm/gup.c
+++ b/arch/powerpc/mm/gup.c
@@ -117,8 +117,8 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, 
unsigned long end,
return 1;
 }
 
-int get_user_pages_fast(unsigned long start, int nr_pages, int write,
-   struct page **pages)
+int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
+ struct page **pages)
 {
struct mm_struct *mm = current->mm;
unsigned long addr, len, end;
@@ -135,7 +135,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, 
int write,
 
if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
start, len)))
-   goto slow_irqon;
+   return 0;
 
pr_devel("  aligned: %lx .. %lx\n", start, end);
 
@@ -166,30 +166,35 @@ int get_user_pages_fast(unsigned long start, int 
nr_pages, int write,
 (void *)pgd_val(pgd));
next = pgd_addr_end(addr, end);
if (pgd_none(pgd))
-   goto slow;
+   break;
if (pgd_huge(pgd)) {
if (!gup_hugepte((pte_t *)pgdp, PGDIR_SIZE, addr, next,
 write, pages, &nr))
-   goto slow;
+   break;
} else if (is_hugepd(pgdp)) {
if (!gup_hugepd((hugepd_t *)pgdp, PGDIR_SHIFT,
addr, next, write, pages, &nr))
-   goto slow;
+   break;
} else if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
-   goto slow;
+   break;
} while (pgdp++, addr = next, addr != end);
 
local_irq_enable();
 
-   VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
return nr;
+}
 
-   {
-   int ret;
+int get_user_pages_fast(unsigned long start, int nr_pages, int write,
+   struct page **pages)
+{
+   struct mm_struct *mm = current->mm;
+   int nr, ret;
+
+   start &= PAGE_MASK;
+   nr = __get_user_pages_fast(start, nr_pages, write, pages);
+   ret = nr;
 
-slow:
-   local_irq_enable();
-slow_irqon:
+   if (nr < nr_pages) {
pr_devel("  slow path ! nr = %d\n", nr);
 
/* Try to get the remaining pages with get_user_pages */
@@ -198,7 +203,7 @@ slow_irqon:
 
down_read(&mm->mmap_sem);
ret = get_user_pages(current, mm, start,
-   (end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
+nr_pages - nr, write, 0, pages, NULL);
up_read(&mm->mmap_sem);
 
/* Have to be a bit careful with return values */
@@ -208,9 +213,9 @@ slow_irqon:
else
ret += nr;
}
-
-   return ret;
}
+
+   return ret;
 }
 
 #endif /* __HAVE_ARCH_PTE_SPECIAL */
-- 
1.8.3.1

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH] powerpc: Fix VRSAVE handling

2013-08-04 Thread Paul Mackerras
Since 2002, the kernel has not saved VRSAVE on exception entry and
restored it on exit; rather, VRSAVE gets context-switched in _switch.
This means that when executing in process context in the kernel, the
userspace VRSAVE value is live in the VRSAVE register.

However, the signal code assumes that current->thread.vrsave holds
the current VRSAVE value, which is incorrect.  Therefore, this
commit changes it to use the actual VRSAVE register instead.  (It
still uses current->thread.vrsave as a temporary location to store
it in, as __get_user and __put_user can only transfer to/from a
variable, not an SPR.)

This also modifies the transactional memory code to save and restore
VRSAVE regardless of whether VMX is enabled in the MSR.  This is
because accesses to VRSAVE are not controlled by the MSR.VEC bit,
but can happen at any time.

Signed-off-by: Paul Mackerras 
---
 arch/powerpc/kernel/signal_32.c | 9 +
 arch/powerpc/kernel/signal_64.c | 8 
 arch/powerpc/kernel/tm.S| 4 ++--
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 0f83122..bebdf1a 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -436,7 +436,10 @@ static int save_user_regs(struct pt_regs *regs, struct 
mcontext __user *frame,
 * use altivec. Since VSCR only contains 32 bits saved in the least
 * significant bits of a vector, we "cheat" and stuff VRSAVE in the
 * most significant bits of that same vector. --BenH
+* Note that the current VRSAVE value is in the SPR at this point.
 */
+   if (cpu_has_feature(CPU_FTR_ALTIVEC))
+   current->thread.vrsave = mfspr(SPRN_VRSAVE);
if (__put_user(current->thread.vrsave, (u32 __user 
*)&frame->mc_vregs[32]))
return 1;
 #endif /* CONFIG_ALTIVEC */
@@ -557,6 +560,8 @@ static int save_tm_user_regs(struct pt_regs *regs,
 * significant bits of a vector, we "cheat" and stuff VRSAVE in the
 * most significant bits of that same vector. --BenH
 */
+   if (cpu_has_feature(CPU_FTR_ALTIVEC))
+   current->thread.vrsave = mfspr(SPRN_VRSAVE);
if (__put_user(current->thread.vrsave,
   (u32 __user *)&frame->mc_vregs[32]))
return 1;
@@ -696,6 +701,8 @@ static long restore_user_regs(struct pt_regs *regs,
/* Always get VRSAVE back */
if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
return 1;
+   if (cpu_has_feature(CPU_FTR_ALTIVEC))
+   mtspr(SPRN_VRSAVE, current->thread.vrsave);
 #endif /* CONFIG_ALTIVEC */
if (copy_fpr_from_user(current, &sr->mc_fregs))
return 1;
@@ -809,6 +816,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
__get_user(current->thread.transact_vrsave,
   (u32 __user *)&tm_sr->mc_vregs[32]))
return 1;
+   if (cpu_has_feature(CPU_FTR_ALTIVEC))
+   mtspr(SPRN_VRSAVE, current->thread.vrsave);
 #endif /* CONFIG_ALTIVEC */
 
regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 887e99d..c95257e 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -114,6 +114,8 @@ static long setup_sigcontext(struct sigcontext __user *sc, 
struct pt_regs *regs,
/* We always copy to/from vrsave, it's 0 if we don't have or don't
 * use altivec.
 */
+   if (cpu_has_feature(CPU_FTR_ALTIVEC))
+   current->thread.vrsave = mfspr(SPRN_VRSAVE);
err |= __put_user(current->thread.vrsave, (u32 __user *)&v_regs[33]);
 #else /* CONFIG_ALTIVEC */
err |= __put_user(0, &sc->v_regs);
@@ -217,6 +219,8 @@ static long setup_tm_sigcontexts(struct sigcontext __user 
*sc,
/* We always copy to/from vrsave, it's 0 if we don't have or don't
 * use altivec.
 */
+   if (cpu_has_feature(CPU_FTR_ALTIVEC))
+   current->thread.vrsave = mfspr(SPRN_VRSAVE);
err |= __put_user(current->thread.vrsave, (u32 __user *)&v_regs[33]);
if (msr & MSR_VEC)
err |= __put_user(current->thread.transact_vrsave,
@@ -356,6 +360,8 @@ static long restore_sigcontext(struct pt_regs *regs, 
sigset_t *set, int sig,
err |= __get_user(current->thread.vrsave, (u32 __user 
*)&v_regs[33]);
else
current->thread.vrsave = 0;
+   if (cpu_has_feature(CPU_FTR_ALTIVEC))
+   mtspr(SPRN_VRSAVE, current->thread.vrsave);
 #endif /* CONFIG_ALTIVEC */
/* restore floating point */
err |= copy_fpr_from_user(current, &sc->fp_regs);
@@ -484,6 +490,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
current->thread.vrsave = 0;
current->thread.transact_vrsave = 0;
}
+   if (cpu_has

Re: [PATCH] arch: powerpc: kvm: add signed type cast for comparation

2013-08-04 Thread Paul Mackerras
On Mon, Jul 22, 2013 at 02:32:35PM +0800, Chen Gang wrote:
> 'rmls' is 'unsigned long', lpcr_rmls() will return negative number when
> failure occurs, so it need a type cast for comparing.
> 
> 'lpid' is 'unsigned long', kvmppc_alloc_lpid() return negative number
> when failure occurs, so it need a type cast for comparing.
> 
> 
> Signed-off-by: Chen Gang 

Looks right, thanks.

Acked-by: Paul Mackerras 
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


Re: [PATCH] arch: powerpc: kvm: add signed type cast for comparation

2013-08-04 Thread Chen Gang
On 08/05/2013 12:34 PM, Paul Mackerras wrote:
> On Mon, Jul 22, 2013 at 02:32:35PM +0800, Chen Gang wrote:
>> > 'rmls' is 'unsigned long', lpcr_rmls() will return negative number when
>> > failure occurs, so it need a type cast for comparing.
>> > 
>> > 'lpid' is 'unsigned long', kvmppc_alloc_lpid() return negative number
>> > when failure occurs, so it need a type cast for comparing.
>> > 
>> > 
>> > Signed-off-by: Chen Gang 
> Looks right, thanks.
> 
> Acked-by: Paul Mackerras 
> 
> 

Thank you very much.

-- 
Chen Gang
___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v2 1/2] ASoC: fsl: Add S/PDIF CPU DAI driver

2013-08-04 Thread Nicolin Chen
This patch add S/PDIF controller driver for Freescale SoC.

Reviewed-by: Lars-Peter Clausen 
Signed-off-by: Nicolin Chen 
---
 .../devicetree/bindings/sound/fsl,spdif.txt|   62 +
 sound/soc/fsl/Kconfig  |3 +
 sound/soc/fsl/Makefile |2 +
 sound/soc/fsl/fsl_spdif.c  | 1311 
 sound/soc/fsl/fsl_spdif.h  |  227 
 5 files changed, 1605 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,spdif.txt
 create mode 100644 sound/soc/fsl/fsl_spdif.c
 create mode 100644 sound/soc/fsl/fsl_spdif.h

diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt 
b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
new file mode 100644
index 000..8b1bfe2
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/fsl,spdif.txt
@@ -0,0 +1,62 @@
+Freescale Sony/Philips Digital Interface Format (S/PDIF) Controller
+
+The Freescale S/PDIF audio block is a stereo transceiver that allows the
+processor to receive and transmit digital audio via an coaxial cable or
+a fibre cable.
+
+Required properties:
+
+  - compatible : Compatible list, contains "fsl,fsl-spdif" or SoC specific
+  "fsl,imx6q-spdif", "fsl,imx6sl-spdif".
+
+  - reg : Offset and length of the register set for the device.
+
+  - interrupts : Should contain spdif interrupt.
+
+  - dmas : Generic dma devicetree binding as described in
+  Documentation/devicetree/bindings/dma/dma.txt.
+
+  - dma-names : Two dmas have to be defined, "tx" and "rx".
+
+  - clocks : (First) The phandle for the clock ID registered in clock tree.
+  There could be two clocks being set here, but only the first one, CORE
+  clock, is must.
+
+
+Optional properties:
+
+  - clocks : (Second) The phandle for the clock ID registered in clock tree.
+  There could be two clocks being set here, but the second one, TX clock is
+  optional. If absent, the TX clock will use CORE clock as default.
+
+  - clock-names : The names for the two clocks. It will be required only when
+  the second clock's present. If absent, the TX clock will use CORE clock as
+  default.
+
+  - tx-clk-source : The clock cources for Tx. Need to set this source according
+  to the SoC datasheet in SPDIF_STC section. If absent, the default source is
+  value 0x1 - CCM spdif0_clk_root input.
+
+  - rx-clk-source : The clock cource for Rx. Need to set this source according
+  to the SoC datasheet in SPDIF_SRPC section. If absent, the default source is
+  value 0x0 - if (DPLL Locked) SPDIF_RxClk else extal.
+
+
+Example:
+
+spdif: spdif@02004000 {
+   compatible = "fsl,fsl-spdif";
+   reg = <0x02004000 0x4000>;
+   interrupts = <0 52 0x04>;
+   dmas = <&sdma 14 18 0>,
+  <&sdma 15 18 0>;
+   dma-names = "rx", "tx";
+
+   clocks = <&clks 197>, <&clks 197>;
+   clock-names = "core", "tx";
+
+   tx-clk-source = <0x1>;
+   rx-clk-source = <0x0>;
+
+   status = "okay";
+};
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index c26449b..74f533b 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,6 +1,9 @@
 config SND_SOC_FSL_SSI
tristate
 
+config SND_SOC_FSL_SPDIF
+   tristate
+
 config SND_SOC_FSL_UTILS
tristate
 
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index d4b4aa8..4b5970e 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -12,9 +12,11 @@ obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
 
 # Freescale PowerPC SSI/DMA Platform Support
 snd-soc-fsl-ssi-objs := fsl_ssi.o
+snd-soc-fsl-spdif-objs := fsl_spdif.o
 snd-soc-fsl-utils-objs := fsl_utils.o
 snd-soc-fsl-dma-objs := fsl_dma.o
 obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o
+obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
 obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
 obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
new file mode 100644
index 000..8865499
--- /dev/null
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -0,0 +1,1311 @@
+/*
+ * Freescale S/PDIF ALSA SoC Digital Audio Interface (DAI) driver
+ *
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * Based on stmp3xxx_spdif_dai.c
+ * Vladimir Barinov 
+ * Copyright 2008 SigmaTel, Inc
+ * Copyright 2008 Embedded Alley Solutions, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program  is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "fsl_spdif.h"
+#include "imx-pcm.h"
+
+#define FSL_SPDIF_TXFIFO_WML  0x8
+#define FSL_SPDIF_RXFIFO_WML  0x8
+
+#define INTR_FOR_PLAYBACK (INT_TXFIFO_RESYNC)
+#define INTR_FOR_CAPTURE (INT_SYM_ERR | INT_BIT_ERR | INT_URX_FUL | 
INT_URX_OV|\
+   INT_QRX_F

[PATCH v2 0/2] Add freescale S/PDIF CPU DAI and machine drivers

2013-08-04 Thread Nicolin Chen
Changelog:
v1->v2:
 * Dropped one applied patch for spdif dummy codec drivers.
 * Use generic DMA DT binding.
 * Let spdif controller driver calculate the clock div.
 * Added one optional clock source for spdif tx.
 * Reivsed documentation accordingly.

Nicolin Chen (2):
  ASoC: fsl: Add S/PDIF CPU DAI driver
  ASoC: fsl: Add S/PDIF machine driver

 .../devicetree/bindings/sound/fsl,spdif.txt|   62 +
 .../devicetree/bindings/sound/imx-audio-spdif.txt  |   29 +
 sound/soc/fsl/Kconfig  |   14 +
 sound/soc/fsl/Makefile |4 +
 sound/soc/fsl/fsl_spdif.c  | 1311 
 sound/soc/fsl/fsl_spdif.h  |  227 
 sound/soc/fsl/imx-spdif.c  |  134 ++
 7 files changed, 1781 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/fsl,spdif.txt
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-spdif.txt
 create mode 100644 sound/soc/fsl/fsl_spdif.c
 create mode 100644 sound/soc/fsl/fsl_spdif.h
 create mode 100644 sound/soc/fsl/imx-spdif.c


___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev


[PATCH v2 2/2] ASoC: fsl: Add S/PDIF machine driver

2013-08-04 Thread Nicolin Chen
Add S/PDIF machine driver for Freescale i.MX series SoC.

Signed-off-by: Nicolin Chen 
---
 .../devicetree/bindings/sound/imx-audio-spdif.txt  |   29 +
 sound/soc/fsl/Kconfig  |   11 ++
 sound/soc/fsl/Makefile |2 +
 sound/soc/fsl/imx-spdif.c  |  134 
 4 files changed, 176 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-spdif.txt
 create mode 100644 sound/soc/fsl/imx-spdif.c

diff --git a/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt 
b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt
new file mode 100644
index 000..9a3fa26
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt
@@ -0,0 +1,29 @@
+Freescale i.MX audio complex with S/PDIF transceiver
+
+Required properties:
+
+  - compatible : "fsl,imx-audio-spdif"
+
+  - model : The user-visible name of this sound complex
+
+  - spdif-controller : The phandle of the i.MX S/PDIF controller
+
+
+Optional properties:
+
+  - spdif-transmitter : The phandle of the spdif-transmitter dummy codec
+
+  - spdif-receiver : The phandle of the spdif-receiver dummy codec
+
+* Note: At least one of these two properties should be set in the DT binding.
+
+
+Example:
+
+sound-spdif {
+   compatible = "fsl,imx-audio-spdif";
+   model = "imx-spdif";
+   spdif-controller = <&spdif>;
+   spdif-transmitter = <&spdif_tx_codec>;
+   spdif-receiver = <&spdif_rx_codec>;
+};
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 74f533b..9043abc 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -195,6 +195,17 @@ config SND_SOC_IMX_SGTL5000
  Say Y if you want to add support for SoC audio on an i.MX board with
  a sgtl5000 codec.
 
+config SND_SOC_IMX_SPDIF
+   tristate "SoC Audio support for i.MX boards with S/PDIF"
+   select SND_SOC_IMX_PCM_DMA
+   select SND_SOC_FSL_SPDIF
+   select SND_SOC_FSL_UTILS
+   select SND_SOC_SPDIF
+   help
+ SoC Audio support for i.MX boards with S/PDIF
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ a S/DPDIF.
+
 config SND_SOC_IMX_MC13783
tristate "SoC Audio support for I.MX boards with mc13783"
depends on MFD_MC13783 && ARCH_ARM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index 4b5970e..e2aaff7 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -45,6 +45,7 @@ snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
 snd-soc-wm1133-ev1-objs := wm1133-ev1.o
 snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
 snd-soc-imx-wm8962-objs := imx-wm8962.o
+snd-soc-imx-spdif-objs :=imx-spdif.o
 snd-soc-imx-mc13783-objs := imx-mc13783.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
@@ -53,4 +54,5 @@ obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += 
snd-soc-mx27vis-aic32x4.o
 obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
 obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
 obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
+obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
 obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c
new file mode 100644
index 000..893f3d1
--- /dev/null
+++ b/sound/soc/fsl/imx-spdif.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include 
+#include 
+#include 
+
+struct imx_spdif_data {
+   struct snd_soc_dai_link dai[2];
+   struct snd_soc_card card;
+};
+
+static int imx_spdif_audio_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct device_node *spdif_np, *codec_tx_np, *codec_rx_np;
+   struct platform_device *spdif_pdev;
+   struct imx_spdif_data *data;
+   int ret = 0, num_links = 0;
+
+   spdif_np = of_parse_phandle(np, "spdif-controller", 0);
+   if (!spdif_np) {
+   dev_err(&pdev->dev, "failed to find spdif-controller\n");
+   ret = -EINVAL;
+   goto fail;
+   }
+
+   spdif_pdev = of_find_device_by_node(spdif_np);
+   if (!spdif_pdev) {
+   dev_err(&pdev->dev, "failed to find S/PDIF device\n");
+   ret = -EINVAL;
+   goto fail;
+   }
+
+   data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+   if (!data) {
+   dev_err(&pdev->dev, "failed to allocate memory\n");
+   ret = -ENOMEM;
+   goto fail;
+   }
+
+   codec_tx_np = of_parse_phandle(np, "spdif-transmitter", 0);
+   if