Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/27569/?format=api
{ "id": 27569, "url": "http://patchwork.ozlabs.org/api/patches/27569/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20090523231259.17919.84248.stgit@terra/", "project": { "id": 2, "url": "http://patchwork.ozlabs.org/api/projects/2/?format=api", "name": "Linux PPC development", "link_name": "linuxppc-dev", "list_id": "linuxppc-dev.lists.ozlabs.org", "list_email": "linuxppc-dev@lists.ozlabs.org", "web_url": "https://github.com/linuxppc/wiki/wiki", "scm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git", "webscm_url": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/", "list_archive_url": "https://lore.kernel.org/linuxppc-dev/", "list_archive_url_format": "https://lore.kernel.org/linuxppc-dev/{}/", "commit_url_format": "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?id={}" }, "msgid": "<20090523231259.17919.84248.stgit@terra>", "list_archive_url": "https://lore.kernel.org/linuxppc-dev/20090523231259.17919.84248.stgit@terra/", "date": "2009-05-23T23:12:59", "name": "[V2,2/9] Basic split of mpc5200 DMA code out from mpc5200_psc_i2s", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "0238ea5eff80005ce5291ede13fa594ee59dac7c", "submitter": { "id": 375, "url": "http://patchwork.ozlabs.org/api/people/375/?format=api", "name": "jonsmirl@gmail.com", "email": "jonsmirl@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20090523231259.17919.84248.stgit@terra/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/27569/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/27569/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org>", "X-Original-To": [ "patchwork-incoming@bilbo.ozlabs.org", "linuxppc-dev@ozlabs.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "patchwork-incoming@ozlabs.org", "linuxppc-dev@ozlabs.org" ], "Received": [ "from ozlabs.org (ozlabs.org [203.10.76.45])\n\t(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\n\t(Client CN \"mx.ozlabs.org\",\n\tIssuer \"CA Cert Signing Authority\" (verified OK))\n\tby bilbo.ozlabs.org (Postfix) with ESMTPS id 93ABCB6F56\n\tfor <patchwork-incoming@bilbo.ozlabs.org>;\n\tSun, 24 May 2009 09:16:13 +1000 (EST)", "by ozlabs.org (Postfix)\n\tid E852CDE4FC; Sun, 24 May 2009 09:14:30 +1000 (EST)", "from ozlabs.org (localhost [127.0.0.1])\n\tby ozlabs.org (Postfix) with ESMTP id E32C3DE24E\n\tfor <patchwork-incoming@ozlabs.org>;\n\tSun, 24 May 2009 09:14:30 +1000 (EST)", "from yw-out-2324.google.com (yw-out-2324.google.com [74.125.46.31])\n\tby ozlabs.org (Postfix) with ESMTP id C6A50DDF8E\n\tfor <linuxppc-dev@ozlabs.org>; Sun, 24 May 2009 09:13:00 +1000 (EST)", "by yw-out-2324.google.com with SMTP id 2so1211819ywt.39\n\tfor <linuxppc-dev@ozlabs.org>; Sat, 23 May 2009 16:13:00 -0700 (PDT)", "by 10.90.89.8 with SMTP id m8mr4658315agb.23.1243120380254;\n\tSat, 23 May 2009 16:13:00 -0700 (PDT)", "from terra (c-76-109-159-38.hsd1.fl.comcast.net [76.109.159.38])\n\tby mx.google.com with ESMTPS id 7sm2812471aga.67.2009.05.23.16.12.59\n\t(version=TLSv1/SSLv3 cipher=RC4-MD5);\n\tSat, 23 May 2009 16:12:59 -0700 (PDT)", "from localhost ([127.0.0.1] helo=[127.0.1.1])\n\tby terra with esmtp (Exim 4.69) (envelope-from <jonsmirl@gmail.com>)\n\tid 1M80Oh-0004h8-J7; Sat, 23 May 2009 19:12:59 -0400" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; \n\th=domainkey-signature:received:received:received:subject:to:from:date\n\t:message-id:in-reply-to:references:user-agent:mime-version\n\t:content-type:content-transfer-encoding;\n\tbh=YN0AItEmMyyDTjp5xLKxxL8xQRTJ33d0sWnyfPMkVss=;\n\tb=pM95yBWwDt0MtoOgRVM1eVJVYMhPzkPW3vQ92bALdCOQKq3SUp4P539llMtiy7hAnd\n\tE7MIgBrPg78OLl5y9O30Ctcki1UwvKHuxjVSBKfnRoR5fuaD15Q8V/6Vgk9hmDSYlN3t\n\tpd2/VfPnZXHE0vRO3SCiACWURcAeXHxHWzIP0=", "DomainKey-Signature": "a=rsa-sha1; c=nofws; d=gmail.com; s=gamma;\n\th=subject:to:from:date:message-id:in-reply-to:references:user-agent\n\t:mime-version:content-type:content-transfer-encoding;\n\tb=m1Q3oMdVsOJzqIwBuD8doA9uK59SXCt0nTvc10UcRxmScOCdAegFy5ks/E3QxcsSGc\n\tH3cW8ANx5zW8BSMm4fmMH3lvuaepaQ2C9vGsmoMKyAI9t0hQ69aZ3cUh//vqincEClbW\n\tmWTNyqpL3JoeuZJ4mmKom/UrBD+ts4mSU8Qik=", "Subject": "[PATCH V2 2/9] Basic split of mpc5200 DMA code out from\n\tmpc5200_psc_i2s", "To": "grant.likely@secretlab.ca, linuxppc-dev@ozlabs.org,\n\talsa-devel@alsa-project.org, broonie@sirena.org.uk", "From": "Jon Smirl <jonsmirl@gmail.com>", "Date": "Sat, 23 May 2009 19:12:59 -0400", "Message-ID": "<20090523231259.17919.84248.stgit@terra>", "In-Reply-To": "<20090523231148.17919.46103.stgit@terra>", "References": "<20090523231148.17919.46103.stgit@terra>", "User-Agent": "StGit/0.14.3.366.gf979", "MIME-Version": "1.0", "X-BeenThere": "linuxppc-dev@ozlabs.org", "X-Mailman-Version": "2.1.11", "Precedence": "list", "List-Id": "Linux on PowerPC Developers Mail List <linuxppc-dev.ozlabs.org>", "List-Unsubscribe": "<https://ozlabs.org/mailman/options/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@ozlabs.org?subject=unsubscribe>", "List-Archive": "<http://ozlabs.org/pipermail/linuxppc-dev>", "List-Post": "<mailto:linuxppc-dev@ozlabs.org>", "List-Help": "<mailto:linuxppc-dev-request@ozlabs.org?subject=help>", "List-Subscribe": "<https://ozlabs.org/mailman/listinfo/linuxppc-dev>,\n\t<mailto:linuxppc-dev-request@ozlabs.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Sender": "linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org", "Errors-To": "linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org" }, "content": "Basic split of mpc5200 DMA code out from i2s into a standalone file.\n\nSigned-off-by: Jon Smirl <jonsmirl@gmail.com>\n---\n sound/soc/fsl/Kconfig | 4 \n sound/soc/fsl/Makefile | 2 \n sound/soc/fsl/mpc5200_dma.c | 458 +++++++++++++++++++++++++++++++++++++\n sound/soc/fsl/mpc5200_dma.h | 81 +++++++\n sound/soc/fsl/mpc5200_psc_i2s.c | 485 ---------------------------------------\n 5 files changed, 547 insertions(+), 483 deletions(-)\n create mode 100644 sound/soc/fsl/mpc5200_dma.c\n create mode 100644 sound/soc/fsl/mpc5200_dma.h", "diff": "diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig\nindex 9fc9082..dc79bdf 100644\n--- a/sound/soc/fsl/Kconfig\n+++ b/sound/soc/fsl/Kconfig\n@@ -1,5 +1,8 @@\n config SND_SOC_OF_SIMPLE\n \ttristate\n+\t\n+config SND_MPC52xx_DMA\n+\ttristate\n \n # ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers\n # for the SSI and the Elo DMA controller. You will still need to select\n@@ -23,6 +26,7 @@ config SND_SOC_MPC5200_I2S\n \ttristate \"Freescale MPC5200 PSC in I2S mode driver\"\n \tdepends on PPC_MPC52xx && PPC_BESTCOMM\n \tselect SND_SOC_OF_SIMPLE\n+\tselect SND_MPC52xx_DMA\n \tselect PPC_BESTCOMM_GEN_BD\n \thelp\n \t Say Y here to support the MPC5200 PSCs in I2S mode.\ndiff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile\nindex f85134c..7731ef2 100644\n--- a/sound/soc/fsl/Makefile\n+++ b/sound/soc/fsl/Makefile\n@@ -10,5 +10,7 @@ snd-soc-fsl-ssi-objs := fsl_ssi.o\n snd-soc-fsl-dma-objs := fsl_dma.o\n obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o\n \n+# MPC5200 Platform Support\n+obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o\n obj-$(CONFIG_SND_SOC_MPC5200_I2S) += mpc5200_psc_i2s.o\n \ndiff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c\nnew file mode 100644\nindex 0000000..4bae8d6\n--- /dev/null\n+++ b/sound/soc/fsl/mpc5200_dma.c\n@@ -0,0 +1,458 @@\n+/*\n+ * Freescale MPC5200 PSC DMA\n+ * ALSA SoC Platform driver\n+ *\n+ * Copyright (C) 2008 Secret Lab Technologies Ltd.\n+ */\n+\n+#include <linux/init.h>\n+#include <linux/module.h>\n+#include <linux/interrupt.h>\n+#include <linux/device.h>\n+#include <linux/delay.h>\n+#include <linux/of_device.h>\n+#include <linux/of_platform.h>\n+#include <linux/dma-mapping.h>\n+\n+#include <sound/core.h>\n+#include <sound/pcm.h>\n+#include <sound/pcm_params.h>\n+#include <sound/initval.h>\n+#include <sound/soc.h>\n+#include <sound/soc-of-simple.h>\n+\n+#include <sysdev/bestcomm/bestcomm.h>\n+#include <sysdev/bestcomm/gen_bd.h>\n+#include <asm/mpc52xx_psc.h>\n+\n+#include \"mpc5200_dma.h\"\n+\n+MODULE_AUTHOR(\"Grant Likely <grant.likely@secretlab.ca>\");\n+MODULE_DESCRIPTION(\"Freescale MPC5200 PSC in DMA mode ASoC Driver\");\n+MODULE_LICENSE(\"GPL\");\n+\n+/*\n+ * Interrupt handlers\n+ */\n+static irqreturn_t psc_i2s_status_irq(int irq, void *_psc_i2s)\n+{\n+\tstruct psc_i2s *psc_i2s = _psc_i2s;\n+\tstruct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;\n+\tu16 isr;\n+\n+\tisr = in_be16(®s->mpc52xx_psc_isr);\n+\n+\t/* Playback underrun error */\n+\tif (psc_i2s->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP))\n+\t\tpsc_i2s->stats.underrun_count++;\n+\n+\t/* Capture overrun error */\n+\tif (psc_i2s->capture.active && (isr & MPC52xx_PSC_IMR_ORERR))\n+\t\tpsc_i2s->stats.overrun_count++;\n+\n+\tout_8(®s->command, 4 << 4);\t/* reset the error status */\n+\n+\treturn IRQ_HANDLED;\n+}\n+\n+/**\n+ * psc_i2s_bcom_enqueue_next_buffer - Enqueue another audio buffer\n+ * @s: pointer to stream private data structure\n+ *\n+ * Enqueues another audio period buffer into the bestcomm queue.\n+ *\n+ * Note: The routine must only be called when there is space available in\n+ * the queue. Otherwise the enqueue will fail and the audio ring buffer\n+ * will get out of sync\n+ */\n+static void psc_i2s_bcom_enqueue_next_buffer(struct psc_i2s_stream *s)\n+{\n+\tstruct bcom_bd *bd;\n+\n+\t/* Prepare and enqueue the next buffer descriptor */\n+\tbd = bcom_prepare_next_buffer(s->bcom_task);\n+\tbd->status = s->period_bytes;\n+\tbd->data[0] = s->period_next_pt;\n+\tbcom_submit_next_buffer(s->bcom_task, NULL);\n+\n+\t/* Update for next period */\n+\ts->period_next_pt += s->period_bytes;\n+\tif (s->period_next_pt >= s->period_end)\n+\t\ts->period_next_pt = s->period_start;\n+}\n+\n+/* Bestcomm DMA irq handler */\n+static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream)\n+{\n+\tstruct psc_i2s_stream *s = _psc_i2s_stream;\n+\n+\t/* For each finished period, dequeue the completed period buffer\n+\t * and enqueue a new one in it's place. */\n+\twhile (bcom_buffer_done(s->bcom_task)) {\n+\t\tbcom_retrieve_buffer(s->bcom_task, NULL, NULL);\n+\t\ts->period_current_pt += s->period_bytes;\n+\t\tif (s->period_current_pt >= s->period_end)\n+\t\t\ts->period_current_pt = s->period_start;\n+\t\tpsc_i2s_bcom_enqueue_next_buffer(s);\n+\t\tbcom_enable(s->bcom_task);\n+\t}\n+\n+\t/* If the stream is active, then also inform the PCM middle layer\n+\t * of the period finished event. */\n+\tif (s->active)\n+\t\tsnd_pcm_period_elapsed(s->stream);\n+\n+\treturn IRQ_HANDLED;\n+}\n+\n+/**\n+ * psc_i2s_startup: create a new substream\n+ *\n+ * This is the first function called when a stream is opened.\n+ *\n+ * If this is the first stream open, then grab the IRQ and program most of\n+ * the PSC registers.\n+ */\n+int psc_i2s_startup(struct snd_pcm_substream *substream,\n+\t\t\t struct snd_soc_dai *dai)\n+{\n+\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n+\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n+\tint rc;\n+\n+\tdev_dbg(psc_i2s->dev, \"psc_i2s_startup(substream=%p)\\n\", substream);\n+\n+\tif (!psc_i2s->playback.active &&\n+\t !psc_i2s->capture.active) {\n+\t\t/* Setup the IRQs */\n+\t\trc = request_irq(psc_i2s->irq, &psc_i2s_status_irq, IRQF_SHARED,\n+\t\t\t\t \"psc-i2s-status\", psc_i2s);\n+\t\trc |= request_irq(psc_i2s->capture.irq,\n+\t\t\t\t &psc_i2s_bcom_irq, IRQF_SHARED,\n+\t\t\t\t \"psc-i2s-capture\", &psc_i2s->capture);\n+\t\trc |= request_irq(psc_i2s->playback.irq,\n+\t\t\t\t &psc_i2s_bcom_irq, IRQF_SHARED,\n+\t\t\t\t \"psc-i2s-playback\", &psc_i2s->playback);\n+\t\tif (rc) {\n+\t\t\tfree_irq(psc_i2s->irq, psc_i2s);\n+\t\t\tfree_irq(psc_i2s->capture.irq,\n+\t\t\t\t &psc_i2s->capture);\n+\t\t\tfree_irq(psc_i2s->playback.irq,\n+\t\t\t\t &psc_i2s->playback);\n+\t\t\treturn -ENODEV;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int psc_i2s_hw_free(struct snd_pcm_substream *substream,\n+\t\t\t struct snd_soc_dai *dai)\n+{\n+\tsnd_pcm_set_runtime_buffer(substream, NULL);\n+\treturn 0;\n+}\n+\n+/**\n+ * psc_i2s_trigger: start and stop the DMA transfer.\n+ *\n+ * This function is called by ALSA to start, stop, pause, and resume the DMA\n+ * transfer of data.\n+ */\n+int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,\n+\t\t\t struct snd_soc_dai *dai)\n+{\n+\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n+\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n+\tstruct snd_pcm_runtime *runtime = substream->runtime;\n+\tstruct psc_i2s_stream *s;\n+\tstruct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;\n+\tu16 imr;\n+\tu8 psc_cmd;\n+\tunsigned long flags;\n+\n+\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n+\t\ts = &psc_i2s->capture;\n+\telse\n+\t\ts = &psc_i2s->playback;\n+\n+\tdev_dbg(psc_i2s->dev, \"psc_i2s_trigger(substream=%p, cmd=%i)\"\n+\t\t\" stream_id=%i\\n\",\n+\t\tsubstream, cmd, substream->pstr->stream);\n+\n+\tswitch (cmd) {\n+\tcase SNDRV_PCM_TRIGGER_START:\n+\t\ts->period_bytes = frames_to_bytes(runtime,\n+\t\t\t\t\t\t runtime->period_size);\n+\t\ts->period_start = virt_to_phys(runtime->dma_area);\n+\t\ts->period_end = s->period_start +\n+\t\t\t\t(s->period_bytes * runtime->periods);\n+\t\ts->period_next_pt = s->period_start;\n+\t\ts->period_current_pt = s->period_start;\n+\t\ts->active = 1;\n+\n+\t\t/* First; reset everything */\n+\t\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {\n+\t\t\tout_8(®s->command, MPC52xx_PSC_RST_RX);\n+\t\t\tout_8(®s->command, MPC52xx_PSC_RST_ERR_STAT);\n+\t\t} else {\n+\t\t\tout_8(®s->command, MPC52xx_PSC_RST_TX);\n+\t\t\tout_8(®s->command, MPC52xx_PSC_RST_ERR_STAT);\n+\t\t}\n+\n+\t\t/* Next, fill up the bestcomm bd queue and enable DMA.\n+\t\t * This will begin filling the PSC's fifo. */\n+\t\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n+\t\t\tbcom_gen_bd_rx_reset(s->bcom_task);\n+\t\telse\n+\t\t\tbcom_gen_bd_tx_reset(s->bcom_task);\n+\t\twhile (!bcom_queue_full(s->bcom_task))\n+\t\t\tpsc_i2s_bcom_enqueue_next_buffer(s);\n+\t\tbcom_enable(s->bcom_task);\n+\n+\t\t/* Due to errata in the i2s mode; need to line up enabling\n+\t\t * the transmitter with a transition on the frame sync\n+\t\t * line */\n+\n+\t\tspin_lock_irqsave(&psc_i2s->lock, flags);\n+\t\t/* first make sure it is low */\n+\t\twhile ((in_8(®s->ipcr_acr.ipcr) & 0x80) != 0)\n+\t\t\t;\n+\t\t/* then wait for the transition to high */\n+\t\twhile ((in_8(®s->ipcr_acr.ipcr) & 0x80) == 0)\n+\t\t\t;\n+\t\t/* Finally, enable the PSC.\n+\t\t * Receiver must always be enabled; even when we only want\n+\t\t * transmit. (see 15.3.2.3 of MPC5200B User's Guide) */\n+\t\tpsc_cmd = MPC52xx_PSC_RX_ENABLE;\n+\t\tif (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)\n+\t\t\tpsc_cmd |= MPC52xx_PSC_TX_ENABLE;\n+\t\tout_8(®s->command, psc_cmd);\n+\t\tspin_unlock_irqrestore(&psc_i2s->lock, flags);\n+\n+\t\tbreak;\n+\n+\tcase SNDRV_PCM_TRIGGER_STOP:\n+\t\t/* Turn off the PSC */\n+\t\ts->active = 0;\n+\t\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {\n+\t\t\tif (!psc_i2s->playback.active) {\n+\t\t\t\tout_8(®s->command, 2 << 4);\t/* reset rx */\n+\t\t\t\tout_8(®s->command, 3 << 4);\t/* reset tx */\n+\t\t\t\tout_8(®s->command, 4 << 4);\t/* reset err */\n+\t\t\t}\n+\t\t} else {\n+\t\t\tout_8(®s->command, 3 << 4);\t/* reset tx */\n+\t\t\tout_8(®s->command, 4 << 4);\t/* reset err */\n+\t\t\tif (!psc_i2s->capture.active)\n+\t\t\t\tout_8(®s->command, 2 << 4);\t/* reset rx */\n+\t\t}\n+\n+\t\tbcom_disable(s->bcom_task);\n+\t\twhile (!bcom_queue_empty(s->bcom_task))\n+\t\t\tbcom_retrieve_buffer(s->bcom_task, NULL, NULL);\n+\n+\t\tbreak;\n+\n+\tdefault:\n+\t\tdev_dbg(psc_i2s->dev, \"invalid command\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Update interrupt enable settings */\n+\timr = 0;\n+\tif (psc_i2s->playback.active)\n+\t\timr |= MPC52xx_PSC_IMR_TXEMP;\n+\tif (psc_i2s->capture.active)\n+\t\timr |= MPC52xx_PSC_IMR_ORERR;\n+\tout_be16(®s->isr_imr.imr, imr);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * psc_i2s_shutdown: shutdown the data transfer on a stream\n+ *\n+ * Shutdown the PSC if there are no other substreams open.\n+ */\n+void psc_i2s_shutdown(struct snd_pcm_substream *substream,\n+\t\t\t struct snd_soc_dai *dai)\n+{\n+\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n+\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n+\n+\tdev_dbg(psc_i2s->dev, \"psc_i2s_shutdown(substream=%p)\\n\", substream);\n+\n+\t/*\n+\t * If this is the last active substream, disable the PSC and release\n+\t * the IRQ.\n+\t */\n+\tif (!psc_i2s->playback.active &&\n+\t !psc_i2s->capture.active) {\n+\n+\t\t/* Disable all interrupts and reset the PSC */\n+\t\tout_be16(&psc_i2s->psc_regs->isr_imr.imr, 0);\n+\t\tout_8(&psc_i2s->psc_regs->command, 3 << 4); /* reset tx */\n+\t\tout_8(&psc_i2s->psc_regs->command, 2 << 4); /* reset rx */\n+\t\tout_8(&psc_i2s->psc_regs->command, 1 << 4); /* reset mode */\n+\t\tout_8(&psc_i2s->psc_regs->command, 4 << 4); /* reset error */\n+\n+\t\t/* Release irqs */\n+\t\tfree_irq(psc_i2s->irq, psc_i2s);\n+\t\tfree_irq(psc_i2s->capture.irq, &psc_i2s->capture);\n+\t\tfree_irq(psc_i2s->playback.irq, &psc_i2s->playback);\n+\t}\n+}\n+\n+/* ---------------------------------------------------------------------\n+ * The PSC DMA 'ASoC platform' driver\n+ *\n+ * Can be referenced by an 'ASoC machine' driver\n+ * This driver only deals with the audio bus; it doesn't have any\n+ * interaction with the attached codec\n+ */\n+\n+static const struct snd_pcm_hardware psc_i2s_pcm_hardware = {\n+\t.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |\n+\t\tSNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |\n+\t\tSNDRV_PCM_INFO_BATCH,\n+\t.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\n+\t\t SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,\n+\t.rate_min = 8000,\n+\t.rate_max = 48000,\n+\t.channels_min = 2,\n+\t.channels_max = 2,\n+\t.period_bytes_max\t= 1024 * 1024,\n+\t.period_bytes_min\t= 32,\n+\t.periods_min\t\t= 2,\n+\t.periods_max\t\t= 256,\n+\t.buffer_bytes_max\t= 2 * 1024 * 1024,\n+\t.fifo_size\t\t= 0,\n+};\n+\n+static int psc_i2s_pcm_open(struct snd_pcm_substream *substream)\n+{\n+\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n+\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n+\tstruct psc_i2s_stream *s;\n+\n+\tdev_dbg(psc_i2s->dev, \"psc_i2s_pcm_open(substream=%p)\\n\", substream);\n+\n+\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n+\t\ts = &psc_i2s->capture;\n+\telse\n+\t\ts = &psc_i2s->playback;\n+\n+\tsnd_soc_set_runtime_hwparams(substream, &psc_i2s_pcm_hardware);\n+\n+\ts->stream = substream;\n+\treturn 0;\n+}\n+\n+static int psc_i2s_pcm_close(struct snd_pcm_substream *substream)\n+{\n+\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n+\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n+\tstruct psc_i2s_stream *s;\n+\n+\tdev_dbg(psc_i2s->dev, \"psc_i2s_pcm_close(substream=%p)\\n\", substream);\n+\n+\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n+\t\ts = &psc_i2s->capture;\n+\telse\n+\t\ts = &psc_i2s->playback;\n+\n+\ts->stream = NULL;\n+\treturn 0;\n+}\n+\n+static snd_pcm_uframes_t\n+psc_i2s_pcm_pointer(struct snd_pcm_substream *substream)\n+{\n+\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n+\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n+\tstruct psc_i2s_stream *s;\n+\tdma_addr_t count;\n+\n+\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n+\t\ts = &psc_i2s->capture;\n+\telse\n+\t\ts = &psc_i2s->playback;\n+\n+\tcount = s->period_current_pt - s->period_start;\n+\n+\treturn bytes_to_frames(substream->runtime, count);\n+}\n+\n+static struct snd_pcm_ops psc_i2s_pcm_ops = {\n+\t.open\t\t= psc_i2s_pcm_open,\n+\t.close\t\t= psc_i2s_pcm_close,\n+\t.ioctl\t\t= snd_pcm_lib_ioctl,\n+\t.pointer\t= psc_i2s_pcm_pointer,\n+};\n+\n+static u64 psc_i2s_pcm_dmamask = 0xffffffff;\n+static int psc_i2s_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,\n+\t\t\t struct snd_pcm *pcm)\n+{\n+\tstruct snd_soc_pcm_runtime *rtd = pcm->private_data;\n+\tsize_t size = psc_i2s_pcm_hardware.buffer_bytes_max;\n+\tint rc = 0;\n+\n+\tdev_dbg(rtd->socdev->dev, \"psc_i2s_pcm_new(card=%p, dai=%p, pcm=%p)\\n\",\n+\t\tcard, dai, pcm);\n+\n+\tif (!card->dev->dma_mask)\n+\t\tcard->dev->dma_mask = &psc_i2s_pcm_dmamask;\n+\tif (!card->dev->coherent_dma_mask)\n+\t\tcard->dev->coherent_dma_mask = 0xffffffff;\n+\n+\tif (pcm->streams[0].substream) {\n+\t\trc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,\n+\t\t\t\t\t&pcm->streams[0].substream->dma_buffer);\n+\t\tif (rc)\n+\t\t\tgoto playback_alloc_err;\n+\t}\n+\n+\tif (pcm->streams[1].substream) {\n+\t\trc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,\n+\t\t\t\t\t&pcm->streams[1].substream->dma_buffer);\n+\t\tif (rc)\n+\t\t\tgoto capture_alloc_err;\n+\t}\n+\n+\treturn 0;\n+\n+ capture_alloc_err:\n+\tif (pcm->streams[0].substream)\n+\t\tsnd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);\n+ playback_alloc_err:\n+\tdev_err(card->dev, \"Cannot allocate buffer(s)\\n\");\n+\treturn -ENOMEM;\n+}\n+\n+static void psc_i2s_pcm_free(struct snd_pcm *pcm)\n+{\n+\tstruct snd_soc_pcm_runtime *rtd = pcm->private_data;\n+\tstruct snd_pcm_substream *substream;\n+\tint stream;\n+\n+\tdev_dbg(rtd->socdev->dev, \"psc_i2s_pcm_free(pcm=%p)\\n\", pcm);\n+\n+\tfor (stream = 0; stream < 2; stream++) {\n+\t\tsubstream = pcm->streams[stream].substream;\n+\t\tif (substream) {\n+\t\t\tsnd_dma_free_pages(&substream->dma_buffer);\n+\t\t\tsubstream->dma_buffer.area = NULL;\n+\t\t\tsubstream->dma_buffer.addr = 0;\n+\t\t}\n+\t}\n+}\n+\n+struct snd_soc_platform psc_i2s_pcm_soc_platform = {\n+\t.name\t\t= \"mpc5200-psc-audio\",\n+\t.pcm_ops\t= &psc_i2s_pcm_ops,\n+\t.pcm_new\t= &psc_i2s_pcm_new,\n+\t.pcm_free\t= &psc_i2s_pcm_free,\n+};\n+\ndiff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h\nnew file mode 100644\nindex 0000000..9a19e8a\n--- /dev/null\n+++ b/sound/soc/fsl/mpc5200_dma.h\n@@ -0,0 +1,81 @@\n+/*\n+ * Freescale MPC5200 Audio DMA driver\n+ */\n+\n+#ifndef __SOUND_SOC_FSL_MPC5200_DMA_H__\n+#define __SOUND_SOC_FSL_MPC5200_DMA_H__\n+\n+/**\n+ * psc_i2s_stream - Data specific to a single stream (playback or capture)\n+ * @active:\t\tflag indicating if the stream is active\n+ * @psc_i2s:\t\tpointer back to parent psc_i2s data structure\n+ * @bcom_task:\t\tbestcomm task structure\n+ * @irq:\t\tirq number for bestcomm task\n+ * @period_start:\tphysical address of start of DMA region\n+ * @period_end:\t\tphysical address of end of DMA region\n+ * @period_next_pt:\tphysical address of next DMA buffer to enqueue\n+ * @period_bytes:\tsize of DMA period in bytes\n+ */\n+struct psc_i2s_stream {\n+\tint active;\n+\tstruct psc_i2s *psc_i2s;\n+\tstruct bcom_task *bcom_task;\n+\tint irq;\n+\tstruct snd_pcm_substream *stream;\n+\tdma_addr_t period_start;\n+\tdma_addr_t period_end;\n+\tdma_addr_t period_next_pt;\n+\tdma_addr_t period_current_pt;\n+\tint period_bytes;\n+};\n+\n+/**\n+ * psc_i2s - Private driver data\n+ * @name: short name for this device (\"PSC0\", \"PSC1\", etc)\n+ * @psc_regs: pointer to the PSC's registers\n+ * @fifo_regs: pointer to the PSC's FIFO registers\n+ * @irq: IRQ of this PSC\n+ * @dev: struct device pointer\n+ * @dai: the CPU DAI for this device\n+ * @sicr: Base value used in serial interface control register; mode is ORed\n+ * with this value.\n+ * @playback: Playback stream context data\n+ * @capture: Capture stream context data\n+ */\n+struct psc_i2s {\n+\tchar name[32];\n+\tstruct mpc52xx_psc __iomem *psc_regs;\n+\tstruct mpc52xx_psc_fifo __iomem *fifo_regs;\n+\tunsigned int irq;\n+\tstruct device *dev;\n+\tstruct snd_soc_dai dai;\n+\tspinlock_t lock;\n+\tu32 sicr;\n+\n+\t/* per-stream data */\n+\tstruct psc_i2s_stream playback;\n+\tstruct psc_i2s_stream capture;\n+\n+\t/* Statistics */\n+\tstruct {\n+\t\tint overrun_count;\n+\t\tint underrun_count;\n+\t} stats;\n+};\n+\n+\n+int psc_i2s_startup(struct snd_pcm_substream *substream,\n+\t\t\t struct snd_soc_dai *dai);\n+\n+int psc_i2s_hw_free(struct snd_pcm_substream *substream,\n+\t\t\t struct snd_soc_dai *dai);\n+\n+void psc_i2s_shutdown(struct snd_pcm_substream *substream,\n+\t\t\t struct snd_soc_dai *dai);\n+\n+int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,\n+\t\t\t struct snd_soc_dai *dai);\n+\n+extern struct snd_soc_platform psc_i2s_pcm_soc_platform;\n+\n+#endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */\ndiff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c\nindex 1111c71..8974b53 100644\n--- a/sound/soc/fsl/mpc5200_psc_i2s.c\n+++ b/sound/soc/fsl/mpc5200_psc_i2s.c\n@@ -25,6 +25,8 @@\n #include <sysdev/bestcomm/gen_bd.h>\n #include <asm/mpc52xx_psc.h>\n \n+#include \"mpc5200_dma.h\"\n+\n MODULE_AUTHOR(\"Grant Likely <grant.likely@secretlab.ca>\");\n MODULE_DESCRIPTION(\"Freescale MPC5200 PSC in I2S mode ASoC Driver\");\n MODULE_LICENSE(\"GPL\");\n@@ -47,179 +49,6 @@ MODULE_LICENSE(\"GPL\");\n \t\t\t SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE | \\\n \t\t\t SNDRV_PCM_FMTBIT_S32_BE)\n \n-/**\n- * psc_i2s_stream - Data specific to a single stream (playback or capture)\n- * @active:\t\tflag indicating if the stream is active\n- * @psc_i2s:\t\tpointer back to parent psc_i2s data structure\n- * @bcom_task:\t\tbestcomm task structure\n- * @irq:\t\tirq number for bestcomm task\n- * @period_start:\tphysical address of start of DMA region\n- * @period_end:\t\tphysical address of end of DMA region\n- * @period_next_pt:\tphysical address of next DMA buffer to enqueue\n- * @period_bytes:\tsize of DMA period in bytes\n- */\n-struct psc_i2s_stream {\n-\tint active;\n-\tstruct psc_i2s *psc_i2s;\n-\tstruct bcom_task *bcom_task;\n-\tint irq;\n-\tstruct snd_pcm_substream *stream;\n-\tdma_addr_t period_start;\n-\tdma_addr_t period_end;\n-\tdma_addr_t period_next_pt;\n-\tdma_addr_t period_current_pt;\n-\tint period_bytes;\n-};\n-\n-/**\n- * psc_i2s - Private driver data\n- * @name: short name for this device (\"PSC0\", \"PSC1\", etc)\n- * @psc_regs: pointer to the PSC's registers\n- * @fifo_regs: pointer to the PSC's FIFO registers\n- * @irq: IRQ of this PSC\n- * @dev: struct device pointer\n- * @dai: the CPU DAI for this device\n- * @sicr: Base value used in serial interface control register; mode is ORed\n- * with this value.\n- * @playback: Playback stream context data\n- * @capture: Capture stream context data\n- */\n-struct psc_i2s {\n-\tchar name[32];\n-\tstruct mpc52xx_psc __iomem *psc_regs;\n-\tstruct mpc52xx_psc_fifo __iomem *fifo_regs;\n-\tunsigned int irq;\n-\tstruct device *dev;\n-\tstruct snd_soc_dai dai;\n-\tspinlock_t lock;\n-\tu32 sicr;\n-\n-\t/* per-stream data */\n-\tstruct psc_i2s_stream playback;\n-\tstruct psc_i2s_stream capture;\n-\n-\t/* Statistics */\n-\tstruct {\n-\t\tint overrun_count;\n-\t\tint underrun_count;\n-\t} stats;\n-};\n-\n-/*\n- * Interrupt handlers\n- */\n-static irqreturn_t psc_i2s_status_irq(int irq, void *_psc_i2s)\n-{\n-\tstruct psc_i2s *psc_i2s = _psc_i2s;\n-\tstruct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;\n-\tu16 isr;\n-\n-\tisr = in_be16(®s->mpc52xx_psc_isr);\n-\n-\t/* Playback underrun error */\n-\tif (psc_i2s->playback.active && (isr & MPC52xx_PSC_IMR_TXEMP))\n-\t\tpsc_i2s->stats.underrun_count++;\n-\n-\t/* Capture overrun error */\n-\tif (psc_i2s->capture.active && (isr & MPC52xx_PSC_IMR_ORERR))\n-\t\tpsc_i2s->stats.overrun_count++;\n-\n-\tout_8(®s->command, 4 << 4);\t/* reset the error status */\n-\n-\treturn IRQ_HANDLED;\n-}\n-\n-/**\n- * psc_i2s_bcom_enqueue_next_buffer - Enqueue another audio buffer\n- * @s: pointer to stream private data structure\n- *\n- * Enqueues another audio period buffer into the bestcomm queue.\n- *\n- * Note: The routine must only be called when there is space available in\n- * the queue. Otherwise the enqueue will fail and the audio ring buffer\n- * will get out of sync\n- */\n-static void psc_i2s_bcom_enqueue_next_buffer(struct psc_i2s_stream *s)\n-{\n-\tstruct bcom_bd *bd;\n-\n-\t/* Prepare and enqueue the next buffer descriptor */\n-\tbd = bcom_prepare_next_buffer(s->bcom_task);\n-\tbd->status = s->period_bytes;\n-\tbd->data[0] = s->period_next_pt;\n-\tbcom_submit_next_buffer(s->bcom_task, NULL);\n-\n-\t/* Update for next period */\n-\ts->period_next_pt += s->period_bytes;\n-\tif (s->period_next_pt >= s->period_end)\n-\t\ts->period_next_pt = s->period_start;\n-}\n-\n-/* Bestcomm DMA irq handler */\n-static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream)\n-{\n-\tstruct psc_i2s_stream *s = _psc_i2s_stream;\n-\n-\t/* For each finished period, dequeue the completed period buffer\n-\t * and enqueue a new one in it's place. */\n-\twhile (bcom_buffer_done(s->bcom_task)) {\n-\t\tbcom_retrieve_buffer(s->bcom_task, NULL, NULL);\n-\t\ts->period_current_pt += s->period_bytes;\n-\t\tif (s->period_current_pt >= s->period_end)\n-\t\t\ts->period_current_pt = s->period_start;\n-\t\tpsc_i2s_bcom_enqueue_next_buffer(s);\n-\t\tbcom_enable(s->bcom_task);\n-\t}\n-\n-\t/* If the stream is active, then also inform the PCM middle layer\n-\t * of the period finished event. */\n-\tif (s->active)\n-\t\tsnd_pcm_period_elapsed(s->stream);\n-\n-\treturn IRQ_HANDLED;\n-}\n-\n-/**\n- * psc_i2s_startup: create a new substream\n- *\n- * This is the first function called when a stream is opened.\n- *\n- * If this is the first stream open, then grab the IRQ and program most of\n- * the PSC registers.\n- */\n-static int psc_i2s_startup(struct snd_pcm_substream *substream,\n-\t\t\t struct snd_soc_dai *dai)\n-{\n-\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n-\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n-\tint rc;\n-\n-\tdev_dbg(psc_i2s->dev, \"psc_i2s_startup(substream=%p)\\n\", substream);\n-\n-\tif (!psc_i2s->playback.active &&\n-\t !psc_i2s->capture.active) {\n-\t\t/* Setup the IRQs */\n-\t\trc = request_irq(psc_i2s->irq, &psc_i2s_status_irq, IRQF_SHARED,\n-\t\t\t\t \"psc-i2s-status\", psc_i2s);\n-\t\trc |= request_irq(psc_i2s->capture.irq,\n-\t\t\t\t &psc_i2s_bcom_irq, IRQF_SHARED,\n-\t\t\t\t \"psc-i2s-capture\", &psc_i2s->capture);\n-\t\trc |= request_irq(psc_i2s->playback.irq,\n-\t\t\t\t &psc_i2s_bcom_irq, IRQF_SHARED,\n-\t\t\t\t \"psc-i2s-playback\", &psc_i2s->playback);\n-\t\tif (rc) {\n-\t\t\tfree_irq(psc_i2s->irq, psc_i2s);\n-\t\t\tfree_irq(psc_i2s->capture.irq,\n-\t\t\t\t &psc_i2s->capture);\n-\t\t\tfree_irq(psc_i2s->playback.irq,\n-\t\t\t\t &psc_i2s->playback);\n-\t\t\treturn -ENODEV;\n-\t\t}\n-\t}\n-\n-\treturn 0;\n-}\n-\n static int psc_i2s_hw_params(struct snd_pcm_substream *substream,\n \t\t\t\t struct snd_pcm_hw_params *params,\n \t\t\t\t struct snd_soc_dai *dai)\n@@ -258,164 +87,6 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,\n \treturn 0;\n }\n \n-static int psc_i2s_hw_free(struct snd_pcm_substream *substream,\n-\t\t\t struct snd_soc_dai *dai)\n-{\n-\tsnd_pcm_set_runtime_buffer(substream, NULL);\n-\treturn 0;\n-}\n-\n-/**\n- * psc_i2s_trigger: start and stop the DMA transfer.\n- *\n- * This function is called by ALSA to start, stop, pause, and resume the DMA\n- * transfer of data.\n- */\n-static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,\n-\t\t\t struct snd_soc_dai *dai)\n-{\n-\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n-\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n-\tstruct snd_pcm_runtime *runtime = substream->runtime;\n-\tstruct psc_i2s_stream *s;\n-\tstruct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs;\n-\tu16 imr;\n-\tu8 psc_cmd;\n-\tunsigned long flags;\n-\n-\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n-\t\ts = &psc_i2s->capture;\n-\telse\n-\t\ts = &psc_i2s->playback;\n-\n-\tdev_dbg(psc_i2s->dev, \"psc_i2s_trigger(substream=%p, cmd=%i)\"\n-\t\t\" stream_id=%i\\n\",\n-\t\tsubstream, cmd, substream->pstr->stream);\n-\n-\tswitch (cmd) {\n-\tcase SNDRV_PCM_TRIGGER_START:\n-\t\ts->period_bytes = frames_to_bytes(runtime,\n-\t\t\t\t\t\t runtime->period_size);\n-\t\ts->period_start = virt_to_phys(runtime->dma_area);\n-\t\ts->period_end = s->period_start +\n-\t\t\t\t(s->period_bytes * runtime->periods);\n-\t\ts->period_next_pt = s->period_start;\n-\t\ts->period_current_pt = s->period_start;\n-\t\ts->active = 1;\n-\n-\t\t/* First; reset everything */\n-\t\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {\n-\t\t\tout_8(®s->command, MPC52xx_PSC_RST_RX);\n-\t\t\tout_8(®s->command, MPC52xx_PSC_RST_ERR_STAT);\n-\t\t} else {\n-\t\t\tout_8(®s->command, MPC52xx_PSC_RST_TX);\n-\t\t\tout_8(®s->command, MPC52xx_PSC_RST_ERR_STAT);\n-\t\t}\n-\n-\t\t/* Next, fill up the bestcomm bd queue and enable DMA.\n-\t\t * This will begin filling the PSC's fifo. */\n-\t\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n-\t\t\tbcom_gen_bd_rx_reset(s->bcom_task);\n-\t\telse\n-\t\t\tbcom_gen_bd_tx_reset(s->bcom_task);\n-\t\twhile (!bcom_queue_full(s->bcom_task))\n-\t\t\tpsc_i2s_bcom_enqueue_next_buffer(s);\n-\t\tbcom_enable(s->bcom_task);\n-\n-\t\t/* Due to errata in the i2s mode; need to line up enabling\n-\t\t * the transmitter with a transition on the frame sync\n-\t\t * line */\n-\n-\t\tspin_lock_irqsave(&psc_i2s->lock, flags);\n-\t\t/* first make sure it is low */\n-\t\twhile ((in_8(®s->ipcr_acr.ipcr) & 0x80) != 0)\n-\t\t\t;\n-\t\t/* then wait for the transition to high */\n-\t\twhile ((in_8(®s->ipcr_acr.ipcr) & 0x80) == 0)\n-\t\t\t;\n-\t\t/* Finally, enable the PSC.\n-\t\t * Receiver must always be enabled; even when we only want\n-\t\t * transmit. (see 15.3.2.3 of MPC5200B User's Guide) */\n-\t\tpsc_cmd = MPC52xx_PSC_RX_ENABLE;\n-\t\tif (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)\n-\t\t\tpsc_cmd |= MPC52xx_PSC_TX_ENABLE;\n-\t\tout_8(®s->command, psc_cmd);\n-\t\tspin_unlock_irqrestore(&psc_i2s->lock, flags);\n-\n-\t\tbreak;\n-\n-\tcase SNDRV_PCM_TRIGGER_STOP:\n-\t\t/* Turn off the PSC */\n-\t\ts->active = 0;\n-\t\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) {\n-\t\t\tif (!psc_i2s->playback.active) {\n-\t\t\t\tout_8(®s->command, 2 << 4);\t/* reset rx */\n-\t\t\t\tout_8(®s->command, 3 << 4);\t/* reset tx */\n-\t\t\t\tout_8(®s->command, 4 << 4);\t/* reset err */\n-\t\t\t}\n-\t\t} else {\n-\t\t\tout_8(®s->command, 3 << 4);\t/* reset tx */\n-\t\t\tout_8(®s->command, 4 << 4);\t/* reset err */\n-\t\t\tif (!psc_i2s->capture.active)\n-\t\t\t\tout_8(®s->command, 2 << 4);\t/* reset rx */\n-\t\t}\n-\n-\t\tbcom_disable(s->bcom_task);\n-\t\twhile (!bcom_queue_empty(s->bcom_task))\n-\t\t\tbcom_retrieve_buffer(s->bcom_task, NULL, NULL);\n-\n-\t\tbreak;\n-\n-\tdefault:\n-\t\tdev_dbg(psc_i2s->dev, \"invalid command\\n\");\n-\t\treturn -EINVAL;\n-\t}\n-\n-\t/* Update interrupt enable settings */\n-\timr = 0;\n-\tif (psc_i2s->playback.active)\n-\t\timr |= MPC52xx_PSC_IMR_TXEMP;\n-\tif (psc_i2s->capture.active)\n-\t\timr |= MPC52xx_PSC_IMR_ORERR;\n-\tout_be16(®s->isr_imr.imr, imr);\n-\n-\treturn 0;\n-}\n-\n-/**\n- * psc_i2s_shutdown: shutdown the data transfer on a stream\n- *\n- * Shutdown the PSC if there are no other substreams open.\n- */\n-static void psc_i2s_shutdown(struct snd_pcm_substream *substream,\n-\t\t\t struct snd_soc_dai *dai)\n-{\n-\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n-\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n-\n-\tdev_dbg(psc_i2s->dev, \"psc_i2s_shutdown(substream=%p)\\n\", substream);\n-\n-\t/*\n-\t * If this is the last active substream, disable the PSC and release\n-\t * the IRQ.\n-\t */\n-\tif (!psc_i2s->playback.active &&\n-\t !psc_i2s->capture.active) {\n-\n-\t\t/* Disable all interrupts and reset the PSC */\n-\t\tout_be16(&psc_i2s->psc_regs->isr_imr.imr, 0);\n-\t\tout_8(&psc_i2s->psc_regs->command, 3 << 4); /* reset tx */\n-\t\tout_8(&psc_i2s->psc_regs->command, 2 << 4); /* reset rx */\n-\t\tout_8(&psc_i2s->psc_regs->command, 1 << 4); /* reset mode */\n-\t\tout_8(&psc_i2s->psc_regs->command, 4 << 4); /* reset error */\n-\n-\t\t/* Release irqs */\n-\t\tfree_irq(psc_i2s->irq, psc_i2s);\n-\t\tfree_irq(psc_i2s->capture.irq, &psc_i2s->capture);\n-\t\tfree_irq(psc_i2s->playback.irq, &psc_i2s->playback);\n-\t}\n-}\n-\n /**\n * psc_i2s_set_sysclk: set the clock frequency and direction\n *\n@@ -495,158 +166,6 @@ static struct snd_soc_dai psc_i2s_dai_template = {\n };\n \n /* ---------------------------------------------------------------------\n- * The PSC I2S 'ASoC platform' driver\n- *\n- * Can be referenced by an 'ASoC machine' driver\n- * This driver only deals with the audio bus; it doesn't have any\n- * interaction with the attached codec\n- */\n-\n-static const struct snd_pcm_hardware psc_i2s_pcm_hardware = {\n-\t.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |\n-\t\tSNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |\n-\t\tSNDRV_PCM_INFO_BATCH,\n-\t.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\n-\t\t SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,\n-\t.rate_min = 8000,\n-\t.rate_max = 48000,\n-\t.channels_min = 2,\n-\t.channels_max = 2,\n-\t.period_bytes_max\t= 1024 * 1024,\n-\t.period_bytes_min\t= 32,\n-\t.periods_min\t\t= 2,\n-\t.periods_max\t\t= 256,\n-\t.buffer_bytes_max\t= 2 * 1024 * 1024,\n-\t.fifo_size\t\t= 0,\n-};\n-\n-static int psc_i2s_pcm_open(struct snd_pcm_substream *substream)\n-{\n-\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n-\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n-\tstruct psc_i2s_stream *s;\n-\n-\tdev_dbg(psc_i2s->dev, \"psc_i2s_pcm_open(substream=%p)\\n\", substream);\n-\n-\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n-\t\ts = &psc_i2s->capture;\n-\telse\n-\t\ts = &psc_i2s->playback;\n-\n-\tsnd_soc_set_runtime_hwparams(substream, &psc_i2s_pcm_hardware);\n-\n-\ts->stream = substream;\n-\treturn 0;\n-}\n-\n-static int psc_i2s_pcm_close(struct snd_pcm_substream *substream)\n-{\n-\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n-\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n-\tstruct psc_i2s_stream *s;\n-\n-\tdev_dbg(psc_i2s->dev, \"psc_i2s_pcm_close(substream=%p)\\n\", substream);\n-\n-\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n-\t\ts = &psc_i2s->capture;\n-\telse\n-\t\ts = &psc_i2s->playback;\n-\n-\ts->stream = NULL;\n-\treturn 0;\n-}\n-\n-static snd_pcm_uframes_t\n-psc_i2s_pcm_pointer(struct snd_pcm_substream *substream)\n-{\n-\tstruct snd_soc_pcm_runtime *rtd = substream->private_data;\n-\tstruct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;\n-\tstruct psc_i2s_stream *s;\n-\tdma_addr_t count;\n-\n-\tif (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)\n-\t\ts = &psc_i2s->capture;\n-\telse\n-\t\ts = &psc_i2s->playback;\n-\n-\tcount = s->period_current_pt - s->period_start;\n-\n-\treturn bytes_to_frames(substream->runtime, count);\n-}\n-\n-static struct snd_pcm_ops psc_i2s_pcm_ops = {\n-\t.open\t\t= psc_i2s_pcm_open,\n-\t.close\t\t= psc_i2s_pcm_close,\n-\t.ioctl\t\t= snd_pcm_lib_ioctl,\n-\t.pointer\t= psc_i2s_pcm_pointer,\n-};\n-\n-static u64 psc_i2s_pcm_dmamask = 0xffffffff;\n-static int psc_i2s_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,\n-\t\t\t struct snd_pcm *pcm)\n-{\n-\tstruct snd_soc_pcm_runtime *rtd = pcm->private_data;\n-\tsize_t size = psc_i2s_pcm_hardware.buffer_bytes_max;\n-\tint rc = 0;\n-\n-\tdev_dbg(rtd->socdev->dev, \"psc_i2s_pcm_new(card=%p, dai=%p, pcm=%p)\\n\",\n-\t\tcard, dai, pcm);\n-\n-\tif (!card->dev->dma_mask)\n-\t\tcard->dev->dma_mask = &psc_i2s_pcm_dmamask;\n-\tif (!card->dev->coherent_dma_mask)\n-\t\tcard->dev->coherent_dma_mask = 0xffffffff;\n-\n-\tif (pcm->streams[0].substream) {\n-\t\trc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,\n-\t\t\t\t\t&pcm->streams[0].substream->dma_buffer);\n-\t\tif (rc)\n-\t\t\tgoto playback_alloc_err;\n-\t}\n-\n-\tif (pcm->streams[1].substream) {\n-\t\trc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, size,\n-\t\t\t\t\t&pcm->streams[1].substream->dma_buffer);\n-\t\tif (rc)\n-\t\t\tgoto capture_alloc_err;\n-\t}\n-\n-\treturn 0;\n-\n- capture_alloc_err:\n-\tif (pcm->streams[0].substream)\n-\t\tsnd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);\n- playback_alloc_err:\n-\tdev_err(card->dev, \"Cannot allocate buffer(s)\\n\");\n-\treturn -ENOMEM;\n-}\n-\n-static void psc_i2s_pcm_free(struct snd_pcm *pcm)\n-{\n-\tstruct snd_soc_pcm_runtime *rtd = pcm->private_data;\n-\tstruct snd_pcm_substream *substream;\n-\tint stream;\n-\n-\tdev_dbg(rtd->socdev->dev, \"psc_i2s_pcm_free(pcm=%p)\\n\", pcm);\n-\n-\tfor (stream = 0; stream < 2; stream++) {\n-\t\tsubstream = pcm->streams[stream].substream;\n-\t\tif (substream) {\n-\t\t\tsnd_dma_free_pages(&substream->dma_buffer);\n-\t\t\tsubstream->dma_buffer.area = NULL;\n-\t\t\tsubstream->dma_buffer.addr = 0;\n-\t\t}\n-\t}\n-}\n-\n-struct snd_soc_platform psc_i2s_pcm_soc_platform = {\n-\t.name\t\t= \"mpc5200-psc-audio\",\n-\t.pcm_ops\t= &psc_i2s_pcm_ops,\n-\t.pcm_new\t= &psc_i2s_pcm_new,\n-\t.pcm_free\t= &psc_i2s_pcm_free,\n-};\n-\n-/* ---------------------------------------------------------------------\n * Sysfs attributes for debugging\n */\n \n", "prefixes": [ "V2", "2/9" ] }