<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/">
  <channel rdf:about="http://blog.gmane.org/gmane.linux.ports.arm.kernel">
    <title>gmane.linux.ports.arm.kernel</title>
    <link>http://blog.gmane.org/gmane.linux.ports.arm.kernel</link>
    <description/>
    <syn:updatePeriod>hourly</syn:updatePeriod>
    <syn:updateFrequency>1</syn:updateFrequency>
    <syn:updateBase>1901-01-01T00:00+00:00</syn:updateBase>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169382"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169381"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169380"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169379"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169377"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169371"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169359"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169357"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169352"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169351"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169345"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169327"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169326"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169325"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169324"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169323"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169322"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169314"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169313"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169312"/>
      </rdf:Seq>
    </items>
    <image rdf:resource="http://gmane.org/img/gmane-25t.png"/>
    <textinput rdf:resource=""/>
  </channel>
  <image rdf:about="http://gmane.org/img/gmane-25t.png">
    <title>Gmane</title>
    <url>http://gmane.org/img/gmane-25t.png</url>
    <link>http://gmane.org</link>
  </image>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169382">
    <title>[STABLE PATCH] ARM: 7409/1: Do not call flush_cache_user_range with mmap_sem held</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169382</link>
    <description>&lt;pre&gt;From: Dima Zavin &amp;lt;dima&amp;lt; at &amp;gt;android.com&amp;gt;

commit 435a7ef52db7d86e67a009b36cac1457f8972391 upstream

We can't be holding the mmap_sem while calling flush_cache_user_range
because the flush can fault. If we fault on a user address, the
page fault handler will try to take mmap_sem again. Since both places
acquire the read lock, most of the time it succeeds. However, if another
thread tries to acquire the write lock on the mmap_sem (e.g. mmap) in
between the call to flush_cache_user_range and the fault, the down_read
in do_page_fault will deadlock.

[will: removed drop of vma parameter as already queued by rmk (7365/1)]

Cc: &amp;lt;stable&amp;lt; at &amp;gt;vger.kernel.org&amp;gt; # 2.6.32+: 4542b6a0: ARM: 7365/1
Cc: &amp;lt;stable&amp;lt; at &amp;gt;vger.kernel.org&amp;gt; # 2.6.32+
Acked-by: Catalin Marinas &amp;lt;catalin.marinas&amp;lt; at &amp;gt;arm.com&amp;gt;
Signed-off-by: Dima Zavin &amp;lt;dima&amp;lt; at &amp;gt;android.com&amp;gt;
Signed-off-by: John Stultz &amp;lt;john.stultz&amp;lt; at &amp;gt;linaro.org&amp;gt;
Signed-off-by: Will Deacon &amp;lt;will.deacon&amp;lt; at &amp;gt;arm.com&amp;gt;
Signed-off-by: Russell King &amp;lt;rmk+kernel&amp;lt; at &amp;gt;arm.linux.org.uk&amp;gt;
---

Greg: This patch is a candidate for -stable, but its dependency (listed
      above) wasn't marked as such, hence this retrospective submission.

 arch/arm/kernel/traps.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 55b2f3d..63d402f 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -496,7 +496,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; do_cache_op(unsigned long start, unsigned long end, int flags)
 if (end &amp;gt; vma-&amp;gt;vm_end)
 end = vma-&amp;gt;vm_end;
 
+up_read(&amp;amp;mm-&amp;gt;mmap_sem);
 flush_cache_user_range(start, end);
+return;
 }
 up_read(&amp;amp;mm-&amp;gt;mmap_sem);
 }
&lt;/pre&gt;</description>
    <dc:creator>Will Deacon</dc:creator>
    <dc:date>2012-05-25T14:38:04</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169381">
    <title>[PATCH 2/2] mtd mxc_nand: move ecc strengh setup before nand_scan_tail</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169381</link>
    <description>&lt;pre&gt;Since this commit:

  commit 6a918bade9dab40aaef80559bd1169c69e8d69cb
  Author: Mike Dunn &amp;lt;mikedunn&amp;lt; at &amp;gt;newsguy.com&amp;gt;
  Date:   Sun Mar 11 14:21:11 2012 -0700

     mtd: flash drivers set ecc strength

The mxc_nand driver fails with:

Driver must set ecc.strength when using hardware ECC

This is because nand_scan_tail checks for correct ecc strength
settings, so we must set them up before nand_scan_tail.

Signed-off-by: Sascha Hauer &amp;lt;s.hauer&amp;lt; at &amp;gt;pengutronix.de&amp;gt;
Cc: stable&amp;lt; at &amp;gt;vger.kernel.org
---
 drivers/mtd/nand/mxc_nand.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 4d27ddc..aaf042b 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1485,12 +1485,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int __init mxcnd_probe(struct platform_device *pdev)
 else if (mtd-&amp;gt;writesize == 4096)
 this-&amp;gt;ecc.layout = host-&amp;gt;devtype_data-&amp;gt;ecclayout_4k;
 
-/* second phase scan */
-if (nand_scan_tail(mtd)) {
-err = -ENXIO;
-goto escan;
-}
-
 if (this-&amp;gt;ecc.mode == NAND_ECC_HW) {
 if (nfc_is_v1())
 this-&amp;gt;ecc.strength = 1;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1498,6 +1492,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int __init mxcnd_probe(struct platform_device *pdev)
 this-&amp;gt;ecc.strength = (host-&amp;gt;eccsize == 4) ? 4 : 8;
 }
 
+/* second phase scan */
+if (nand_scan_tail(mtd)) {
+err = -ENXIO;
+goto escan;
+}
+
 /* Register the partitions */
 mtd_device_parse_register(mtd, part_probes,
 &amp;amp;(struct mtd_part_parser_data){
&lt;/pre&gt;</description>
    <dc:creator>Sascha Hauer</dc:creator>
    <dc:date>2012-05-25T14:22:42</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169380">
    <title>[PATCH 1/2] mtd mxc_nand: use 32bit copy functions</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169380</link>
    <description>&lt;pre&gt;The following commit changes the function used to copy from/to
the hardware buffer to memcpy_[from|to]io. This does not work
since the hardware cannot handle the byte accesses used by these
functions. Instead of reverting this patch introduce 32bit
correspondents of these functions.

commit 5775ba36ea9c760c2d7e697dac04f2f7fc95aa62
Author: Uwe Kleine-König &amp;lt;u.kleine-koenig&amp;lt; at &amp;gt;pengutronix.de&amp;gt;
Date:   Tue Apr 24 10:05:22 2012 +0200

    mtd: mxc_nand: fix several sparse warnings about incorrect address space

    Signed-off-by: Uwe Kleine-König &amp;lt;u.kleine-koenig&amp;lt; at &amp;gt;pengutronix.de&amp;gt;
    Signed-off-by: Artem Bityutskiy &amp;lt;artem.bityutskiy&amp;lt; at &amp;gt;linux.intel.com&amp;gt;

Signed-off-by: Sascha Hauer &amp;lt;s.hauer&amp;lt; at &amp;gt;pengutronix.de&amp;gt;
Cc: Uwe Kleine-König &amp;lt;u.kleine-koenig&amp;lt; at &amp;gt;pengutronix.de&amp;gt;
---
 drivers/mtd/nand/mxc_nand.c |   36 ++++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index fd14966..4d27ddc 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -273,6 +273,26 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct nand_ecclayout nandv2_hw_eccoob_4k = {
 
 static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL };
 
+static void memcpy32_fromio(void *trg, const volatile void __iomem  *src, size_t size)
+{
+int i;
+u32 *t = trg;
+const volatile u32 *s = src;
+
+for (i = 0; i &amp;lt; (size &amp;gt;&amp;gt; 2); i++)
+*t++ = __raw_readl(s++);
+}
+
+static void memcpy32_toio(volatile void __iomem *trg, const void *src, int size)
+{
+int i;
+volatile u32 *t = trg;
+const u32 *s = src;
+
+for (i = 0; i &amp;lt; (size &amp;gt;&amp;gt; 2); i++)
+__raw_writel(*s++, t++);
+}
+
 static int check_int_v3(struct mxc_nand_host *host)
 {
 uint32_t tmp;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -519,7 +539,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void send_read_id_v3(struct mxc_nand_host *host)
 
 wait_op_done(host, true);
 
-memcpy_fromio(host-&amp;gt;data_buf, host-&amp;gt;main_area0, 16);
+memcpy32_fromio(host-&amp;gt;data_buf, host-&amp;gt;main_area0, 16);
 }
 
 /* Request the NANDFC to perform a read of the NAND device ID. */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -535,7 +555,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void send_read_id_v1_v2(struct mxc_nand_host *host)
 /* Wait for operation to complete */
 wait_op_done(host, true);
 
-memcpy_fromio(host-&amp;gt;data_buf, host-&amp;gt;main_area0, 16);
+memcpy32_fromio(host-&amp;gt;data_buf, host-&amp;gt;main_area0, 16);
 
 if (this-&amp;gt;options &amp;amp; NAND_BUSWIDTH_16) {
 /* compress the ID info */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -797,16 +817,16 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void copy_spare(struct mtd_info *mtd, bool bfrom)
 
 if (bfrom) {
 for (i = 0; i &amp;lt; n - 1; i++)
-memcpy_fromio(d + i * j, s + i * t, j);
+memcpy32_fromio(d + i * j, s + i * t, j);
 
 /* the last section */
-memcpy_fromio(d + i * j, s + i * t, mtd-&amp;gt;oobsize - i * j);
+memcpy32_fromio(d + i * j, s + i * t, mtd-&amp;gt;oobsize - i * j);
 } else {
 for (i = 0; i &amp;lt; n - 1; i++)
-memcpy_toio(&amp;amp;s[i * t], &amp;amp;d[i * j], j);
+memcpy32_toio(&amp;amp;s[i * t], &amp;amp;d[i * j], j);
 
 /* the last section */
-memcpy_toio(&amp;amp;s[i * t], &amp;amp;d[i * j], mtd-&amp;gt;oobsize - i * j);
+memcpy32_toio(&amp;amp;s[i * t], &amp;amp;d[i * j], mtd-&amp;gt;oobsize - i * j);
 }
 }
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1070,7 +1090,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
 host-&amp;gt;devtype_data-&amp;gt;send_page(mtd, NFC_OUTPUT);
 
-memcpy_fromio(host-&amp;gt;data_buf, host-&amp;gt;main_area0, mtd-&amp;gt;writesize);
+memcpy32_fromio(host-&amp;gt;data_buf, host-&amp;gt;main_area0, mtd-&amp;gt;writesize);
 copy_spare(mtd, true);
 break;
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1086,7 +1106,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 break;
 
 case NAND_CMD_PAGEPROG:
-memcpy_toio(host-&amp;gt;main_area0, host-&amp;gt;data_buf, mtd-&amp;gt;writesize);
+memcpy32_toio(host-&amp;gt;main_area0, host-&amp;gt;data_buf, mtd-&amp;gt;writesize);
 copy_spare(mtd, false);
 host-&amp;gt;devtype_data-&amp;gt;send_page(mtd, NFC_INPUT);
 host-&amp;gt;devtype_data-&amp;gt;send_cmd(host, command, true);
&lt;/pre&gt;</description>
    <dc:creator>Sascha Hauer</dc:creator>
    <dc:date>2012-05-25T14:22:41</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169379">
    <title>Booting mx27 on linux-next</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169379</link>
    <description>&lt;pre&gt;Hi Sascha,

Just tried booting a mx27pdk on linux-next and it failed to boot.

Any patches I am missing?

Just wanted to check with you first prior to start debugging it.

Regards,

Fabio Estevam
&lt;/pre&gt;</description>
    <dc:creator>Fabio Estevam</dc:creator>
    <dc:date>2012-05-25T13:56:07</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169377">
    <title>[PATCH v4 4/6] gpio: introduce lock mechanism for gpiochip_find</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169377</link>
    <description>&lt;pre&gt;From: Dong Aisheng &amp;lt;dong.aisheng&amp;lt; at &amp;gt;linaro.org&amp;gt;

The module lock will be automatically claimed for gpiochip_find function
in case the gpio module is removed during the using of gpiochip instance.
Users are responsible to call gpiochip_put to release the lock after
the using.

Signed-off-by: Dong Aisheng &amp;lt;dong.aisheng&amp;lt; at &amp;gt;linaro.org&amp;gt;
---
 drivers/gpio/gpiolib-of.c  |    5 ++++-
 drivers/gpio/gpiolib.c     |   17 +++++++++++++++++
 include/asm-generic/gpio.h |    2 +-
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index b8010a9..d521452 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -63,6 +63,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int of_get_named_gpio_flags(struct device_node *np, const char *propname,
                            int index, enum of_gpio_flags *flags)
 {
 struct gg_data gg_data = { .flags = flags, .out_gpio = -ENODEV };
+struct gpio_chip *chip;
 int ret;
 
 /* .of_xlate might decide to not fill in the flags, so clear it. */
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -76,7 +77,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int of_get_named_gpio_flags(struct device_node *np, const char *propname,
 return -EINVAL;
 }
 
-gpiochip_find(&amp;amp;gg_data, of_gpiochip_find_and_xlate);
+chip = gpiochip_find(&amp;amp;gg_data, of_gpiochip_find_and_xlate);
+if (chip)
+gpiochip_put(chip);
 
 of_node_put(gg_data.gpiospec.np);
 pr_debug("%s exited with status %d\n", __func__, ret);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 120b2a0..6453d43 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1144,6 +1144,18 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; int gpiochip_remove(struct gpio_chip *chip)
 EXPORT_SYMBOL_GPL(gpiochip_remove);
 
 /**
+ * gpiochip_put() - release a gpio_chip
+ * &amp;lt; at &amp;gt;chip: the chip to release
+ */
+inline void gpiochip_put(struct gpio_chip *chip)
+{
+BUG_ON(!chip);
+
+module_put(chip-&amp;gt;owner);
+}
+EXPORT_SYMBOL_GPL(gpiochip_put);
+
+/**
  * gpiochip_find() - iterator for locating a specific gpio_chip
  * &amp;lt; at &amp;gt;data: data to pass to match function
  * &amp;lt; at &amp;gt;callback: Callback function to check gpio_chip
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1153,6 +1165,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; EXPORT_SYMBOL_GPL(gpiochip_remove);
  * 0 if the device doesn't match and non-zero if it does.  If the callback is
  * non-zero, this function will return to the caller and not iterate over any
  * more gpio_chips.
+ *
+ * Note the gpio_chip is returned with the module locked, users are responsible
+ * to release the lock with gpiochip_put(chip) after using it.
  */
 struct gpio_chip *gpiochip_find(void *data,
 int (*match)(struct gpio_chip *chip,
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -1169,6 +1184,8 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; struct gpio_chip *gpiochip_find(void *data,
 
 if (match(gpio_desc[i].chip, data)) {
 chip = gpio_desc[i].chip;
+if (!try_module_get(chip-&amp;gt;owner))
+chip = NULL;
 break;
 }
 }
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 365ea09..af372be 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -145,7 +145,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; extern int __must_check gpiochip_remove(struct gpio_chip *chip);
 extern struct gpio_chip *gpiochip_find(void *data,
 int (*match)(struct gpio_chip *chip,
      void *data));
-
+extern void gpiochip_put(struct gpio_chip *chip);
 
 /* Always use the library code for GPIO management calls,
  * or when sleeping may be involved.
&lt;/pre&gt;</description>
    <dc:creator>Dong Aisheng</dc:creator>
    <dc:date>2012-05-25T13:36:18</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169371">
    <title>[PATCH] ARM: at91: aic can use fast eoi handler type</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169371</link>
    <description>&lt;pre&gt;From: Ludovic Desroches &amp;lt;ludovic.desroches&amp;lt; at &amp;gt;atmel.com&amp;gt;

The Advanced Interrupt Controller allows to use the fast EOI handler type.
It lets remove the Atmel specific workaround into arch/arm/kernel/irq.c used
to indicate to the AIC the end of the interrupt treatment.

Signed-off-by: Ludovic Desroches &amp;lt;ludovic.desroches&amp;lt; at &amp;gt;atmel.com&amp;gt;
---
 arch/arm/kernel/irq.c                  |    3 ---
 arch/arm/mach-at91/gpio.c              |   10 ++++++++--
 arch/arm/mach-at91/include/mach/irqs.h |    7 -------
 arch/arm/mach-at91/irq.c               |   10 ++++++++--
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 71ccdbf..6236d1a 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -85,9 +85,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void handle_IRQ(unsigned int irq, struct pt_regs *regs)
 generic_handle_irq(irq);
 }
 
-/* AT91 specific workaround */
-irq_finish(irq);
-
 irq_exit();
 set_irq_regs(old_regs);
 }
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index 325837a..ee38e6d 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -520,6 +520,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void gpio_irq_unmask(struct irq_data *d)
 __raw_writel(mask, pio + PIO_IER);
 }
 
+static void gpio_irq_eoi(struct irq_data *d)
+{
+at91_aic_write(AT91_AIC_EOICR, 0);
+}
+
 static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
 switch (type) {
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -581,6 +586,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct irq_chip gpio_irqchip = {
 .irq_unmask= gpio_irq_unmask,
 /* .irq_set_type is set dynamically */
 .irq_set_wake= gpio_irq_set_wake,
+.irq_eoi= gpio_irq_eoi,
 };
 
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -725,7 +731,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int at91_gpio_irq_map(struct irq_domain *h, unsigned int virq,
  * shorter, and the AIC handles interrupts sanely.
  */
 irq_set_chip_and_handler(virq, &amp;amp;gpio_irqchip,
- handle_simple_irq);
+ handle_fasteoi_irq);
 set_irq_flags(virq, IRQF_VALID);
 irq_set_chip_data(virq, at91_gpio);
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -839,7 +845,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void __init at91_gpio_irq_setup(void)
  * shorter, and the AIC handles interrupts sanely.
  */
 irq_set_chip_and_handler(virq, &amp;amp;gpio_irqchip,
- handle_simple_irq);
+ handle_fasteoi_irq);
 set_irq_flags(virq, IRQF_VALID);
 irq_set_chip_data(virq, this);
 
diff --git a/arch/arm/mach-at91/include/mach/irqs.h b/arch/arm/mach-at91/include/mach/irqs.h
index ac8b7df..2d510ee 100644
--- a/arch/arm/mach-at91/include/mach/irqs.h
+++ b/arch/arm/mach-at91/include/mach/irqs.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -28,13 +28,6 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 
 
 /*
- * Acknowledge interrupt with AIC after interrupt has been handled.
- *   (by kernel/irq.c)
- */
-#define irq_finish(irq) do { at91_aic_write(AT91_AIC_EOICR, 0); } while (0)
-
-
-/*
  * IRQ interrupt symbols are the AT91xxx_ID_* symbols
  * for IRQs handled directly through the AIC, or else the AT91_PIN_*
  * symbols in gpio.h for ones handled indirectly as GPIOs.
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
index 601b4ee..40714f1 100644
--- a/arch/arm/mach-at91/irq.c
+++ b/arch/arm/mach-at91/irq.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -55,6 +55,11 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static void at91_aic_unmask_irq(struct irq_data *d)
 at91_aic_write(AT91_AIC_IECR, 1 &amp;lt;&amp;lt; d-&amp;gt;hwirq);
 }
 
+static void at91_aic_eoi(struct irq_data *d)
+{
+at91_aic_write(AT91_AIC_EOICR, 0);
+}
+
 unsigned int at91_extern_irq;
 
 #define is_extern_irq(hwirq) ((1 &amp;lt;&amp;lt; (hwirq)) &amp;amp; at91_extern_irq)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -133,6 +138,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct irq_chip at91_aic_chip = {
 .irq_unmask= at91_aic_unmask_irq,
 .irq_set_type= at91_aic_set_type,
 .irq_set_wake= at91_aic_set_wake,
+.irq_eoi= at91_aic_eoi,
 };
 
 static void __init at91_aic_hw_init(unsigned int spu_vector)
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -171,7 +177,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
 /* Active Low interrupt, without priority */
 at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW);
 
-irq_set_chip_and_handler(virq, &amp;amp;at91_aic_chip, handle_level_irq);
+irq_set_chip_and_handler(virq, &amp;amp;at91_aic_chip, handle_fasteoi_irq);
 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
 
 return 0;
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -271,7 +277,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
 /* Active Low interrupt, with the specified priority */
 at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
 
-irq_set_chip_and_handler(i, &amp;amp;at91_aic_chip, handle_level_irq);
+irq_set_chip_and_handler(i, &amp;amp;at91_aic_chip, handle_fasteoi_irq);
 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 }
 
&lt;/pre&gt;</description>
    <dc:creator>ludovic.desroches&lt; at &gt;atmel.com</dc:creator>
    <dc:date>2012-05-25T12:55:11</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169359">
    <title>Re: [RFC PATCH 00/11] OMAP System Control Module</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169359</link>
    <description>&lt;pre&gt;  Hi.

On 05/25/2012 12:25 PM, Eduardo Valentin wrote:
In my latest version I got rid from early API set, check out patch for V3 patch set.
I'll attach patch for current version later.

BR,
    Konstantin Baydarov.

&lt;/pre&gt;</description>
    <dc:creator>Konstantin Baydarov</dc:creator>
    <dc:date>2012-05-25T10:50:15</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169357">
    <title>[PATCH 2/3] OMAP: avoid build wdt platform device if with dt support</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169357</link>
    <description>&lt;pre&gt;From: Xiao Jiang &amp;lt;jgq516&amp;lt; at &amp;gt;gmail.com&amp;gt;

If provided dt support, then skip add wdt platform device as usual.

Signed-off-by: Xiao Jiang &amp;lt;jgq516&amp;lt; at &amp;gt;gmail.com&amp;gt;
---
 arch/arm/mach-omap2/devices.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index ae62ece..80d7e3f 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -759,7 +759,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static int __init omap_init_wdt(void)
 char *oh_name = "wd_timer2";
 char *dev_name = "omap_wdt";
 
-if (!cpu_class_is_omap2())
+if (!cpu_class_is_omap2() || of_have_populated_dt())
 return 0;
 
 oh = omap_hwmod_lookup(oh_name);
&lt;/pre&gt;</description>
    <dc:creator>jgq516&lt; at &gt;gmail.com</dc:creator>
    <dc:date>2012-05-25T10:42:31</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169352">
    <title>[PATCH 2/2] clk: mxs: rename the gpmi clock for imx28</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169352</link>
    <description>&lt;pre&gt;rename the clock name from `8000c000.gpmi` to `8000c000.gpmi-nand`.

Signed-off-by: Huang Shijie &amp;lt;b32955&amp;lt; at &amp;gt;freescale.com&amp;gt;
---
 drivers/clk/mxs/clk-imx28.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 2826a26..003b0f3 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -174,7 +174,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; static struct clk_lookup lcdif_lookups[] __initdata = {
 
 static struct clk_lookup gpmi_lookups[] __initdata = {
 { .dev_id = "imx28-gpmi-nand", },
-{ .dev_id = "8000c000.gpmi", },
+{ .dev_id = "8000c000.gpmi-nand", },
 };
 
 static struct clk_lookup fec_lookups[] __initdata = {
&lt;/pre&gt;</description>
    <dc:creator>Huang Shijie</dc:creator>
    <dc:date>2012-05-25T09:25:36</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169351">
    <title>[PATCH 1/2] ARM: mx28: add gpmi-nand support</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169351</link>
    <description>&lt;pre&gt;add gpmi-nand device tree support.
add gpmi-nand pinctrl support.

Also enable the gpmi support for mx28-evk board.

Signed-off-by: Huang Shijie &amp;lt;b32955&amp;lt; at &amp;gt;freescale.com&amp;gt;
---

add pinctrl for gpmi-nand.

---
 arch/arm/boot/dts/imx28-evk.dts |    6 ++++++
 arch/arm/boot/dts/imx28.dtsi    |   35 ++++++++++++++++++++++++++---------
 2 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index ee520a5..e53cf67 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -22,6 +22,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 
 apb&amp;lt; at &amp;gt;80000000 {
 apbh&amp;lt; at &amp;gt;80000000 {
+gpmi-nand&amp;lt; at &amp;gt;8000c000 {
+pinctrl-names = "default";
+pinctrl-0 = &amp;lt;&amp;amp;gpmi_pins_a &amp;amp;gpmi_status_cfg&amp;gt;;
+status = "okay";
+};
+
 ssp0: ssp&amp;lt; at &amp;gt;80010000 {
 compatible = "fsl,imx28-mmc";
 pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 4634cb8..2636339 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -68,15 +68,15 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 status = "disabled";
 };
 
-bch&amp;lt; at &amp;gt;8000a000 {
-reg = &amp;lt;0x8000a000 2000&amp;gt;;
-interrupts = &amp;lt;41&amp;gt;;
-status = "disabled";
-};
-
-gpmi&amp;lt; at &amp;gt;8000c000 {
-reg = &amp;lt;0x8000c000 2000&amp;gt;;
-interrupts = &amp;lt;42 88&amp;gt;;
+gpmi-nand&amp;lt; at &amp;gt;8000c000 {
+compatible = "fsl,imx28-gpmi-nand";
+#address-cells = &amp;lt;1&amp;gt;;
+#size-cells = &amp;lt;1&amp;gt;;
+reg = &amp;lt;0x8000c000 2000&amp;gt;, &amp;lt;0x8000a000 2000&amp;gt;;
+reg-names = "gpmi-nand", "bch";
+interrupts = &amp;lt;88&amp;gt;, &amp;lt;41&amp;gt;;
+interrupt-names = "gpmi-dma", "bch";
+fsl,gpmi-dma-channel = &amp;lt;4&amp;gt;;
 status = "disabled";
 };
 
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -167,6 +167,23 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
 fsl,pull-up = &amp;lt;0&amp;gt;;
 };
 
+gpmi_pins_a: gpmi-nand&amp;lt; at &amp;gt;0 {
+reg = &amp;lt;0&amp;gt;;
+fsl,pinmux-ids = &amp;lt;0x0000 0x0010 0x0020
+0x0030 0x0040 0x0050 0x0060
+0x0070 0x0100 0x0110 0x0140
+0x0150 0x0180 0x0190 0x01a0
+0x01b0 0x01c0 &amp;gt;;
+fsl,drive-strength = &amp;lt;0&amp;gt;;
+fsl,voltage = &amp;lt;1&amp;gt;;
+fsl,pull-up = &amp;lt;0&amp;gt;;
+};
+
+gpmi_status_cfg: gpmi-status-cfg {
+fsl,pinmux-ids = &amp;lt;0x0180 0x0190 0x01c0&amp;gt;;
+fsl,drive-strength = &amp;lt;2&amp;gt;;
+};
+
 mac0_pins_a: mac0&amp;lt; at &amp;gt;0 {
 reg = &amp;lt;0&amp;gt;;
 fsl,pinmux-ids = &amp;lt;0x4000 0x4010 0x4020
&lt;/pre&gt;</description>
    <dc:creator>Huang Shijie</dc:creator>
    <dc:date>2012-05-25T09:25:35</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169345">
    <title>Re: [PATCH] lib/decompress_unxz.c: removing all memory helper functions</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169345</link>
    <description>&lt;pre&gt;
Is it best to copy these functions to each arch, or would it be better
to have a shared file from which these functions could be pulled for
multiple archs? I wasn't sure when I wrote decompress_unxz.c, which is
why I put the extra functions there as a temporary solution.


These already have memcpy. It can save a few bytes if one reused
memmove as memcpy when using XZ compression. I got a difference of 48
bytes on x86_64.

Adding memmove to string.c on x86 means that memmove is included in the
kernel image even when memmove isn't needed. With gzip compression I
got 128 bytes bigger image on x86_64 after adding the unneeded memmove
to string.c.

I don't know if those size increases matter in practice.


s/XZ-decompressed/XZ-compressed/ :-)

&lt;/pre&gt;</description>
    <dc:creator>Lasse Collin</dc:creator>
    <dc:date>2012-05-25T08:34:32</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169327">
    <title>[PATCH 4/4] ASoC: add mmp brownstone support</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169327</link>
    <description>&lt;pre&gt;Adds Alsa audio platform driver for mmp brownstone machine

Signed-off-by: Zhangfei Gao &amp;lt;zhangfei.gao&amp;lt; at &amp;gt;marvell.com&amp;gt;
Signed-off-by: Leo Yan &amp;lt;leoy&amp;lt; at &amp;gt;marvell.com&amp;gt;
---
 sound/soc/pxa/Kconfig      |    9 ++
 sound/soc/pxa/Makefile     |    2 +
 sound/soc/pxa/brownstone.c |  303 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 314 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/pxa/brownstone.c

diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 39461ba..b5fa91f 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -205,3 +205,12 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; config SND_PXA2XX_SOC_IMOTE2
        help
          Say Y if you want to add support for SoC audio on the
  IMote 2.
+
+config SND_MMP_SOC_BROWNSTONE
+tristate "SoC Audio support for Marvell Brownstone"
+depends on SND_MMP_SOC &amp;amp;&amp;amp; MACH_BROWNSTONE
+select SND_MMP_SOC_SSPA
+select SND_SOC_WM8994
+help
+  Say Y if you want to add support for SoC audio on the
+  Marvell Brownstone reference platform.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 07b8417..c12aa2a 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -32,6 +32,7 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; snd-soc-mioa701-objs := mioa701_wm9713.o
 snd-soc-z2-objs := z2.o
 snd-soc-imote2-objs := imote2.o
 snd-soc-raumfeld-objs := raumfeld.o
+snd-soc-brownstone-objs := brownstone.o
 
 obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
 obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -51,3 +52,4 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o
 obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
 obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
 obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o
+obj-$(CONFIG_SND_MMP_SOC_BROWNSTONE) += snd-soc-brownstone.o
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
new file mode 100644
index 0000000..b024e58
--- /dev/null
+++ b/sound/soc/pxa/brownstone.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,303 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * linux/sound/soc/pxa/brownstone.c
+ *
+ * Copyright (C) 2011 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/moduleparam.h&amp;gt;
+#include &amp;lt;linux/timer.h&amp;gt;
+#include &amp;lt;linux/interrupt.h&amp;gt;
+#include &amp;lt;linux/platform_device.h&amp;gt;
+#include &amp;lt;linux/fs.h&amp;gt;
+#include &amp;lt;linux/proc_fs.h&amp;gt;
+#include &amp;lt;linux/delay.h&amp;gt;
+#include &amp;lt;linux/suspend.h&amp;gt;
+#include &amp;lt;linux/i2c.h&amp;gt;
+#include &amp;lt;linux/clk.h&amp;gt;
+#include &amp;lt;linux/io.h&amp;gt;
+#include &amp;lt;linux/uaccess.h&amp;gt;
+#include &amp;lt;linux/mfd/wm8994/registers.h&amp;gt;
+#include &amp;lt;sound/core.h&amp;gt;
+#include &amp;lt;sound/pcm.h&amp;gt;
+#include &amp;lt;sound/soc.h&amp;gt;
+#include &amp;lt;sound/jack.h&amp;gt;
+#include &amp;lt;sound/soc-dapm.h&amp;gt;
+#include &amp;lt;asm/mach-types.h&amp;gt;
+
+#include "../codecs/wm8994.h"
+#include "mmp-sspa.h"
+
+#define BROWNSTONE_HP        0
+#define BROWNSTONE_MIC       1
+#define BROWNSTONE_HEADSET   2
+#define BROWNSTONE_HP_OFF    3
+#define BROWNSTONE_SPK_ON    0
+#define BROWNSTONE_SPK_OFF   1
+
+static struct snd_soc_card brownstone;
+static int brownstone_jack_func;
+static int brownstone_spk_func;
+
+static void brownstone_ext_control(struct snd_soc_dapm_context *dapm)
+{
+if (brownstone_spk_func == BROWNSTONE_SPK_ON) {
+snd_soc_dapm_enable_pin(dapm, "Ext Left Spk");
+snd_soc_dapm_enable_pin(dapm, "Ext Right Spk");
+} else {
+snd_soc_dapm_disable_pin(dapm, "Ext Left Spk");
+snd_soc_dapm_disable_pin(dapm, "Ext Right Spk");
+}
+
+/* set up jack connection */
+switch (brownstone_jack_func) {
+case BROWNSTONE_HP:
+snd_soc_dapm_disable_pin(dapm, "Headset Mic");
+snd_soc_dapm_enable_pin(dapm, "Main Mic");
+snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
+break;
+case BROWNSTONE_MIC:
+snd_soc_dapm_disable_pin(dapm, "Headset Mic");
+snd_soc_dapm_enable_pin(dapm, "Main Mic");
+snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
+break;
+case BROWNSTONE_HEADSET:
+snd_soc_dapm_enable_pin(dapm, "Headset Mic");
+snd_soc_dapm_disable_pin(dapm, "Main Mic");
+snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
+break;
+case BROWNSTONE_HP_OFF:
+snd_soc_dapm_disable_pin(dapm, "Headset Mic");
+snd_soc_dapm_disable_pin(dapm, "Main Mic");
+snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
+break;
+}
+snd_soc_dapm_sync(dapm);
+return;
+}
+
+static int brownstone_get_jack(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+ucontrol-&amp;gt;value.integer.value[0] = brownstone_jack_func;
+return 0;
+}
+
+static int brownstone_set_jack(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+
+if (brownstone_jack_func == ucontrol-&amp;gt;value.integer.value[0])
+return 0;
+
+brownstone_jack_func = ucontrol-&amp;gt;value.integer.value[0];
+brownstone_ext_control(&amp;amp;card-&amp;gt;dapm);
+return 1;
+}
+
+static int brownstone_get_spk(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+ucontrol-&amp;gt;value.integer.value[0] = brownstone_spk_func;
+return 0;
+}
+
+static int brownstone_set_spk(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
+
+if (brownstone_spk_func == ucontrol-&amp;gt;value.integer.value[0])
+return 0;
+
+brownstone_spk_func = ucontrol-&amp;gt;value.integer.value[0];
+brownstone_ext_control(&amp;amp;card-&amp;gt;dapm);
+return 1;
+}
+
+static const struct snd_soc_dapm_widget brownstone_dapm_widgets[] = {
+SND_SOC_DAPM_SPK("Ext Left Spk", NULL),
+SND_SOC_DAPM_SPK("Ext Right Spk", NULL),
+SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+SND_SOC_DAPM_MIC("Headset Mic", NULL),
+SND_SOC_DAPM_MIC("Main Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route brownstone_audio_map[] = {
+{"Ext Left Spk", NULL, "SPKOUTLP"},
+{"Ext Left Spk", NULL, "SPKOUTLN"},
+
+{"Ext Right Spk", NULL, "SPKOUTRP"},
+{"Ext Right Spk", NULL, "SPKOUTRN"},
+
+{"Headset Stereophone", NULL, "HPOUT1L"},
+{"Headset Stereophone", NULL, "HPOUT1R"},
+
+{"IN1RN", NULL, "Headset Mic"},
+
+{"DMIC1DAT", NULL, "MICBIAS1"},
+{"MICBIAS1", NULL, "Main Mic"},
+};
+
+static const char *jack_function[] = {"Headphone", "Mic", "Headset", "Off"};
+static const char *spk_function[]  = {"On", "Off"};
+static const struct soc_enum brownstone_enum[] = {
+SOC_ENUM_SINGLE_EXT(4, jack_function),
+SOC_ENUM_SINGLE_EXT(2, spk_function),
+};
+
+static const struct snd_kcontrol_new brownstone_wm8994_controls[] = {
+SOC_ENUM_EXT("Jack Function", brownstone_enum[0],
+     brownstone_get_jack, brownstone_set_jack),
+SOC_ENUM_EXT("Speaker Function", brownstone_enum[1],
+     brownstone_get_spk, brownstone_set_spk),
+};
+
+static int brownstone_wm8994_init(struct snd_soc_pcm_runtime *rtd)
+{
+struct snd_soc_codec *codec = rtd-&amp;gt;codec;
+struct snd_soc_dapm_context *dapm = &amp;amp;codec-&amp;gt;dapm;
+
+brownstone_jack_func = BROWNSTONE_MIC;
+brownstone_spk_func  = BROWNSTONE_SPK_ON;
+
+snd_soc_dapm_enable_pin(dapm, "Ext Left Spk");
+snd_soc_dapm_enable_pin(dapm, "Ext Right Spk");
+snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
+snd_soc_dapm_enable_pin(dapm, "Headset Mic");
+snd_soc_dapm_enable_pin(dapm, "Main Mic");
+
+/* set endpoints to not connected */
+snd_soc_dapm_nc_pin(dapm, "HPOUT2P");
+snd_soc_dapm_nc_pin(dapm, "HPOUT2N");
+snd_soc_dapm_nc_pin(dapm, "LINEOUT1N");
+snd_soc_dapm_nc_pin(dapm, "LINEOUT1P");
+snd_soc_dapm_nc_pin(dapm, "LINEOUT2N");
+snd_soc_dapm_nc_pin(dapm, "LINEOUT2P");
+snd_soc_dapm_nc_pin(dapm, "IN1LN");
+snd_soc_dapm_nc_pin(dapm, "IN1LP");
+snd_soc_dapm_nc_pin(dapm, "IN1RP");
+snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
+snd_soc_dapm_nc_pin(dapm, "IN2RN");
+snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
+snd_soc_dapm_nc_pin(dapm, "IN2LN");
+
+snd_soc_dapm_sync(dapm);
+
+/* turn on micbias 1/2 always */
+snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+    WM8994_MICB1_ENA_MASK |
+    WM8994_MICB2_ENA_MASK,
+    WM8994_MICB1_ENA |
+    WM8994_MICB2_ENA);
+return 0;
+}
+
+static int brownstone_wm8994_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+struct snd_soc_pcm_runtime *rtd = substream-&amp;gt;private_data;
+struct snd_soc_dai *codec_dai = rtd-&amp;gt;codec_dai;
+struct snd_soc_dai *cpu_dai = rtd-&amp;gt;cpu_dai;
+int freq_out, sspa_mclk, sysclk;
+int sspa_div;
+
+if (params_rate(params) &amp;gt; 11025) {
+freq_out  = params_rate(params) * 512;
+sysclk    = params_rate(params) * 256;
+sspa_mclk = params_rate(params) * 64;
+} else {
+freq_out  = params_rate(params) * 1024;
+sysclk    = params_rate(params) * 512;
+sspa_mclk = params_rate(params) * 64;
+}
+sspa_div = freq_out;
+do_div(sspa_div, sspa_mclk);
+
+snd_soc_dai_set_sysclk(cpu_dai, MMP_SSPA_CLK_AUDIO, freq_out, 0);
+snd_soc_dai_set_pll(cpu_dai, MMP_SYSCLK, 0, freq_out, sysclk);
+snd_soc_dai_set_pll(cpu_dai, MMP_SSPA_CLK, 0, freq_out, sspa_mclk);
+
+/* set wm8994 sysclk */
+snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, sysclk, 0);
+
+snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+
+snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+
+return 0;
+}
+
+/* machine stream operations */
+static struct snd_soc_ops brownstone_ops = {
+.hw_params = brownstone_wm8994_hw_params,
+};
+
+static struct snd_soc_dai_link brownstone_wm8994_dai[] = {
+{
+.name= "WM8994",
+.stream_name= "WM8994 HiFi",
+.cpu_dai_name= "mmp-sspa-dai.0",
+.codec_dai_name= "wm8994-aif1",
+.platform_name= "mmp-pcm-audio",
+.codec_name= "wm8994-codec",
+.ops= &amp;amp;brownstone_ops,
+.init= brownstone_wm8994_init,
+},
+};
+
+/* audio machine driver */
+static struct snd_soc_card brownstone = {
+.name         = "brownstone",
+.dai_link     = brownstone_wm8994_dai,
+.num_links    = ARRAY_SIZE(brownstone_wm8994_dai),
+
+.controls = brownstone_wm8994_controls,
+.num_controls = ARRAY_SIZE(brownstone_wm8994_controls),
+.dapm_widgets = brownstone_dapm_widgets,
+.num_dapm_widgets = ARRAY_SIZE(brownstone_dapm_widgets),
+.dapm_routes = brownstone_audio_map,
+.num_dapm_routes = ARRAY_SIZE(brownstone_audio_map),
+};
+
+static int __devinit brownstone_probe(struct platform_device *pdev)
+{
+int ret;
+
+brownstone.dev = &amp;amp;pdev-&amp;gt;dev;
+ret = snd_soc_register_card(&amp;amp;brownstone);
+if (ret)
+dev_err(&amp;amp;pdev-&amp;gt;dev, "snd_soc_register_card() failed: %d\n",
+ret);
+return ret;
+}
+
+static int __devexit brownstone_remove(struct platform_device *pdev)
+{
+snd_soc_unregister_card(&amp;amp;brownstone);
+return 0;
+}
+
+static struct platform_driver mmp_driver = {
+.driver= {
+.name= "mmp-audio",
+.owner= THIS_MODULE,
+},
+.probe= brownstone_probe,
+.remove= __devexit_p(brownstone_remove),
+};
+
+module_platform_driver(mmp_driver);
+
+MODULE_AUTHOR("Leo Yan &amp;lt;leoy&amp;lt; at &amp;gt;marvell.com&amp;gt;");
+MODULE_DESCRIPTION("ALSA SoC Brownstone");
+MODULE_LICENSE("GPL");
&lt;/pre&gt;</description>
    <dc:creator>Zhangfei Gao</dc:creator>
    <dc:date>2012-05-25T07:11:03</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169326">
    <title>[PATCH 3/4] ASOC: mmp: add sspa support</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169326</link>
    <description>&lt;pre&gt;The SSPA is a configurable multi-channel audio serial (TDM) interface.
It's configurable at runtime to support up to 128 channels and the
number of bits per sample: 8, 12, 16, 20, 24 and 32 bits. It also
support stereo format: I2S, left-justified or right-justified.

Signed-off-by: Zhangfei Gao &amp;lt;zhangfei.gao&amp;lt; at &amp;gt;marvell.com&amp;gt;
Signed-off-by: Leo Yan &amp;lt;leoy&amp;lt; at &amp;gt;marvell.com&amp;gt;
---
 sound/soc/pxa/Kconfig    |    3 +
 sound/soc/pxa/Makefile   |    2 +
 sound/soc/pxa/mmp-sspa.c |  536 ++++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/pxa/mmp-sspa.h |   92 ++++++++
 4 files changed, 633 insertions(+), 0 deletions(-)
 create mode 100644 sound/soc/pxa/mmp-sspa.c
 create mode 100644 sound/soc/pxa/mmp-sspa.h

diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index a516068..39461ba 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -34,6 +34,9 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; config SND_PXA_SOC_SSP
 tristate
 select PXA_SSP
 
+config SND_MMP_SOC_SSPA
+tristate
+
 config SND_PXA2XX_SOC_CORGI
 tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
 depends on SND_PXA2XX_SOC &amp;amp;&amp;amp; PXA_SHARP_C7xx
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index f913e9b..07b8417 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -4,12 +4,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
 snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
 snd-soc-pxa-ssp-objs := pxa-ssp.o
 snd-soc-mmp-objs := mmp-pcm.o
+snd-soc-mmp-sspa-objs := mmp-sspa.o
 
 obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
 obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
 obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
 obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
 obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o
+obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o
 
 # PXA Machine Support
 snd-soc-corgi-objs := corgi.o
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
new file mode 100644
index 0000000..b78bf1e
--- /dev/null
+++ b/sound/soc/pxa/mmp-sspa.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,536 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * linux/sound/soc/pxa/mmp-sspa.c
+ * Base on pxa2xx-ssp.c
+ *
+ * Copyright (C) 2011 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include &amp;lt;linux/init.h&amp;gt;
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/platform_device.h&amp;gt;
+#include &amp;lt;linux/delay.h&amp;gt;
+#include &amp;lt;linux/clk.h&amp;gt;
+#include &amp;lt;linux/slab.h&amp;gt;
+#include &amp;lt;linux/pxa2xx_ssp.h&amp;gt;
+#include &amp;lt;linux/io.h&amp;gt;
+#include &amp;lt;sound/core.h&amp;gt;
+#include &amp;lt;sound/pcm.h&amp;gt;
+#include &amp;lt;sound/initval.h&amp;gt;
+#include &amp;lt;sound/pcm_params.h&amp;gt;
+#include &amp;lt;sound/soc.h&amp;gt;
+#include &amp;lt;sound/pxa2xx-lib.h&amp;gt;
+#include "mmp-sspa.h"
+
+/*
+ * SSPA audio private data
+ */
+struct sspa_priv {
+struct ssp_device *sspa;
+struct pxa2xx_pcm_dma_params *dma_params;
+int dai_fmt;
+int running_cnt;
+};
+
+static struct clk *audio_clk;
+static struct clk *sysclk;
+
+static void mmp_sspa_write_reg(struct ssp_device *sspa, u32 reg, u32 val)
+{
+__raw_writel(val, sspa-&amp;gt;mmio_base + reg);
+}
+
+static u32 mmp_sspa_read_reg(struct ssp_device *sspa, u32 reg)
+{
+return __raw_readl(sspa-&amp;gt;mmio_base + reg);
+}
+
+static void mmp_sspa_tx_enable(struct ssp_device *sspa)
+{
+unsigned int sspa_sp;
+
+sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP);
+sspa_sp |= SSPA_SP_S_EN;
+sspa_sp |= SSPA_SP_WEN;
+mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
+}
+
+static void mmp_sspa_tx_disable(struct ssp_device *sspa)
+{
+unsigned int sspa_sp;
+
+sspa_sp = mmp_sspa_read_reg(sspa, SSPA_TXSP);
+sspa_sp &amp;amp;= ~SSPA_SP_S_EN;
+sspa_sp |= SSPA_SP_WEN;
+mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
+}
+
+static void mmp_sspa_rx_enable(struct ssp_device *sspa)
+{
+unsigned int sspa_sp;
+
+sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP);
+sspa_sp |= SSPA_SP_S_EN;
+sspa_sp |= SSPA_SP_WEN;
+mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
+}
+
+static void mmp_sspa_rx_disable(struct ssp_device *sspa)
+{
+unsigned int sspa_sp;
+
+sspa_sp = mmp_sspa_read_reg(sspa, SSPA_RXSP);
+sspa_sp &amp;amp;= ~SSPA_SP_S_EN;
+sspa_sp |= SSPA_SP_WEN;
+mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
+}
+
+static int mmp_sspa_startup(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+struct snd_soc_pcm_runtime *rtd = substream-&amp;gt;private_data;
+struct snd_soc_dai *cpu_dai = rtd-&amp;gt;cpu_dai;
+struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
+struct ssp_device *sspa = sspa_priv-&amp;gt;sspa;
+int ret = 0;
+
+if (!cpu_dai-&amp;gt;active) {
+clk_enable(sysclk);
+clk_enable(sspa-&amp;gt;clk);
+}
+
+return ret;
+}
+
+static void mmp_sspa_shutdown(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+struct snd_soc_pcm_runtime *rtd = substream-&amp;gt;private_data;
+struct snd_soc_dai *cpu_dai = rtd-&amp;gt;cpu_dai;
+struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai);
+struct ssp_device *sspa = sspa_priv-&amp;gt;sspa;
+
+if (!cpu_dai-&amp;gt;active) {
+clk_disable(sspa-&amp;gt;clk);
+clk_disable(sysclk);
+}
+
+return;
+}
+
+/*
+ * Set the SSP ports SYSCLK.
+ */
+static int mmp_sspa_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+    int clk_id, unsigned int freq, int dir)
+{
+int ret = 0;
+
+switch (clk_id) {
+case MMP_SSPA_CLK_AUDIO:
+ret = clk_set_rate(audio_clk, freq);
+if (ret)
+return ret;
+break;
+case MMP_SSPA_CLK_PLL:
+case MMP_SSPA_CLK_VCXO:
+/* not support yet */
+return -EINVAL;
+default:
+return -EINVAL;
+}
+
+return 0;
+}
+
+static int mmp_sspa_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
+ int source, unsigned int freq_in,
+ unsigned int freq_out)
+{
+struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai);
+struct ssp_device *sspa = sspa_priv-&amp;gt;sspa;
+
+switch (pll_id) {
+case MMP_SYSCLK:
+clk_set_rate(sysclk, freq_out);
+break;
+case MMP_SSPA_CLK:
+clk_set_rate(sspa-&amp;gt;clk, freq_out);
+break;
+default:
+return -ENODEV;
+}
+
+return 0;
+}
+
+/*
+ * Set up the sspa dai format. The sspa port must be inactive
+ * before calling this function as the physical
+ * interface format is changed.
+ */
+static int mmp_sspa_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(cpu_dai);
+struct ssp_device *sspa = sspa_priv-&amp;gt;sspa;
+u32 sspa_sp, sspa_ctrl;
+
+/* check if we need to change anything at all */
+if (sspa_priv-&amp;gt;dai_fmt == fmt)
+return 0;
+
+/* we can only change the settings if the port is not in use */
+if ((mmp_sspa_read_reg(sspa, SSPA_TXSP) &amp;amp; SSPA_SP_S_EN) ||
+    (mmp_sspa_read_reg(sspa, SSPA_RXSP) &amp;amp; SSPA_SP_S_EN)) {
+dev_err(&amp;amp;sspa-&amp;gt;pdev-&amp;gt;dev,
+"can't change hardware dai format: stream is in use\n");
+return -EINVAL;
+}
+
+/* reset port settings */
+sspa_sp   = SSPA_SP_WEN | SSPA_SP_S_RST | SSPA_SP_FFLUSH;
+sspa_ctrl = 0;
+
+switch (fmt &amp;amp; SND_SOC_DAIFMT_MASTER_MASK) {
+case SND_SOC_DAIFMT_CBS_CFS:
+sspa_sp |= SSPA_SP_MSL;
+break;
+case SND_SOC_DAIFMT_CBM_CFM:
+break;
+default:
+return -EINVAL;
+}
+
+switch (fmt &amp;amp; SND_SOC_DAIFMT_INV_MASK) {
+case SND_SOC_DAIFMT_NB_NF:
+sspa_sp |= SSPA_SP_FSP;
+break;
+default:
+return -EINVAL;
+}
+
+switch (fmt &amp;amp; SND_SOC_DAIFMT_FORMAT_MASK) {
+case SND_SOC_DAIFMT_I2S:
+sspa_sp |= SSPA_TXSP_FPER(63);
+sspa_sp |= SSPA_SP_FWID(31);
+sspa_ctrl |= SSPA_CTL_XDATDLY(1);
+break;
+default:
+return -EINVAL;
+}
+
+mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
+mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
+
+sspa_sp &amp;amp;= ~(SSPA_SP_S_RST | SSPA_SP_FFLUSH);
+mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
+mmp_sspa_write_reg(sspa, SSPA_RXSP, sspa_sp);
+
+/*
+ * FIXME: hw issue, for the tx serial port,
+ * can not config the master/slave mode;
+ * so must clean this bit.
+ * The master/slave mode has been set in the
+ * rx port.
+ */
+sspa_sp &amp;amp;= ~SSPA_SP_MSL;
+mmp_sspa_write_reg(sspa, SSPA_TXSP, sspa_sp);
+
+mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl);
+mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl);
+
+/* Since we are configuring the timings for the format by hand
+ * we have to defer some things until hw_params() where we
+ * know parameters like the sample size.
+ */
+sspa_priv-&amp;gt;dai_fmt = fmt;
+return 0;
+}
+
+/*
+ * Set the SSPA audio DMA parameters and sample size.
+ * Can be called multiple times by oss emulation.
+ */
+static int mmp_sspa_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params,
+       struct snd_soc_dai *dai)
+{
+struct snd_soc_pcm_runtime *rtd = substream-&amp;gt;private_data;
+struct snd_soc_dai *cpu_dai = rtd-&amp;gt;cpu_dai;
+struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
+struct ssp_device *sspa = sspa_priv-&amp;gt;sspa;
+struct pxa2xx_pcm_dma_params *dma_params;
+u32 sspa_ctrl;
+
+if (substream-&amp;gt;stream == SNDRV_PCM_STREAM_PLAYBACK)
+sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_TXCTL);
+else
+sspa_ctrl = mmp_sspa_read_reg(sspa, SSPA_RXCTL);
+
+sspa_ctrl &amp;amp;= ~SSPA_CTL_XFRLEN1_MASK;
+sspa_ctrl |= SSPA_CTL_XFRLEN1(params_channels(params) - 1);
+sspa_ctrl &amp;amp;= ~SSPA_CTL_XWDLEN1_MASK;
+sspa_ctrl |= SSPA_CTL_XWDLEN1(SSPA_CTL_32_BITS);
+sspa_ctrl &amp;amp;= ~SSPA_CTL_XSSZ1_MASK;
+
+switch (params_format(params)) {
+case SNDRV_PCM_FORMAT_S8:
+sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_8_BITS);
+break;
+case SNDRV_PCM_FORMAT_S16_LE:
+sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_16_BITS);
+break;
+case SNDRV_PCM_FORMAT_S20_3LE:
+sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_20_BITS);
+break;
+case SNDRV_PCM_FORMAT_S24_3LE:
+sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_24_BITS);
+break;
+case SNDRV_PCM_FORMAT_S32_LE:
+sspa_ctrl |= SSPA_CTL_XSSZ1(SSPA_CTL_32_BITS);
+break;
+default:
+return -EINVAL;
+}
+
+if (substream-&amp;gt;stream == SNDRV_PCM_STREAM_PLAYBACK) {
+mmp_sspa_write_reg(sspa, SSPA_TXCTL, sspa_ctrl);
+mmp_sspa_write_reg(sspa, SSPA_TXFIFO_LL, 0x1);
+} else {
+mmp_sspa_write_reg(sspa, SSPA_RXCTL, sspa_ctrl);
+mmp_sspa_write_reg(sspa, SSPA_RXFIFO_UL, 0x0);
+}
+
+dma_params = &amp;amp;sspa_priv-&amp;gt;dma_params[substream-&amp;gt;stream];
+dma_params-&amp;gt;dev_addr = substream-&amp;gt;stream == SNDRV_PCM_STREAM_PLAYBACK ?
+(sspa-&amp;gt;phys_base + SSPA_TXD) :
+(sspa-&amp;gt;phys_base + SSPA_RXD);
+snd_soc_dai_set_dma_data(cpu_dai, substream, dma_params);
+return 0;
+}
+
+static int mmp_sspa_trigger(struct snd_pcm_substream *substream, int cmd,
+     struct snd_soc_dai *dai)
+{
+struct sspa_priv *sspa_priv = snd_soc_dai_get_drvdata(dai);
+struct ssp_device *sspa = sspa_priv-&amp;gt;sspa;
+int ret = 0;
+
+switch (cmd) {
+case SNDRV_PCM_TRIGGER_START:
+case SNDRV_PCM_TRIGGER_RESUME:
+case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+/*
+ * whatever playback or capture, must enable rx.
+ * this is a hw issue, so need check if rx has been
+ * enabled or not; if has been enabled by another
+ * stream, do not enable again.
+ */
+if (!sspa_priv-&amp;gt;running_cnt)
+mmp_sspa_rx_enable(sspa);
+
+if (substream-&amp;gt;stream == SNDRV_PCM_STREAM_PLAYBACK)
+mmp_sspa_tx_enable(sspa);
+
+sspa_priv-&amp;gt;running_cnt++;
+break;
+
+case SNDRV_PCM_TRIGGER_STOP:
+case SNDRV_PCM_TRIGGER_SUSPEND:
+case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+sspa_priv-&amp;gt;running_cnt--;
+
+if (substream-&amp;gt;stream == SNDRV_PCM_STREAM_PLAYBACK)
+mmp_sspa_tx_disable(sspa);
+
+/* have no capture stream, disable rx port */
+if (!sspa_priv-&amp;gt;running_cnt)
+mmp_sspa_rx_disable(sspa);
+break;
+
+default:
+ret = -EINVAL;
+}
+
+return ret;
+}
+
+static int mmp_sspa_probe(struct snd_soc_dai *dai)
+{
+struct sspa_priv *priv = dev_get_drvdata(dai-&amp;gt;dev);
+
+snd_soc_dai_set_drvdata(dai, priv);
+return 0;
+
+}
+
+#define MMP_SSPA_RATES SNDRV_PCM_RATE_8000_192000
+#define MMP_SSPA_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
+SNDRV_PCM_FMTBIT_S16_LE | \
+SNDRV_PCM_FMTBIT_S24_LE | \
+SNDRV_PCM_FMTBIT_S24_LE | \
+SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops mmp_sspa_dai_ops = {
+.startup= mmp_sspa_startup,
+.shutdown= mmp_sspa_shutdown,
+.trigger= mmp_sspa_trigger,
+.hw_params= mmp_sspa_hw_params,
+.set_sysclk= mmp_sspa_set_dai_sysclk,
+.set_pll= mmp_sspa_set_dai_pll,
+.set_fmt= mmp_sspa_set_dai_fmt,
+};
+
+struct snd_soc_dai_driver mmp_sspa_dai = {
+.probe = mmp_sspa_probe,
+.playback = {
+.channels_min = 1,
+.channels_max = 128,
+.rates = MMP_SSPA_RATES,
+.formats = MMP_SSPA_FORMATS,
+},
+.capture = {
+.channels_min = 1,
+.channels_max = 2,
+.rates = MMP_SSPA_RATES,
+.formats = MMP_SSPA_FORMATS,
+},
+.ops = &amp;amp;mmp_sspa_dai_ops,
+};
+
+static __devinit int asoc_mmp_sspa_probe(struct platform_device *pdev)
+{
+int ret;
+struct sspa_priv *priv;
+struct resource *res;
+
+priv = devm_kzalloc(&amp;amp;pdev-&amp;gt;dev,
+sizeof(struct sspa_priv), GFP_KERNEL);
+if (!priv)
+return -ENOMEM;
+
+priv-&amp;gt;sspa = devm_kzalloc(&amp;amp;pdev-&amp;gt;dev,
+sizeof(struct ssp_device), GFP_KERNEL);
+if (priv-&amp;gt;sspa == NULL) {
+ret = -ENOMEM;
+goto err_priv_sspa;
+}
+
+priv-&amp;gt;dma_params = devm_kzalloc(&amp;amp;pdev-&amp;gt;dev,
+2 * sizeof(struct pxa2xx_pcm_dma_params), GFP_KERNEL);
+if (priv-&amp;gt;dma_params == NULL) {
+ret = -ENOMEM;
+goto err_priv_dma_params;
+}
+
+priv-&amp;gt;sspa-&amp;gt;clk = clk_get(&amp;amp;pdev-&amp;gt;dev, NULL);
+if (IS_ERR(priv-&amp;gt;sspa-&amp;gt;clk)) {
+ret = PTR_ERR(priv-&amp;gt;sspa-&amp;gt;clk);
+goto err_free_clk;
+}
+
+res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+if (res == NULL) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "no memory resource defined\n");
+ret = -ENOMEM;
+goto err_get_res;
+}
+
+res = request_mem_region(res-&amp;gt;start, resource_size(res),
+pdev-&amp;gt;name);
+if (res == NULL) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "failed to request memory resource\n");
+ret = -EBUSY;
+goto err_get_res;
+}
+
+priv-&amp;gt;sspa-&amp;gt;mmio_base = ioremap(res-&amp;gt;start, resource_size(res));
+if (priv-&amp;gt;sspa-&amp;gt;mmio_base == NULL) {
+dev_err(&amp;amp;pdev-&amp;gt;dev, "failed to ioremap() registers\n");
+ret = -ENODEV;
+goto err_free_mem;
+}
+
+priv-&amp;gt;dai_fmt = (unsigned int) -1;
+platform_set_drvdata(pdev, priv);
+return snd_soc_register_dai(&amp;amp;pdev-&amp;gt;dev, &amp;amp;mmp_sspa_dai);
+
+err_free_mem:
+release_mem_region(res-&amp;gt;start, resource_size(res));
+err_get_res:
+clk_put(priv-&amp;gt;sspa-&amp;gt;clk);
+err_free_clk:
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, priv-&amp;gt;dma_params);
+err_priv_dma_params:
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, priv-&amp;gt;sspa);
+err_priv_sspa:
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, priv);
+return ret;
+}
+
+static int __devexit asoc_mmp_sspa_remove(struct platform_device *pdev)
+{
+struct sspa_priv *priv = platform_get_drvdata(pdev);
+struct resource *res;
+
+iounmap(priv-&amp;gt;sspa-&amp;gt;mmio_base);
+res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+release_mem_region(res-&amp;gt;start, resource_size(res));
+snd_soc_unregister_dai(&amp;amp;pdev-&amp;gt;dev);
+clk_put(priv-&amp;gt;sspa-&amp;gt;clk);
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, priv-&amp;gt;dma_params);
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, priv-&amp;gt;sspa);
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, priv);
+return 0;
+}
+
+static struct platform_driver asoc_mmp_sspa_driver = {
+.driver = {
+.name = "mmp-sspa-dai",
+.owner = THIS_MODULE,
+},
+.probe = asoc_mmp_sspa_probe,
+.remove = __devexit_p(asoc_mmp_sspa_remove),
+};
+
+
+static int __init mmp_sspa_modinit(void)
+{
+audio_clk = clk_get(NULL, "mmp-audio");
+if (IS_ERR(audio_clk))
+return PTR_ERR(audio_clk);
+
+sysclk = clk_get(NULL, "mmp-sysclk");
+if (IS_ERR(sysclk))
+return PTR_ERR(sysclk);
+clk_enable(audio_clk);
+return platform_driver_register(&amp;amp;asoc_mmp_sspa_driver);
+}
+module_init(mmp_sspa_modinit);
+
+static void __exit mmp_sspa_exit(void)
+{
+clk_disable(audio_clk);
+clk_put(sysclk);
+clk_put(audio_clk);
+platform_driver_unregister(&amp;amp;asoc_mmp_sspa_driver);
+}
+module_exit(mmp_sspa_exit);
+
+MODULE_AUTHOR("Leo Yan &amp;lt;leoy&amp;lt; at &amp;gt;marvell.com&amp;gt;");
+MODULE_DESCRIPTION("MMP SSPA SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/mmp-sspa.h b/sound/soc/pxa/mmp-sspa.h
new file mode 100644
index 0000000..ea365cb
--- /dev/null
+++ b/sound/soc/pxa/mmp-sspa.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,92 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * linux/sound/soc/pxa/mmp-sspa.h
+ *
+ * Copyright (C) 2011 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef _MMP_SSPA_H
+#define _MMP_SSPA_H
+
+/*
+ * SSPA Registers
+ */
+#define SSPA_RXD(0x00)
+#define SSPA_RXID(0x04)
+#define SSPA_RXCTL(0x08)
+#define SSPA_RXSP(0x0c)
+#define SSPA_RXFIFO_UL(0x10)
+#define SSPA_RXINT_MASK(0x14)
+#define SSPA_RXC(0x18)
+#define SSPA_RXFIFO_NOFS(0x1c)
+#define SSPA_RXFIFO_SIZE(0x20)
+
+#define SSPA_TXD(0x80)
+#define SSPA_TXID(0x84)
+#define SSPA_TXCTL(0x88)
+#define SSPA_TXSP(0x8c)
+#define SSPA_TXFIFO_LL(0x90)
+#define SSPA_TXINT_MASK(0x94)
+#define SSPA_TXC(0x98)
+#define SSPA_TXFIFO_NOFS(0x9c)
+#define SSPA_TXFIFO_SIZE(0xa0)
+
+/* SSPA Control Register */
+#defineSSPA_CTL_XPH(1 &amp;lt;&amp;lt; 31)/* Read Phase */
+#defineSSPA_CTL_XFIG(1 &amp;lt;&amp;lt; 15)/* Transmit Zeros when FIFO Empty */
+#defineSSPA_CTL_JST(1 &amp;lt;&amp;lt; 3)/* Audio Sample Justification */
+#defineSSPA_CTL_XFRLEN2_MASK(7 &amp;lt;&amp;lt; 24)
+#defineSSPA_CTL_XFRLEN2(x)((x) &amp;lt;&amp;lt; 24)/* Transmit Frame Length in Phase 2 */
+#defineSSPA_CTL_XWDLEN2_MASK(7 &amp;lt;&amp;lt; 21)
+#defineSSPA_CTL_XWDLEN2(x)((x) &amp;lt;&amp;lt; 21)/* Transmit Word Length in Phase 2 */
+#defineSSPA_CTL_XDATDLY(x)((x) &amp;lt;&amp;lt; 19)/* Tansmit Data Delay */
+#defineSSPA_CTL_XSSZ2_MASK(7 &amp;lt;&amp;lt; 16)
+#defineSSPA_CTL_XSSZ2(x)((x) &amp;lt;&amp;lt; 16)/* Transmit Sample Audio Size */
+#defineSSPA_CTL_XFRLEN1_MASK(7 &amp;lt;&amp;lt; 8)
+#defineSSPA_CTL_XFRLEN1(x)((x) &amp;lt;&amp;lt; 8)/* Transmit Frame Length in Phase 1 */
+#defineSSPA_CTL_XWDLEN1_MASK(7 &amp;lt;&amp;lt; 5)
+#defineSSPA_CTL_XWDLEN1(x)((x) &amp;lt;&amp;lt; 5)/* Transmit Word Length in Phase 1 */
+#defineSSPA_CTL_XSSZ1_MASK(7 &amp;lt;&amp;lt; 0)
+#defineSSPA_CTL_XSSZ1(x)((x) &amp;lt;&amp;lt; 0)/* XSSZ1 */
+
+#define SSPA_CTL_8_BITS(0x0)/* Sample Size */
+#define SSPA_CTL_12_BITS(0x1)
+#define SSPA_CTL_16_BITS(0x2)
+#define SSPA_CTL_20_BITS(0x3)
+#define SSPA_CTL_24_BITS(0x4)
+#define SSPA_CTL_32_BITS(0x5)
+
+/* SSPA Serial Port Register */
+#defineSSPA_SP_WEN(1 &amp;lt;&amp;lt; 31)/* Write Configuration Enable */
+#defineSSPA_SP_MSL(1 &amp;lt;&amp;lt; 18)/* Master Slave Configuration */
+#defineSSPA_SP_CLKP(1 &amp;lt;&amp;lt; 17)/* CLKP Polarity Clock Edge Select */
+#defineSSPA_SP_FSP(1 &amp;lt;&amp;lt; 16)/* FSP Polarity Clock Edge Select */
+#defineSSPA_SP_FFLUSH(1 &amp;lt;&amp;lt; 2)/* FIFO Flush */
+#defineSSPA_SP_S_RST(1 &amp;lt;&amp;lt; 1)/* Active High Reset Signal */
+#defineSSPA_SP_S_EN(1 &amp;lt;&amp;lt; 0)/* Serial Clock Domain Enable */
+#defineSSPA_SP_FWID(x)((x) &amp;lt;&amp;lt; 20)/* Frame-Sync Width */
+#defineSSPA_TXSP_FPER(x)((x) &amp;lt;&amp;lt; 4)/* Frame-Sync Active */
+
+/* sspa clock sources */
+#define MMP_SSPA_CLK_PLL0
+#define MMP_SSPA_CLK_VCXO1
+#define MMP_SSPA_CLK_AUDIO3
+
+/* sspa pll id */
+#define MMP_SYSCLK0
+#define MMP_SSPA_CLK1
+
+#endif /* _MMP_SSPA_H */
&lt;/pre&gt;</description>
    <dc:creator>Zhangfei Gao</dc:creator>
    <dc:date>2012-05-25T07:11:02</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169325">
    <title>[PATCH 2/4] ASoC: mmp: add audio dma support</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169325</link>
    <description>&lt;pre&gt;mmp-pcm handle audio dma based on dmaengine
Support mmp and pxa910

Signed-off-by: Zhangfei Gao &amp;lt;zhangfei.gao&amp;lt; at &amp;gt;marvell.com&amp;gt;
Signed-off-by: Leo Yan &amp;lt;leoy&amp;lt; at &amp;gt;marvell.com&amp;gt;
Signed-off-by: Qiao Zhou &amp;lt;zhouqiao&amp;lt; at &amp;gt;marvell.com&amp;gt;
---
 include/linux/platform_data/mmp_audio.h |   22 ++
 sound/soc/pxa/Kconfig                   |    8 +
 sound/soc/pxa/Makefile                  |    2 +
 sound/soc/pxa/mmp-pcm.c                 |  448 +++++++++++++++++++++++++++++++
 4 files changed, 480 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/platform_data/mmp_audio.h
 create mode 100644 sound/soc/pxa/mmp-pcm.c

diff --git a/include/linux/platform_data/mmp_audio.h b/include/linux/platform_data/mmp_audio.h
new file mode 100644
index 0000000..0f25d16
--- /dev/null
+++ b/include/linux/platform_data/mmp_audio.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,22 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ *  MMP Platform AUDIO Management
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#ifndef MMP_AUDIO_H
+#define MMP_AUDIO_H
+
+struct mmp_audio_platdata {
+u32 period_max_capture;
+u32 buffer_max_capture;
+u32 period_max_playback;
+u32 buffer_max_playback;
+};
+
+#endif /* MMP_AUDIO_H */
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index a0f7d3c..a516068 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -8,6 +8,14 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; config SND_PXA2XX_SOC
   the PXA2xx AC97, I2S or SSP interface. You will also need
   to select the audio interfaces to support below.
 
+config SND_MMP_SOC
+bool "Soc Audio for Marvell MMP chips"
+depends on ARCH_MMP
+select SND_ARM
+help
+  Say Y if you want to add support for codecs attached to
+  the MMP SSPA interface.
+
 config SND_PXA2XX_AC97
 tristate
 select SND_AC97_CODEC
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index af35762..f913e9b 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -3,11 +3,13 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; snd-soc-pxa2xx-objs := pxa2xx-pcm.o
 snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
 snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
 snd-soc-pxa-ssp-objs := pxa-ssp.o
+snd-soc-mmp-objs := mmp-pcm.o
 
 obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
 obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
 obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
 obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
+obj-$(CONFIG_SND_MMP_SOC) += snd-soc-mmp.o
 
 # PXA Machine Support
 snd-soc-corgi-objs := corgi.o
diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c
new file mode 100644
index 0000000..abafbb9
--- /dev/null
+++ b/sound/soc/pxa/mmp-pcm.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,448 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * linux/sound/soc/pxa/mmp-pcm.c
+ *
+ * Copyright (C) 2011 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/init.h&amp;gt;
+#include &amp;lt;linux/platform_device.h&amp;gt;
+#include &amp;lt;linux/slab.h&amp;gt;
+#include &amp;lt;linux/dma-mapping.h&amp;gt;
+#include &amp;lt;linux/dmaengine.h&amp;gt;
+#include &amp;lt;linux/platform_data/mmp_dma.h&amp;gt;
+#include &amp;lt;linux/platform_data/mmp_audio.h&amp;gt;
+#include &amp;lt;sound/pxa2xx-lib.h&amp;gt;
+#include &amp;lt;sound/core.h&amp;gt;
+#include &amp;lt;sound/pcm.h&amp;gt;
+#include &amp;lt;sound/pcm_params.h&amp;gt;
+#include &amp;lt;sound/soc.h&amp;gt;
+#include &amp;lt;mach/sram.h&amp;gt;
+
+struct mmp_runtime_data {
+int ssp_id;
+u32 period_size;
+u32 pointer;
+struct resource *dma_res;
+struct mmp_tdma_data tdma_data;
+struct gen_pool *gpool;
+struct snd_pcm_substream *substream;
+struct dma_chan *dma_chan;
+struct dma_async_tx_descriptor *desc;
+};
+
+#define MMP_PCM_INFO (SNDRV_PCM_INFO_MMAP |\
+SNDRV_PCM_INFO_MMAP_VALID |\
+SNDRV_PCM_INFO_INTERLEAVED |\
+SNDRV_PCM_INFO_PAUSE |\
+SNDRV_PCM_INFO_RESUME)
+
+#define MMP_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_pcm_hardware mmp_pcm_hardware[] = {
+{
+.info= MMP_PCM_INFO,
+.formats= MMP_PCM_FORMATS,
+.period_bytes_min= 1024,
+.period_bytes_max= 2048,
+.periods_min= 2,
+.periods_max= 32,
+.buffer_bytes_max= 4096,
+.fifo_size= 32,
+},
+{
+.info= MMP_PCM_INFO,
+.formats= MMP_PCM_FORMATS,
+.period_bytes_min= 1024,
+.period_bytes_max= 2048,
+.periods_min= 2,
+.periods_max= 32,
+.buffer_bytes_max= 4096,
+.fifo_size= 32,
+},
+};
+
+static void mmp_pcm_adma_irq(void *data)
+{
+struct snd_pcm_substream *substream = data;
+struct mmp_runtime_data *prtd = substream-&amp;gt;runtime-&amp;gt;private_data;
+size_t dma_bytes = substream-&amp;gt;runtime-&amp;gt;dma_bytes;
+
+prtd-&amp;gt;pointer = (prtd-&amp;gt;pointer + prtd-&amp;gt;period_size) % dma_bytes;
+snd_pcm_period_elapsed(substream);
+return;
+}
+
+static bool filter(struct dma_chan *chan, void *param)
+{
+struct mmp_runtime_data *prtd = param;
+bool found = false;
+char *devname;
+
+devname = kasprintf(GFP_KERNEL, "%s.%d", prtd-&amp;gt;dma_res-&amp;gt;name,
+prtd-&amp;gt;ssp_id);
+if ((strcmp(dev_name(chan-&amp;gt;device-&amp;gt;dev), devname) == 0) &amp;amp;&amp;amp;
+(chan-&amp;gt;chan_id == prtd-&amp;gt;dma_res-&amp;gt;start)) {
+chan-&amp;gt;private = &amp;amp;prtd-&amp;gt;tdma_data;
+found = true;
+}
+
+kfree(devname);
+return found;
+}
+
+static int mmp_pcm_hw_params(struct snd_pcm_substream *substream,
+      struct snd_pcm_hw_params *params)
+{
+struct snd_pcm_runtime *runtime = substream-&amp;gt;runtime;
+struct mmp_runtime_data *prtd = runtime-&amp;gt;private_data;
+struct snd_soc_pcm_runtime *rtd = substream-&amp;gt;private_data;
+struct pxa2xx_pcm_dma_params *dma_params;
+size_t totsize = params_buffer_bytes(params);
+size_t period = params_period_bytes(params);
+int ret;
+struct dma_slave_config slave_config;
+dma_cap_mask_t mask;
+
+dma_params = snd_soc_dai_get_dma_data(rtd-&amp;gt;cpu_dai, substream);
+if (!dma_params)
+return 0;
+
+switch (params_format(params)) {
+case SNDRV_PCM_FORMAT_S8:
+prtd-&amp;gt;tdma_data.bus_size = 8;
+break;
+case SNDRV_PCM_FORMAT_S16_LE:
+prtd-&amp;gt;tdma_data.bus_size = 16;
+break;
+case SNDRV_PCM_FORMAT_S24_LE:
+prtd-&amp;gt;tdma_data.bus_size = 24;
+break;
+case SNDRV_PCM_FORMAT_S32_LE:
+prtd-&amp;gt;tdma_data.bus_size = 32;
+break;
+default:
+return -EINVAL;
+}
+prtd-&amp;gt;tdma_data.pack_mod = true;
+
+dma_cap_zero(mask);
+dma_cap_set(DMA_CYCLIC, mask);
+prtd-&amp;gt;dma_chan = dma_request_channel(mask, filter, prtd);
+if (!prtd-&amp;gt;dma_chan)
+return -EINVAL;
+
+if (substream-&amp;gt;stream == SNDRV_PCM_STREAM_PLAYBACK) {
+slave_config.direction    = DMA_TO_DEVICE;
+slave_config.dst_addr     = dma_params-&amp;gt;dev_addr;
+slave_config.dst_maxburst = 4;
+} else {
+slave_config.direction  = DMA_FROM_DEVICE;
+slave_config.src_addr  = dma_params-&amp;gt;dev_addr;
+slave_config.src_maxburst = 4;
+}
+
+ret = dmaengine_slave_config(prtd-&amp;gt;dma_chan, &amp;amp;slave_config);
+if (ret)
+return ret;
+
+snd_pcm_set_runtime_buffer(substream, &amp;amp;substream-&amp;gt;dma_buffer);
+
+prtd-&amp;gt;period_size = period;
+runtime-&amp;gt;dma_bytes = totsize;
+
+prtd-&amp;gt;desc = prtd-&amp;gt;dma_chan-&amp;gt;device-&amp;gt;device_prep_dma_cyclic(
+prtd-&amp;gt;dma_chan, runtime-&amp;gt;dma_addr, totsize, period,
+substream-&amp;gt;stream == SNDRV_PCM_STREAM_PLAYBACK ?
+DMA_TO_DEVICE : DMA_FROM_DEVICE, NULL);
+if (!prtd-&amp;gt;desc) {
+dev_err(&amp;amp;prtd-&amp;gt;dma_chan-&amp;gt;dev-&amp;gt;device, "cannot prepare slave dma\n");
+return -EINVAL;
+}
+
+prtd-&amp;gt;desc-&amp;gt;callback = mmp_pcm_adma_irq;
+prtd-&amp;gt;desc-&amp;gt;callback_param = substream;
+dmaengine_submit(prtd-&amp;gt;desc);
+return 0;
+}
+
+static int mmp_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+struct mmp_runtime_data *prtd = substream-&amp;gt;runtime-&amp;gt;private_data;
+
+if (prtd-&amp;gt;dma_chan) {
+dma_release_channel(prtd-&amp;gt;dma_chan);
+prtd-&amp;gt;dma_chan = NULL;
+}
+
+return 0;
+}
+
+static int mmp_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+struct mmp_runtime_data *prtd = substream-&amp;gt;runtime-&amp;gt;private_data;
+int ret = 0;
+
+switch (cmd) {
+case SNDRV_PCM_TRIGGER_START:
+prtd-&amp;gt;pointer = 0;
+dma_async_issue_pending(prtd-&amp;gt;dma_chan);
+break;
+
+case SNDRV_PCM_TRIGGER_STOP:
+case SNDRV_PCM_TRIGGER_SUSPEND:
+case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+dmaengine_terminate_all(prtd-&amp;gt;dma_chan);
+break;
+
+case SNDRV_PCM_TRIGGER_RESUME:
+dma_async_issue_pending(prtd-&amp;gt;dma_chan);
+break;
+
+case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+dma_async_issue_pending(prtd-&amp;gt;dma_chan);
+break;
+
+default:
+ret = -EINVAL;
+break;
+}
+
+return ret;
+}
+
+static snd_pcm_uframes_t mmp_pcm_pointer(struct snd_pcm_substream *substream)
+{
+struct snd_pcm_runtime *runtime = substream-&amp;gt;runtime;
+struct mmp_runtime_data *prtd = runtime-&amp;gt;private_data;
+snd_pcm_uframes_t x;
+
+x = bytes_to_frames(runtime, prtd-&amp;gt;pointer);
+if (x == runtime-&amp;gt;buffer_size)
+x = 0;
+
+return x;
+}
+
+static int mmp_pcm_open(struct snd_pcm_substream *substream)
+{
+struct snd_soc_pcm_runtime *rtd = substream-&amp;gt;private_data;
+struct platform_device *pdev = to_platform_device(rtd-&amp;gt;platform-&amp;gt;dev);
+struct snd_pcm_runtime *runtime = substream-&amp;gt;runtime;
+struct snd_soc_dai *cpu_dai = rtd-&amp;gt;cpu_dai;
+struct mmp_runtime_data *prtd;
+struct resource *r;
+int ret;
+
+r = platform_get_resource(pdev, IORESOURCE_DMA, substream-&amp;gt;stream);
+if (!r)
+return -EBUSY;
+
+snd_soc_set_runtime_hwparams(substream,
+&amp;amp;mmp_pcm_hardware[substream-&amp;gt;stream]);
+
+/*
+ * For mysterious reasons (and despite what the manual says)
+ * playback samples are lost if the DMA count is not a multiple
+ * of the DMA burst size.  Let's add a rule to enforce that.
+ */
+ret = snd_pcm_hw_constraint_step(runtime, 0,
+SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
+if (ret)
+goto out;
+
+ret = snd_pcm_hw_constraint_step(runtime, 0,
+SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
+if (ret)
+goto out;
+
+ret = snd_pcm_hw_constraint_integer(runtime,
+SNDRV_PCM_HW_PARAM_PERIODS);
+if (ret &amp;lt; 0)
+goto out;
+
+prtd = devm_kzalloc(&amp;amp;pdev-&amp;gt;dev,
+sizeof(struct mmp_runtime_data), GFP_KERNEL);
+if (prtd == NULL) {
+ret = -ENOMEM;
+goto out;
+}
+
+prtd-&amp;gt;substream = substream;
+runtime-&amp;gt;private_data = prtd;
+prtd-&amp;gt;dma_res = r;
+prtd-&amp;gt;ssp_id = cpu_dai-&amp;gt;id;
+return 0;
+
+out:
+return ret;
+}
+
+static int mmp_pcm_close(struct snd_pcm_substream *substream)
+{
+struct snd_soc_pcm_runtime *rtd = substream-&amp;gt;private_data;
+struct platform_device *pdev = to_platform_device(rtd-&amp;gt;platform-&amp;gt;dev);
+struct snd_pcm_runtime *runtime = substream-&amp;gt;runtime;
+struct mmp_runtime_data *prtd = runtime-&amp;gt;private_data;
+
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, prtd);
+runtime-&amp;gt;private_data = NULL;
+return 0;
+}
+
+static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+struct snd_pcm_runtime *runtime = substream-&amp;gt;runtime;
+unsigned long off = vma-&amp;gt;vm_pgoff;
+
+vma-&amp;gt;vm_page_prot = pgprot_noncached(vma-&amp;gt;vm_page_prot);
+return remap_pfn_range(vma, vma-&amp;gt;vm_start,
+__phys_to_pfn(runtime-&amp;gt;dma_addr) + off,
+vma-&amp;gt;vm_end - vma-&amp;gt;vm_start, vma-&amp;gt;vm_page_prot);
+}
+
+struct snd_pcm_ops mmp_pcm_ops = {
+.open= mmp_pcm_open,
+.close= mmp_pcm_close,
+.ioctl= snd_pcm_lib_ioctl,
+.hw_params= mmp_pcm_hw_params,
+.hw_free= mmp_pcm_hw_free,
+.trigger= mmp_pcm_trigger,
+.pointer= mmp_pcm_pointer,
+.mmap= mmp_pcm_mmap,
+};
+
+static int mmp_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+struct snd_pcm_substream *substream = pcm-&amp;gt;streams[stream].substream;
+struct snd_dma_buffer *buf = &amp;amp;substream-&amp;gt;dma_buffer;
+size_t size = mmp_pcm_hardware[stream].buffer_bytes_max;
+struct gen_pool *gpool;
+
+buf-&amp;gt;dev.type = SNDRV_DMA_TYPE_DEV;
+buf-&amp;gt;dev.dev = pcm-&amp;gt;card-&amp;gt;dev;
+buf-&amp;gt;private_data = NULL;
+
+gpool = sram_get_gpool("asram");
+if (!gpool)
+return -ENOMEM;
+
+buf-&amp;gt;area = (unsigned char *)gen_pool_alloc(gpool, size);
+if (!buf-&amp;gt;area)
+return -ENOMEM;
+buf-&amp;gt;addr = gen_pool_virt_to_phys(gpool, (unsigned long)buf-&amp;gt;area);
+buf-&amp;gt;bytes = size;
+return 0;
+}
+
+static void mmp_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+struct snd_pcm_substream *substream;
+struct snd_dma_buffer *buf;
+int stream;
+struct gen_pool *gpool;
+
+gpool = sram_get_gpool("asram");
+if (!gpool)
+return;
+
+for (stream = 0; stream &amp;lt; 2; stream++) {
+size_t size = mmp_pcm_hardware[stream].buffer_bytes_max;
+
+substream = pcm-&amp;gt;streams[stream].substream;
+if (!substream)
+continue;
+
+buf = &amp;amp;substream-&amp;gt;dma_buffer;
+if (!buf-&amp;gt;area)
+continue;
+gen_pool_free(gpool, (unsigned long)buf-&amp;gt;area, size);
+buf-&amp;gt;area = NULL;
+}
+
+return;
+}
+
+static u64 mmp_pcm_dmamask = DMA_BIT_MASK(64);
+
+int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+struct snd_card *card = rtd-&amp;gt;card-&amp;gt;snd_card;
+struct snd_pcm *pcm = rtd-&amp;gt;pcm;
+int ret = 0;
+
+if (!card-&amp;gt;dev-&amp;gt;dma_mask)
+card-&amp;gt;dev-&amp;gt;dma_mask = &amp;amp;mmp_pcm_dmamask;
+
+if (!card-&amp;gt;dev-&amp;gt;coherent_dma_mask)
+card-&amp;gt;dev-&amp;gt;coherent_dma_mask = DMA_BIT_MASK(64);
+
+if (pcm-&amp;gt;streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ret = mmp_pcm_preallocate_dma_buffer(pcm,
+SNDRV_PCM_STREAM_PLAYBACK);
+if (ret)
+goto out;
+}
+
+if (pcm-&amp;gt;streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ret = mmp_pcm_preallocate_dma_buffer(pcm,
+SNDRV_PCM_STREAM_CAPTURE);
+if (ret)
+goto out;
+}
+ out:
+return ret;
+}
+
+struct snd_soc_platform_driver mmp_soc_platform = {
+.ops= &amp;amp;mmp_pcm_ops,
+.pcm_new= mmp_pcm_new,
+.pcm_free= mmp_pcm_free_dma_buffers,
+};
+
+static __devinit int mmp_pcm_probe(struct platform_device *pdev)
+{
+struct mmp_audio_platdata *pdata = pdev-&amp;gt;dev.platform_data;
+
+if (pdata) {
+mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK].buffer_bytes_max =
+pdata-&amp;gt;buffer_max_playback;
+mmp_pcm_hardware[SNDRV_PCM_STREAM_PLAYBACK].period_bytes_max =
+pdata-&amp;gt;period_max_playback;
+mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].buffer_bytes_max =
+pdata-&amp;gt;buffer_max_capture;
+mmp_pcm_hardware[SNDRV_PCM_STREAM_CAPTURE].period_bytes_max =
+pdata-&amp;gt;period_max_capture;
+}
+return snd_soc_register_platform(&amp;amp;pdev-&amp;gt;dev, &amp;amp;mmp_soc_platform);
+}
+
+static int __devexit mmp_pcm_remove(struct platform_device *pdev)
+{
+snd_soc_unregister_platform(&amp;amp;pdev-&amp;gt;dev);
+return 0;
+}
+
+static struct platform_driver mmp_pcm_driver = {
+.driver = {
+.name = "mmp-pcm-audio",
+.owner = THIS_MODULE,
+},
+
+.probe = mmp_pcm_probe,
+.remove = __devexit_p(mmp_pcm_remove),
+};
+
+module_platform_driver(mmp_pcm_driver);
+
+MODULE_AUTHOR("Leo Yan &amp;lt;leoy&amp;lt; at &amp;gt;marvell.com&amp;gt;");
+MODULE_DESCRIPTION("MMP Soc Audio DMA module");
+MODULE_LICENSE("GPL");
&lt;/pre&gt;</description>
    <dc:creator>Zhangfei Gao</dc:creator>
    <dc:date>2012-05-25T07:11:01</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169324">
    <title>[PATCH] dmaengine: mmp_tdma: add mmp tdma support</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169324</link>
    <description>&lt;pre&gt;Add support for two-channel dma under dmaengine
support: mmp-adma and pxa910-squ

Signed-off-by: Zhangfei Gao &amp;lt;zhangfei.gao&amp;lt; at &amp;gt;marvell.com&amp;gt;
Signed-off-by: Leo Yan &amp;lt;leoy&amp;lt; at &amp;gt;marvell.com&amp;gt;
Signed-off-by: Qiao Zhou &amp;lt;zhouqiao&amp;lt; at &amp;gt;marvell.com&amp;gt;
---
 drivers/dma/Kconfig                   |   10 +
 drivers/dma/Makefile                  |    1 +
 drivers/dma/mmp_tdma.c                |  677 +++++++++++++++++++++++++++++++++
 include/linux/platform_data/mmp_dma.h |   20 +
 4 files changed, 708 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dma/mmp_tdma.c
 create mode 100644 include/linux/platform_data/mmp_dma.h

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index ef378b5..26d5b1b 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -259,6 +259,16 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; config DMA_SA11X0
   SA-1110 SoCs.  This DMA engine can only be used with on-chip
   devices.
 
+config MMP_TDMA
+bool "MMP Two-Channel DMA support"
+default ARCH_MMP
+select DMA_ENGINE
+help
+  Support the MMP Two-Channel DMA engine.
+  This engine used for MMP Audio DMA and pxa910 SQU.
+
+  Say Y here if you enabled MMP ADMA, otherwise say N.
+
 config DMA_ENGINE
 bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 86b795b..37e9258 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -28,3 +28,4 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt; obj-$(CONFIG_PCH_DMA) += pch_dma.o
 obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
 obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
 obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
+obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
new file mode 100644
index 0000000..043511b
--- /dev/null
+++ b/drivers/dma/mmp_tdma.c
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,677 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ * Driver For Marvell Two-channel DMA Engine
+ *
+ * Copyright:Marvell International Ltd.
+ *Leo Yan &amp;lt;leoy&amp;lt; at &amp;gt;marvell.com&amp;gt;
+ *
+ * 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:
+ *
+ */
+
+#include &amp;lt;linux/module.h&amp;gt;
+#include &amp;lt;linux/init.h&amp;gt;
+#include &amp;lt;linux/types.h&amp;gt;
+#include &amp;lt;linux/interrupt.h&amp;gt;
+#include &amp;lt;linux/dma-mapping.h&amp;gt;
+#include &amp;lt;linux/slab.h&amp;gt;
+#include &amp;lt;linux/dmaengine.h&amp;gt;
+#include &amp;lt;linux/platform_device.h&amp;gt;
+#include &amp;lt;linux/device.h&amp;gt;
+#include &amp;lt;linux/platform_data/mmp_dma.h&amp;gt;
+#include &amp;lt;mach/regs-icu.h&amp;gt;
+#include &amp;lt;mach/sram.h&amp;gt;
+
+/*
+ * Two-Channel DMA registers
+ */
+#define TDBCR0x00/* Byte Count */
+#define TDSAR0x10/* Src Addr */
+#define TDDAR0x20/* Dst Addr */
+#define TDNDPR0x30/* Next Desc */
+#define TDCR0x40/* Control */
+#define TDCP0x60/* Priority*/
+#define TDCDPR0x70/* Current Desc */
+#define TDIMR0x80/* Int Mask */
+#define TDISR0xa0/* Int Status */
+
+/* Two-Channel DMA Control Register */
+#define TDCR_SSZ_8_BITS(0x0 &amp;lt;&amp;lt; 22)/* Sample Size */
+#define TDCR_SSZ_12_BITS(0x1 &amp;lt;&amp;lt; 22)
+#define TDCR_SSZ_16_BITS(0x2 &amp;lt;&amp;lt; 22)
+#define TDCR_SSZ_20_BITS(0x3 &amp;lt;&amp;lt; 22)
+#define TDCR_SSZ_24_BITS(0x4 &amp;lt;&amp;lt; 22)
+#define TDCR_SSZ_32_BITS(0x5 &amp;lt;&amp;lt; 22)
+#define TDCR_SSZ_SHIFT(0x1 &amp;lt;&amp;lt; 22)
+#define TDCR_SSZ_MASK(0x7 &amp;lt;&amp;lt; 22)
+#define TDCR_SSPMOD(0x1 &amp;lt;&amp;lt; 21)/* SSP MOD */
+#define TDCR_ABR(0x1 &amp;lt;&amp;lt; 20)/* Channel Abort */
+#define TDCR_CDE(0x1 &amp;lt;&amp;lt; 17)/* Close Desc Enable */
+#define TDCR_PACKMOD(0x1 &amp;lt;&amp;lt; 16)/* Pack Mode (ADMA Only) */
+#define TDCR_CHANACT(0x1 &amp;lt;&amp;lt; 14)/* Channel Active */
+#define TDCR_FETCHND(0x1 &amp;lt;&amp;lt; 13)/* Fetch Next Desc */
+#define TDCR_CHANEN(0x1 &amp;lt;&amp;lt; 12)/* Channel Enable */
+#define TDCR_INTMODE(0x1 &amp;lt;&amp;lt; 10)/* Interrupt Mode */
+#define TDCR_CHAINMOD(0x1 &amp;lt;&amp;lt; 9)/* Chain Mode */
+#define TDCR_BURSTSZ_MSK(0x7 &amp;lt;&amp;lt; 6)/* Burst Size */
+#define TDCR_BURSTSZ_4B(0x0 &amp;lt;&amp;lt; 6)
+#define TDCR_BURSTSZ_8B(0x1 &amp;lt;&amp;lt; 6)
+#define TDCR_BURSTSZ_16B(0x3 &amp;lt;&amp;lt; 6)
+#define TDCR_BURSTSZ_32B(0x6 &amp;lt;&amp;lt; 6)
+#define TDCR_BURSTSZ_64B(0x7 &amp;lt;&amp;lt; 6)
+#define TDCR_BURSTSZ_SQU_32B(0x7 &amp;lt;&amp;lt; 6)
+#define TDCR_BURSTSZ_128B(0x5 &amp;lt;&amp;lt; 6)
+#define TDCR_DSTDIR_MSK(0x3 &amp;lt;&amp;lt; 4)/* Dst Direction */
+#define TDCR_DSTDIR_ADDR_HOLD(0x2 &amp;lt;&amp;lt; 4)/* Dst Addr Hold */
+#define TDCR_DSTDIR_ADDR_INC(0x0 &amp;lt;&amp;lt; 4)/* Dst Addr Increment */
+#define TDCR_SRCDIR_MSK(0x3 &amp;lt;&amp;lt; 2)/* Src Direction */
+#define TDCR_SRCDIR_ADDR_HOLD(0x2 &amp;lt;&amp;lt; 2)/* Src Addr Hold */
+#define TDCR_SRCDIR_ADDR_INC(0x0 &amp;lt;&amp;lt; 2)/* Src Addr Increment */
+#define TDCR_DSTDESCCONT(0x1 &amp;lt;&amp;lt; 1)
+#define TDCR_SRCDESTCONT(0x1 &amp;lt;&amp;lt; 0)
+
+/* Two-Channel DMA Int Mask Register */
+#define TDIMR_COMP(0x1 &amp;lt;&amp;lt; 0)
+
+/* Two-Channel DMA Int Status Register */
+#define TDISR_COMP(0x1 &amp;lt;&amp;lt; 0)
+
+/*
+ * Two-Channel DMA Descriptor Struct
+ * NOTE: desc's buf must be aligned to 16 bytes.
+ */
+struct mmp_tdma_desc {
+u32 byte_cnt;
+u32 src_addr;
+u32 dst_addr;
+u32 nxt_desc;
+};
+
+enum mmp_tdma_type {
+MMP_AUD_TDMA = 0,
+PXA910_SQU,
+};
+
+#define TDMA_ALIGNMENT3
+#define TDMA_MAX_XFER_BYTES    SZ_64K
+
+struct mmp_tdma_chan {
+struct device*dev;
+struct dma_chanchan;
+struct dma_async_tx_descriptordesc;
+struct tasklet_structtasklet;
+
+struct mmp_tdma_desc*desc_arr;
+phys_addr_tdesc_arr_phys;
+intdesc_num;
+enum dma_transfer_directiondir;
+dma_addr_tdev_addr;
+u32burst_sz;
+enum dma_statusstatus;
+
+intidx;
+enum mmp_tdma_typetype;
+intirq;
+unsigned longreg_base;
+};
+
+#define TDMA_CHANNEL_NUM 2
+struct mmp_tdma_device {
+struct device*dev;
+void __iomem*base;
+struct dma_devicedevice;
+struct mmp_tdma_chan*tdmac[TDMA_CHANNEL_NUM];
+intirq;
+};
+
+#define to_mmp_tdma_chan(dchan) container_of(dchan, struct mmp_tdma_chan, chan)
+
+static void mmp_tdma_chan_set_desc(struct mmp_tdma_chan *tdmac, dma_addr_t phys)
+{
+writel(phys, tdmac-&amp;gt;reg_base + TDNDPR);
+writel(readl(tdmac-&amp;gt;reg_base + TDCR) | TDCR_FETCHND,
+tdmac-&amp;gt;reg_base + TDCR);
+}
+
+static void mmp_tdma_enable_chan(struct mmp_tdma_chan *tdmac)
+{
+/* enable irq */
+writel(TDIMR_COMP, tdmac-&amp;gt;reg_base + TDIMR);
+/* enable dma chan */
+writel(readl(tdmac-&amp;gt;reg_base + TDCR) | TDCR_CHANEN,
+tdmac-&amp;gt;reg_base + TDCR);
+tdmac-&amp;gt;status = DMA_IN_PROGRESS;
+}
+
+static void mmp_tdma_disable_chan(struct mmp_tdma_chan *tdmac)
+{
+writel(readl(tdmac-&amp;gt;reg_base + TDCR) &amp;amp; ~TDCR_CHANEN,
+tdmac-&amp;gt;reg_base + TDCR);
+tdmac-&amp;gt;status = DMA_SUCCESS;
+}
+
+static void mmp_tdma_resume_chan(struct mmp_tdma_chan *tdmac)
+{
+writel(readl(tdmac-&amp;gt;reg_base + TDCR) | TDCR_CHANEN,
+tdmac-&amp;gt;reg_base + TDCR);
+tdmac-&amp;gt;status = DMA_IN_PROGRESS;
+}
+
+static void mmp_tdma_pause_chan(struct mmp_tdma_chan *tdmac)
+{
+writel(readl(tdmac-&amp;gt;reg_base + TDCR) &amp;amp; ~TDCR_CHANEN,
+tdmac-&amp;gt;reg_base + TDCR);
+tdmac-&amp;gt;status = DMA_PAUSED;
+}
+
+static int mmp_tdma_config_chan(struct mmp_tdma_chan *tdmac)
+{
+struct mmp_tdma_data *tdma_data = tdmac-&amp;gt;chan.private;
+unsigned int tdcr;
+
+mmp_tdma_disable_chan(tdmac);
+
+if (tdmac-&amp;gt;dir == DMA_MEM_TO_DEV)
+tdcr = TDCR_DSTDIR_ADDR_HOLD | TDCR_SRCDIR_ADDR_INC;
+else if (tdmac-&amp;gt;dir == DMA_DEV_TO_MEM)
+tdcr = TDCR_SRCDIR_ADDR_HOLD | TDCR_DSTDIR_ADDR_INC;
+else if (tdmac-&amp;gt;dir == DMA_MEM_TO_MEM)
+tdcr = TDCR_SRCDIR_ADDR_INC  | TDCR_DSTDIR_ADDR_INC;
+else
+tdcr = TDCR_SRCDIR_ADDR_HOLD | TDCR_DSTDIR_ADDR_HOLD;
+
+if (tdmac-&amp;gt;type == MMP_AUD_TDMA) {
+switch (tdmac-&amp;gt;burst_sz) {
+case 4:
+tdcr |= TDCR_BURSTSZ_4B;
+break;
+case 8:
+tdcr |= TDCR_BURSTSZ_8B;
+break;
+case 16:
+tdcr |= TDCR_BURSTSZ_16B;
+break;
+case 32:
+tdcr |= TDCR_BURSTSZ_32B;
+break;
+case 64:
+tdcr |= TDCR_BURSTSZ_64B;
+break;
+case 128:
+tdcr |= TDCR_BURSTSZ_128B;
+break;
+default:
+dev_err(tdmac-&amp;gt;dev, "mmp_tdma: unknown burst size.\n");
+return -EINVAL;
+}
+
+if (tdma_data-&amp;gt;pack_mod)
+tdcr |= TDCR_PACKMOD;
+
+switch (tdma_data-&amp;gt;bus_size) {
+case 8:
+tdcr |= TDCR_SSZ_8_BITS;
+break;
+case 12:
+tdcr |= TDCR_SSZ_12_BITS;
+break;
+case 16:
+tdcr |= TDCR_SSZ_16_BITS;
+break;
+case 20:
+tdcr |= TDCR_SSZ_20_BITS;
+break;
+case 24:
+tdcr |= TDCR_SSZ_24_BITS;
+break;
+case 32:
+tdcr |= TDCR_SSZ_32_BITS;
+break;
+default:
+dev_err(tdmac-&amp;gt;dev, "mmp_tdma: unknown bus size.\n");
+return -EINVAL;
+}
+} else if (tdmac-&amp;gt;type == PXA910_SQU) {
+tdcr |= TDCR_BURSTSZ_SQU_32B;
+tdcr |= TDCR_SSPMOD;
+}
+
+writel(tdcr, tdmac-&amp;gt;reg_base + TDCR);
+return 0;
+}
+
+static int mmp_tdma_clear_chan_irq(struct mmp_tdma_chan *tdmac)
+{
+u32 reg = readl(tdmac-&amp;gt;reg_base + TDISR);
+
+if (reg &amp;amp; TDISR_COMP) {
+/* clear irq */
+reg &amp;amp;= ~TDISR_COMP;
+writel(reg, tdmac-&amp;gt;reg_base + TDISR);
+
+return 1;
+}
+return 0;
+}
+
+static irqreturn_t mmp_tdma_chan_handler(int irq, void *dev_id)
+{
+struct mmp_tdma_chan *tdmac = dev_id;
+
+if (mmp_tdma_clear_chan_irq(tdmac)) {
+tasklet_schedule(&amp;amp;tdmac-&amp;gt;tasklet);
+return IRQ_HANDLED;
+} else
+return IRQ_NONE;
+}
+
+static irqreturn_t mmp_tdma_int_handler(int irq, void *dev_id)
+{
+struct mmp_tdma_device *tdev = dev_id;
+int i, ret;
+int irq_num = 0;
+
+for (i = 0; i &amp;lt; TDMA_CHANNEL_NUM; i++) {
+struct mmp_tdma_chan *tdmac = tdev-&amp;gt;tdmac[i];
+
+ret = mmp_tdma_chan_handler(irq, tdmac);
+if (ret == IRQ_HANDLED)
+irq_num++;
+}
+
+if (irq_num)
+return IRQ_HANDLED;
+else
+return IRQ_NONE;
+}
+
+static void dma_do_tasklet(unsigned long data)
+{
+struct mmp_tdma_chan *tdmac = (struct mmp_tdma_chan *)data;
+
+if (tdmac-&amp;gt;desc.callback)
+tdmac-&amp;gt;desc.callback(tdmac-&amp;gt;desc.callback_param);
+
+}
+
+static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac)
+{
+struct gen_pool *gpool;
+int size = tdmac-&amp;gt;desc_num * sizeof(struct mmp_tdma_desc);
+
+gpool = sram_get_gpool("asram");
+gen_pool_free(gpool, (unsigned long)tdmac-&amp;gt;desc_arr,
+size);
+
+return;
+}
+
+static dma_cookie_t mmp_tdma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(tx-&amp;gt;chan);
+
+mmp_tdma_chan_set_desc(tdmac, tdmac-&amp;gt;desc_arr_phys);
+
+return 0;
+}
+
+static int mmp_tdma_alloc_chan_resources(struct dma_chan *chan)
+{
+struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
+int ret;
+
+dev_dbg(tdmac-&amp;gt;dev, "%s: enter\n", __func__);
+
+dma_async_tx_descriptor_init(&amp;amp;tdmac-&amp;gt;desc, chan);
+tdmac-&amp;gt;desc.tx_submit = mmp_tdma_tx_submit;
+
+if (tdmac-&amp;gt;irq) {
+ret = devm_request_irq(tdmac-&amp;gt;dev, tdmac-&amp;gt;irq,
+mmp_tdma_chan_handler, IRQF_DISABLED, "tdma", tdmac);
+if (ret)
+goto err_request_irq;
+}
+
+return 0;
+
+err_request_irq:
+mmp_tdma_free_descriptor(tdmac);
+return ret;
+}
+
+static void mmp_tdma_free_chan_resources(struct dma_chan *chan)
+{
+struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
+
+dev_dbg(tdmac-&amp;gt;dev, "%s: enter\n", __func__);
+
+if (tdmac-&amp;gt;irq)
+devm_free_irq(tdmac-&amp;gt;dev, tdmac-&amp;gt;irq, tdmac);
+mmp_tdma_disable_chan(tdmac);
+mmp_tdma_free_descriptor(tdmac);
+return;
+}
+
+
+static struct dma_async_tx_descriptor *mmp_tdma_prep_slave_sg(
+struct dma_chan *chan, struct scatterlist *sgl,
+unsigned int sg_len, enum dma_transfer_direction direction,
+unsigned long flags, void *context)
+{
+/*
+ * This operation is not supported on the TDMA controller
+ *
+ * However, we need to provide the function pointer to allow the
+ * device_control() method to work.
+ */
+return NULL;
+}
+
+static int mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac)
+{
+struct gen_pool *gpool;
+int size = tdmac-&amp;gt;desc_num * sizeof(struct mmp_tdma_desc);
+
+dev_dbg(tdmac-&amp;gt;dev, "%s: enter\n", __func__);
+
+gpool = sram_get_gpool("asram");
+if (!gpool)
+return -ENOMEM;
+
+tdmac-&amp;gt;desc_arr = (void *)gen_pool_alloc(gpool, size);
+if (!tdmac-&amp;gt;desc_arr)
+return -ENOMEM;
+
+tdmac-&amp;gt;desc_arr_phys = gen_pool_virt_to_phys(gpool,
+(unsigned long)tdmac-&amp;gt;desc_arr);
+
+return 0;
+}
+
+static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic(
+struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
+size_t period_len, enum dma_transfer_direction direction,
+void *context)
+{
+struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
+int num_periods = buf_len / period_len;
+int i = 0, buf = 0;
+int ret;
+
+if (tdmac-&amp;gt;status != DMA_SUCCESS)
+return NULL;
+
+if (period_len &amp;gt; TDMA_MAX_XFER_BYTES) {
+dev_err(tdmac-&amp;gt;dev,
+"maximum period size exceeded: %d &amp;gt; %d\n",
+period_len, TDMA_MAX_XFER_BYTES);
+goto err_out;
+}
+
+tdmac-&amp;gt;status = DMA_IN_PROGRESS;
+tdmac-&amp;gt;desc_num = num_periods;
+ret = mmp_tdma_alloc_descriptor(tdmac);
+if (ret &amp;lt; 0)
+goto err_out;
+
+while (buf &amp;lt; buf_len) {
+struct mmp_tdma_desc *desc = &amp;amp;tdmac-&amp;gt;desc_arr[i];
+
+if (i + 1 == num_periods)
+desc-&amp;gt;nxt_desc = tdmac-&amp;gt;desc_arr_phys;
+else
+desc-&amp;gt;nxt_desc = tdmac-&amp;gt;desc_arr_phys +
+sizeof(*desc) * (i + 1);
+
+if (direction == DMA_MEM_TO_DEV) {
+desc-&amp;gt;src_addr = dma_addr;
+desc-&amp;gt;dst_addr = tdmac-&amp;gt;dev_addr;
+} else {
+desc-&amp;gt;src_addr = tdmac-&amp;gt;dev_addr;
+desc-&amp;gt;dst_addr = dma_addr;
+}
+desc-&amp;gt;byte_cnt = period_len;
+dma_addr += period_len;
+buf += period_len;
+i++;
+}
+
+return &amp;amp;tdmac-&amp;gt;desc;
+
+err_out:
+tdmac-&amp;gt;status = DMA_ERROR;
+return NULL;
+}
+
+static int mmp_tdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+unsigned long arg)
+{
+struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
+struct dma_slave_config *dmaengine_cfg = (void *)arg;
+int ret = 0;
+
+switch (cmd) {
+case DMA_TERMINATE_ALL:
+mmp_tdma_disable_chan(tdmac);
+break;
+case DMA_PAUSE:
+mmp_tdma_pause_chan(tdmac);
+break;
+case DMA_RESUME:
+mmp_tdma_resume_chan(tdmac);
+break;
+case DMA_SLAVE_CONFIG:
+if (dmaengine_cfg-&amp;gt;direction == DMA_DEV_TO_MEM) {
+tdmac-&amp;gt;dev_addr = dmaengine_cfg-&amp;gt;src_addr;
+tdmac-&amp;gt;burst_sz = dmaengine_cfg-&amp;gt;src_maxburst;
+} else {
+tdmac-&amp;gt;dev_addr = dmaengine_cfg-&amp;gt;dst_addr;
+tdmac-&amp;gt;burst_sz = dmaengine_cfg-&amp;gt;dst_maxburst;
+}
+tdmac-&amp;gt;dir = dmaengine_cfg-&amp;gt;direction;
+return mmp_tdma_config_chan(tdmac);
+default:
+ret = -ENOSYS;
+}
+
+return ret;
+}
+
+static enum dma_status mmp_tdma_tx_status(struct dma_chan *chan,
+dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
+
+return tdmac-&amp;gt;status;
+}
+
+static void mmp_tdma_issue_pending(struct dma_chan *chan)
+{
+struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
+
+mmp_tdma_enable_chan(tdmac);
+}
+
+static int __devexit mmp_tdma_remove(struct platform_device *pdev)
+{
+struct mmp_tdma_device *tdev = platform_get_drvdata(pdev);
+struct resource *iores;
+int chan_num = TDMA_CHANNEL_NUM;
+int i;
+
+dma_async_device_unregister(&amp;amp;tdev-&amp;gt;device);
+
+if (tdev-&amp;gt;irq)
+devm_free_irq(tdev-&amp;gt;dev, tdev-&amp;gt;irq, tdev);
+
+for (i = 0; i &amp;lt; chan_num; i++)
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, tdev-&amp;gt;tdmac[i]);
+
+iounmap(tdev-&amp;gt;base);
+iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+if (iores)
+release_mem_region(iores-&amp;gt;start, resource_size(iores));
+
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, tdev);
+
+return 0;
+}
+
+static int __devinit mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
+int idx, int irq, int type)
+{
+struct mmp_tdma_chan *tdmac;
+
+if (idx &amp;gt;= TDMA_CHANNEL_NUM) {
+dev_err(tdev-&amp;gt;dev, "too many channels for device!\n");
+return -EINVAL;
+}
+
+/* alloc channel */
+tdmac = devm_kzalloc(tdev-&amp;gt;dev, sizeof(*tdmac), GFP_KERNEL);
+if (!tdmac) {
+dev_err(tdev-&amp;gt;dev, "no free memory for DMA channels!\n");
+return -ENOMEM;
+}
+if (irq)
+tdmac-&amp;gt;irq = irq + idx;
+tdmac-&amp;gt;dev   = tdev-&amp;gt;dev;
+tdmac-&amp;gt;chan.device = &amp;amp;tdev-&amp;gt;device;
+tdmac-&amp;gt;idx   = idx;
+tdmac-&amp;gt;type   = type;
+tdmac-&amp;gt;reg_base   = (unsigned long)tdev-&amp;gt;base + idx * 4;
+tdmac-&amp;gt;status = DMA_SUCCESS;
+tdev-&amp;gt;tdmac[tdmac-&amp;gt;idx] = tdmac;
+tasklet_init(&amp;amp;tdmac-&amp;gt;tasklet, dma_do_tasklet, (unsigned long)tdmac);
+
+/* add the channel to tdma_chan list */
+list_add_tail(&amp;amp;tdmac-&amp;gt;chan.device_node,
+&amp;amp;tdev-&amp;gt;device.channels);
+
+return 0;
+}
+
+static int __devinit mmp_tdma_probe(struct platform_device *pdev)
+{
+const struct platform_device_id *id = platform_get_device_id(pdev);
+enum mmp_tdma_type type = id-&amp;gt;driver_data;
+struct mmp_tdma_device *tdev;
+struct resource *iores;
+int i, ret;
+int irq = 0;
+int chan_num = TDMA_CHANNEL_NUM;
+
+/* always have couple channels */
+tdev = devm_kzalloc(&amp;amp;pdev-&amp;gt;dev, sizeof(*tdev), GFP_KERNEL);
+if (!tdev)
+return -ENOMEM;
+
+tdev-&amp;gt;dev = &amp;amp;pdev-&amp;gt;dev;
+iores = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+if (!iores) {
+ret = -EINVAL;
+goto err_irq;
+}
+
+if (resource_size(iores) != chan_num)
+tdev-&amp;gt;irq = iores-&amp;gt;start;
+else
+irq = iores-&amp;gt;start;
+
+iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+if (!iores) {
+ret = -EINVAL;
+goto err_irq;
+}
+
+if (!request_mem_region(iores-&amp;gt;start, resource_size(iores),
+pdev-&amp;gt;name)) {
+ret = -EBUSY;
+goto err_request_region;
+}
+
+tdev-&amp;gt;base = ioremap(iores-&amp;gt;start, resource_size(iores));
+if (!tdev-&amp;gt;base) {
+ret = -ENOMEM;
+goto err_ioremap;
+}
+
+if (tdev-&amp;gt;irq) {
+ret = devm_request_irq(&amp;amp;pdev-&amp;gt;dev, tdev-&amp;gt;irq,
+mmp_tdma_int_handler, IRQF_DISABLED, "tdma", tdev);
+if (ret)
+goto err_req_irq;
+}
+
+dma_cap_set(DMA_SLAVE, tdev-&amp;gt;device.cap_mask);
+dma_cap_set(DMA_CYCLIC, tdev-&amp;gt;device.cap_mask);
+
+INIT_LIST_HEAD(&amp;amp;tdev-&amp;gt;device.channels);
+
+/* initialize channel parameters */
+for (i = 0; i &amp;lt; chan_num; i++) {
+ret = mmp_tdma_chan_init(tdev, i, irq, type);
+if (ret)
+goto err_init;
+}
+
+tdev-&amp;gt;device.dev = &amp;amp;pdev-&amp;gt;dev;
+tdev-&amp;gt;device.device_alloc_chan_resources =
+mmp_tdma_alloc_chan_resources;
+tdev-&amp;gt;device.device_free_chan_resources =
+mmp_tdma_free_chan_resources;
+tdev-&amp;gt;device.device_prep_slave_sg = mmp_tdma_prep_slave_sg;
+tdev-&amp;gt;device.device_prep_dma_cyclic = mmp_tdma_prep_dma_cyclic;
+tdev-&amp;gt;device.device_tx_status = mmp_tdma_tx_status;
+tdev-&amp;gt;device.device_issue_pending = mmp_tdma_issue_pending;
+tdev-&amp;gt;device.device_control = mmp_tdma_control;
+tdev-&amp;gt;device.copy_align = TDMA_ALIGNMENT;
+
+dma_set_mask(&amp;amp;pdev-&amp;gt;dev, DMA_BIT_MASK(64));
+platform_set_drvdata(pdev, tdev);
+
+ret = dma_async_device_register(&amp;amp;tdev-&amp;gt;device);
+if (ret) {
+dev_err(tdev-&amp;gt;device.dev, "unable to register\n");
+goto err_init;
+}
+
+dev_info(tdev-&amp;gt;device.dev, "initialized\n");
+return 0;
+
+err_init:
+for (i = 0; i &amp;lt; chan_num; i++)
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, tdev-&amp;gt;tdmac[i]);
+if (tdev-&amp;gt;irq)
+devm_free_irq(tdev-&amp;gt;dev, tdev-&amp;gt;irq, tdev);
+err_req_irq:
+iounmap(tdev-&amp;gt;base);
+err_ioremap:
+release_mem_region(iores-&amp;gt;start, resource_size(iores));
+err_request_region:
+err_irq:
+devm_kfree(&amp;amp;pdev-&amp;gt;dev, tdev);
+return ret;
+}
+
+static const struct platform_device_id mmp_tdma_id_table[] = {
+{ "mmp-adma",MMP_AUD_TDMA },
+{ "pxa910-squ",PXA910_SQU },
+{ },
+};
+
+static struct platform_driver mmp_tdma_driver = {
+.driver= {
+.name= "mmp-tdma",
+.owner  = THIS_MODULE,
+},
+.id_table= mmp_tdma_id_table,
+.probe= mmp_tdma_probe,
+.remove= __devexit_p(mmp_tdma_remove),
+};
+
+module_platform_driver(mmp_tdma_driver);
+
+MODULE_DESCRIPTION("MMP Two-Channel DMA Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/mmp_dma.h b/include/linux/platform_data/mmp_dma.h
new file mode 100644
index 0000000..4e21cf9
--- /dev/null
+++ b/include/linux/platform_data/mmp_dma.h
&amp;lt; at &amp;gt;&amp;lt; at &amp;gt; -0,0 +1,20 &amp;lt; at &amp;gt;&amp;lt; at &amp;gt;
+/*
+ *  MMP Platform DMA Management
+ *
+ *  Copyright (c) 2011 Marvell Semiconductors Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+
+#ifndef MMP_DMA_H
+#define MMP_DMA_H
+
+struct mmp_tdma_data {
+u32 bus_size;
+u32 pack_mod;
+};
+
+#endif /* MMP_DMA_H */
&lt;/pre&gt;</description>
    <dc:creator>Zhangfei Gao</dc:creator>
    <dc:date>2012-05-25T07:11:00</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169323">
    <title>[PATCH 0/4] mmp audio support</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169323</link>
    <description>&lt;pre&gt;These four patches provide mmp audio support under alsa via dmaengine
Support platfrom pxa688 and pxa910
mmp_tdma.c and mmp-pcm.c is shared for pxa688 and pxa910
pxa688 (mmp2) use mmp2-sspa.c
pxa910 directly use pxa-ssp.c
mmp_tdma.c is under dmaengine framework

Verified on brownstone (pxa688) and ttc-dkb

Zhangfei Gao (4):
  dmaengine: mmp_tdma: add mmp tdma support
  ASoC: mmp: add audio dma support
  ASOC: mmp: add sspa support
  ASoC: add mmp brownstone support

 drivers/dma/Kconfig                     |   10 +
 drivers/dma/Makefile                    |    1 +
 drivers/dma/mmp_tdma.c                  |  677 +++++++++++++++++++++++++++++++
 include/linux/platform_data/mmp_audio.h |   22 +
 include/linux/platform_data/mmp_dma.h   |   20 +
 sound/soc/pxa/Kconfig                   |   20 +
 sound/soc/pxa/Makefile                  |    6 +
 sound/soc/pxa/brownstone.c              |  303 ++++++++++++++
 sound/soc/pxa/mmp-pcm.c                 |  448 ++++++++++++++++++++
 sound/soc/pxa/mmp-sspa.c                |  536 ++++++++++++++++++++++++
 sound/soc/pxa/mmp-sspa.h                |   92 +++++
 11 files changed, 2135 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dma/mmp_tdma.c
 create mode 100644 include/linux/platform_data/mmp_audio.h
 create mode 100644 include/linux/platform_data/mmp_dma.h
 create mode 100644 sound/soc/pxa/brownstone.c
 create mode 100644 sound/soc/pxa/mmp-pcm.c
 create mode 100644 sound/soc/pxa/mmp-sspa.c
 create mode 100644 sound/soc/pxa/mmp-sspa.h
&lt;/pre&gt;</description>
    <dc:creator>Zhangfei Gao</dc:creator>
    <dc:date>2012-05-25T07:10:59</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169322">
    <title>Re: [PATCH 2/5] ARM: imx6q: add clock for apbh-dma</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169322</link>
    <description>&lt;pre&gt;
Ok then, just wanted to make sure this is no patching accident.

Sascha

&lt;/pre&gt;</description>
    <dc:creator>Sascha Hauer</dc:creator>
    <dc:date>2012-05-25T06:47:53</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169314">
    <title>Re: [PATCH 4/5] ARM: imx6q: add DT node for gpmi-nand</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169314</link>
    <description>&lt;pre&gt;
Missing pinctrl setup?


&lt;/pre&gt;</description>
    <dc:creator>Shawn Guo</dc:creator>
    <dc:date>2012-05-25T02:50:58</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169313">
    <title>Re: [PATCH 2/5] ARM: imx6q: add clock for apbh-dma</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169313</link>
    <description>&lt;pre&gt;I guess it's a hardware bug.

&lt;/pre&gt;</description>
    <dc:creator>Shawn Guo</dc:creator>
    <dc:date>2012-05-25T02:41:08</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169312">
    <title>Re: [PATCH 3/5] dma: mxs-dma: enable apbh-dma for imx6q</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169312</link>
    <description>&lt;pre&gt;
As I commented on dts change, you do not need to patch
drivers/dma/mxs-dma.c at all, since the IP block on imx6q is compatible
with imx28 with no need of any tweaking.  All you need to do is put
imx28 compatible string at the end of imx6q one, and the driver will
simply work for imx6q.  That's the whole point of DT compatible
property.

Regards,
Shawn

&lt;/pre&gt;</description>
    <dc:creator>Shawn Guo</dc:creator>
    <dc:date>2012-05-25T02:36:01</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169311">
    <title>Re: [PATCH 1/5] ARM: imx6q: add DT node for apbh-dma</title>
    <link>http://permalink.gmane.org/gmane.linux.ports.arm.kernel/169311</link>
    <description>&lt;pre&gt;
I guess imx6q-dma-apbh is compatible with imx28-dma-apbh.  In that
case, you need something like below.

compatible = "fsl,imx6q-dma-apbh", "imx28-dma-apbh";

Then you do not need to patch mxs-dma.c at all.

Regards,
Shawn

&lt;/pre&gt;</description>
    <dc:creator>Shawn Guo</dc:creator>
    <dc:date>2012-05-25T02:31:01</dc:date>
  </item>
  <textinput rdf:about="http://search.gmane.org/?group=$group=gmane.linux.ports.arm.kernel">
    <title>Search Engine</title>
    <description>Search the mailing list at Gmane</description>
    <name>query</name>
    <link>http://search.gmane.org/?group=$group=gmane.linux.ports.arm.kernel</link>
  </textinput>
</rdf:RDF>

