summaryrefslogtreecommitdiff
path: root/packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt
diff options
context:
space:
mode:
authorDenys Dmytriyenko <denis@denix.org>2009-03-17 14:32:59 -0400
committerDenys Dmytriyenko <denis@denix.org>2009-03-17 14:32:59 -0400
commit709c4d66e0b107ca606941b988bad717c0b45d9b (patch)
tree37ee08b1eb308f3b2b6426d5793545c38396b838 /packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt
parentfa6cd5a3b993f16c27de4ff82b42684516d433ba (diff)
rename packages/ to recipes/ per earlier agreement
See links below for more details: http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326 http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816 Signed-off-by: Denys Dmytriyenko <denis@denix.org> Acked-by: Mike Westerhof <mwester@dls.net> Acked-by: Philip Balister <philip@balister.org> Acked-by: Khem Raj <raj.khem@gmail.com> Acked-by: Marcin Juszkiewicz <hrw@openembedded.org> Acked-by: Koen Kooi <koen@openembedded.org> Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt')
-rw-r--r--packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt834
1 files changed, 0 insertions, 834 deletions
diff --git a/packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt b/packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt
deleted file mode 100644
index a352f0e2f5..0000000000
--- a/packages/linux/linux-efika/0001-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt
+++ /dev/null
@@ -1,834 +0,0 @@
-I cleaned up the setting of the port_config register on the MPC5200B.
-This driver now touches only the two relevant bits without overriding
-the others.
-
-Signed-off-by: Leon Woestenberg <leonw@mailcan.com>
-
-From 144658ad3d23bb426e29562235e40f0f9797a9c7 Mon Sep 17 00:00:00 2001
-From: Sylvain Munaut <tnt@246tNt.com>
-Date: Mon, 18 Dec 2006 22:51:38 +0100
-Subject: [PATCH] sound: Add support for the MPC52xx PSC AC97 Link
-
-Messy driver, to be cleaned ... a lot ...
-
-Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
----
- include/asm-ppc/mpc52xx_psc.h | 10 -
- sound/ppc/Kconfig | 16 +
- sound/ppc/Makefile | 3
- sound/ppc/mpc52xx_ac97.c | 738 +++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 765 insertions(+), 2 deletions(-)
-
-Index: linux-2.6.19-rc6_efika/include/asm-ppc/mpc52xx_psc.h
-===================================================================
---- linux-2.6.19-rc6_efika.orig/include/asm-ppc/mpc52xx_psc.h 2007-01-14 19:45:07.000000000 +0100
-+++ linux-2.6.19-rc6_efika/include/asm-ppc/mpc52xx_psc.h 2007-01-14 19:45:07.000000000 +0100
-@@ -28,6 +28,10 @@
- #define MPC52xx_PSC_MAXNUM 6
-
- /* Programmable Serial Controller (PSC) status register bits */
-+#define MPC52xx_PSC_SR_UNEX_RX 0x0001
-+#define MPC52xx_PSC_SR_DATA_VAL 0x0002
-+#define MPC52xx_PSC_SR_DATA_OVR 0x0004
-+#define MPC52xx_PSC_SR_CMDSEND 0x0008
- #define MPC52xx_PSC_SR_CDE 0x0080
- #define MPC52xx_PSC_SR_RXRDY 0x0100
- #define MPC52xx_PSC_SR_RXFULL 0x0200
-@@ -132,8 +136,10 @@
- u8 reserved5[3];
- u8 ctlr; /* PSC + 0x1c */
- u8 reserved6[3];
-- u16 ccr; /* PSC + 0x20 */
-- u8 reserved7[14];
-+ u32 ccr; /* PSC + 0x20 */
-+ u32 ac97_slots; /* PSC + 0x24 */
-+ u32 ac97_cmd; /* PSC + 0x28 */
-+ u32 ac97_data; /* PSC + 0x2c */
- u8 ivr; /* PSC + 0x30 */
- u8 reserved8[3];
- u8 ip; /* PSC + 0x34 */
-Index: linux-2.6.19-rc6_efika/sound/ppc/Kconfig
-===================================================================
---- linux-2.6.19-rc6_efika.orig/sound/ppc/Kconfig 2007-01-14 19:45:07.000000000 +0100
-+++ linux-2.6.19-rc6_efika/sound/ppc/Kconfig 2007-01-14 19:45:07.000000000 +0100
-@@ -33,3 +33,19 @@
- option.
-
- endmenu
-+
-+
-+# ALSA ppc drivers
-+
-+menu "ALSA PPC devices"
-+ depends on SND!=n && PPC
-+
-+config SND_PPC_MPC52xx_AC97
-+ tristate "Freescale MPC52xx AC97 interface support"
-+ depends on SND && PPC_MPC52xx
-+ select SND_AC97_CODEC
-+ help
-+ Say Y or M if you want to support any AC97 codec attached to
-+ the Freescqle MPC52xx AC97 interface.
-+
-+endmenu
-Index: linux-2.6.19-rc6_efika/sound/ppc/Makefile
-===================================================================
---- linux-2.6.19-rc6_efika.orig/sound/ppc/Makefile 2007-01-14 19:45:07.000000000 +0100
-+++ linux-2.6.19-rc6_efika/sound/ppc/Makefile 2007-01-14 19:45:07.000000000 +0100
-@@ -4,6 +4,9 @@
- #
-
- snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
-+snd-mpc52xx-ac97-objs := mpc52xx_ac97.o
-
- # Toplevel Module Dependency
- obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
-+
-+obj-$(CONFIG_SND_PPC_MPC52xx_AC97) += snd-mpc52xx-ac97.o
-Index: linux-2.6.19-rc6_efika/sound/ppc/mpc52xx_ac97.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.19-rc6_efika/sound/ppc/mpc52xx_ac97.c 2007-01-14 22:45:55.000000000 +0100
-@@ -0,0 +1,742 @@
-+/*
-+ * Driver for the PSC of the Freescale MPC52xx configured as AC97 interface
-+ *
-+ *
-+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
-+ *
-+ * This file is licensed under the terms of the GNU General Public License
-+ * version 2. This program is licensed "as is" without any warranty of any
-+ * kind, whether express or implied.
-+ */
-+
-+#define DEBUG
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/interrupt.h>
-+
-+#include <sound/driver.h>
-+#include <sound/core.h>
-+#include <sound/initval.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/ac97_codec.h>
-+
-+#include <asm/of_platform.h>
-+#include <asm/mpc52xx_psc.h>
-+
-+
-+#define DRV_NAME "mpc52xx-psc-ac97"
-+
-+
-+/* ======================================================================== */
-+/* Structs / Defines */
-+/* ======================================================================== */
-+
-+/* Private structure */
-+struct mpc52xx_ac97_priv {
-+ struct device *dev;
-+ resource_size_t mem_start;
-+ resource_size_t mem_len;
-+ int irq;
-+ struct mpc52xx_psc __iomem *psc;
-+ struct snd_card *card;
-+ struct snd_pcm *pcm;
-+ struct snd_ac97 *ac97;
-+
-+ struct snd_pcm_substream *substream_playback;
-+ unsigned int buf_pos;
-+};
-+
-+/* Register bit definition (AC97 mode specific) */
-+#define PSC_AC97_SLOT_BIT(n) (1<<(12-n))
-+#define PSC_AC97_SLOTS_XMIT_SHIFT 16
-+#define PSC_AC97_SLOTS_RECV_SHIFT 0
-+
-+
-+
-+/* ======================================================================== */
-+/* ISR routine */
-+/* ======================================================================== */
-+
-+static irqreturn_t
-+mpc52xx_ac97_irq(int irq, void *dev_id)
-+{
-+ struct mpc52xx_ac97_priv *priv = dev_id;
-+
-+ static int icnt = 0;
-+ #if 0
-+ {
-+ unsigned int val;
-+// val = in_be32(&priv->psc->ac97_data);
-+ printk(KERN_INFO "mpc52xx_ac97_irq fired (isr=%04x, status=%04x) %08x\n", in_be16(&priv->psc->mpc52xx_psc_imr), in_be16(&priv->psc->mpc52xx_psc_status), val);
-+ out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
-+ }
-+ #endif
-+
-+ /* Anti Crash during dev ;) */
-+ #if 0
-+ if ((icnt++) > 50000)
-+ out_be16(&priv->psc->mpc52xx_psc_imr, 0);
-+ #endif
-+
-+ /* Copy 64 data into the buffer */
-+ if (in_be16(&priv->psc->mpc52xx_psc_imr) & 0x0100) {
-+ if (priv->substream_playback) {
-+ struct snd_pcm_runtime *rt;
-+
-+ rt = priv->substream_playback->runtime;
-+
-+ if (snd_pcm_playback_hw_avail(rt) < bytes_to_frames(rt,128)) {
-+ int i;
-+ /* Push silence */
-+ for (i=0; i<64; i++)
-+ out_be32(&priv->psc->mpc52xx_psc_buffer_32, 0x00000800);
-+ printk(KERN_DEBUG "pushed silence ...\n");
-+ } else {
-+ int i;
-+ unsigned short *data;
-+
-+ data = (unsigned short *)
-+ (&rt->dma_area[frames_to_bytes(rt, priv->buf_pos)]);
-+
-+ for (i=0; i<64; i++)
-+ out_be32(&priv->psc->mpc52xx_psc_buffer_32,
-+ (((unsigned int)data[i]) << 16) | 0x00000000);
-+ /* Setting the sof bit looks useless */
-+
-+ priv->buf_pos += bytes_to_frames(rt,128);;
-+ if (priv->buf_pos >= rt->buffer_size)
-+ priv->buf_pos = 0;
-+
-+ snd_pcm_period_elapsed(priv->substream_playback);
-+ }
-+ } else {
-+ out_be16(&priv->psc->mpc52xx_psc_imr, 0);
-+ printk(KERN_DEBUG "Interrupt with no stream ...\n");
-+ }
-+ } else {
-+ printk(KERN_ERR "Spurious int\n");
-+ }
-+
-+ return IRQ_HANDLED;
-+}
-+
-+
-+/* ======================================================================== */
-+/* PCM interface */
-+/* ======================================================================== */
-+
-+/* HW desc */
-+
-+static struct snd_pcm_hardware mpc52xx_ac97_hw = {
-+ .info = SNDRV_PCM_INFO_INTERLEAVED |
-+ SNDRV_PCM_INFO_MMAP |
-+ SNDRV_PCM_INFO_MMAP_VALID,
-+ .formats = SNDRV_PCM_FMTBIT_S16_BE,
-+ .rates = SNDRV_PCM_RATE_8000_48000,
-+ .rate_min = 8000,
-+ .rate_max = 48000,
-+ .channels_min = 1,
-+ .channels_max = 2, /* Support for more ? */
-+ .buffer_bytes_max = 128*1024,
-+ .period_bytes_min = 128, /* 32, */
-+ .period_bytes_max = 128, /* 16*1024, */
-+ .periods_min = 8,
-+ .periods_max = 256,
-+ .fifo_size = 512,
-+};
-+
-+
-+/* Playback */
-+
-+static int
-+mpc52xx_ac97_playback_open(struct snd_pcm_substream *substream)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+
-+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_open(%p)\n", substream);
-+
-+ substream->runtime->hw = mpc52xx_ac97_hw;
-+
-+ priv->substream_playback = substream;
-+ priv->buf_pos = 0; /* FIXME Do that where ? */
-+
-+ return 0; /* FIXME */
-+}
-+
-+static int
-+mpc52xx_ac97_playback_close(struct snd_pcm_substream *substream)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_close(%p)\n", substream);
-+ priv->substream_playback = NULL;
-+ return 0; /* FIXME */
-+}
-+
-+static int
-+mpc52xx_ac97_playback_prepare(struct snd_pcm_substream *substream)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+
-+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_prepare(%p)\n", substream);
-+
-+ /* FIXME, need a spinlock to protect access */
-+ if (substream->runtime->channels == 1)
-+ out_be32(&priv->psc->ac97_slots, 0x01000000);
-+ else
-+ out_be32(&priv->psc->ac97_slots, 0x03000000);
-+
-+ snd_ac97_set_rate(priv->ac97, AC97_PCM_FRONT_DAC_RATE, substream->runtime->rate);
-+
-+ return 0; /* FIXME */
-+}
-+
-+
-+/* Capture */
-+
-+static int
-+mpc52xx_ac97_capture_open(struct snd_pcm_substream *substream)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+ return 0; /* FIXME */
-+}
-+
-+static int
-+mpc52xx_ac97_capture_close(struct snd_pcm_substream *substream)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+ return 0; /* FIXME */
-+}
-+
-+static int
-+mpc52xx_ac97_capture_prepare(struct snd_pcm_substream *substream)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+ return 0; /* FIXME */
-+}
-+
-+
-+/* Common */
-+
-+static int
-+mpc52xx_ac97_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+ int rv;
-+
-+ dev_dbg(priv->dev, "mpc52xx_ac97_hw_params(%p)\n", substream);
-+
-+ rv = snd_pcm_lib_malloc_pages(substream,
-+ params_buffer_bytes(params));
-+ if (rv < 0) {
-+ printk(KERN_ERR "hw params failes\n"); /* FIXME */
-+ return rv;
-+ }
-+
-+ printk(KERN_DEBUG "%d %d %d\n", params_buffer_bytes(params), params_period_bytes(params), params_periods(params));
-+
-+
-+ return 0;
-+}
-+
-+static int
-+mpc52xx_ac97_hw_free(struct snd_pcm_substream *substream)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+
-+ dev_dbg(priv->dev, "mpc52xx_ac97_hw_free(%p)\n", substream);
-+
-+ return snd_pcm_lib_free_pages(substream);
-+}
-+
-+static int
-+mpc52xx_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+ int rv = 0;
-+
-+ dev_dbg(priv->dev, "mpc52xx_ac97_trigger(%p,%d)\n", substream, cmd);
-+
-+ switch (cmd) {
-+ case SNDRV_PCM_TRIGGER_START:
-+ /* Enable TX interrupt */
-+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0100); // 0x0100
-+
-+ break;
-+
-+ case SNDRV_PCM_TRIGGER_STOP:
-+ /* Disable TX interrupt */
-+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
-+
-+ break;
-+
-+ default:
-+ rv = -EINVAL;
-+ }
-+
-+ /* FIXME */
-+ return rv;
-+}
-+
-+static snd_pcm_uframes_t
-+mpc52xx_ac97_pointer(struct snd_pcm_substream *substream)
-+{
-+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
-+
-+// dev_dbg(priv->dev, "mpc52xx_ac97_pointer(%p)\n", substream);
-+
-+ if (substream->runtime->channels == 1)
-+ return priv->buf_pos; /* FIXME */
-+ else
-+ return priv->buf_pos >> 1; /* FIXME */
-+}
-+
-+
-+/* Ops */
-+
-+static struct snd_pcm_ops mpc52xx_ac97_playback_ops = {
-+ .open = mpc52xx_ac97_playback_open,
-+ .close = mpc52xx_ac97_playback_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = mpc52xx_ac97_hw_params,
-+ .hw_free = mpc52xx_ac97_hw_free,
-+ .prepare = mpc52xx_ac97_playback_prepare,
-+ .trigger = mpc52xx_ac97_trigger,
-+ .pointer = mpc52xx_ac97_pointer,
-+};
-+
-+static struct snd_pcm_ops mpc52xx_ac97_capture_ops = {
-+ .open = mpc52xx_ac97_capture_open,
-+ .close = mpc52xx_ac97_capture_close,
-+ .ioctl = snd_pcm_lib_ioctl,
-+ .hw_params = mpc52xx_ac97_hw_params,
-+ .hw_free = mpc52xx_ac97_hw_free,
-+ .prepare = mpc52xx_ac97_capture_prepare,
-+ .trigger = mpc52xx_ac97_trigger,
-+ .pointer = mpc52xx_ac97_pointer,
-+};
-+
-+
-+/* ======================================================================== */
-+/* AC97 Bus interface */
-+/* ======================================================================== */
-+
-+static unsigned short
-+mpc52xx_ac97_bus_read(struct snd_ac97 *ac97, unsigned short reg)
-+{
-+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
-+ int timeout;
-+ unsigned int val;
-+
-+ dev_dbg(priv->dev, "ac97 read: reg %04x\n", reg);
-+
-+ /* Wait for it to be ready */
-+ timeout = 1000;
-+ while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
-+ MPC52xx_PSC_SR_CMDSEND) )
-+ udelay(10);
-+
-+ if (!timeout) {
-+ printk(KERN_ERR DRV_NAME ": timeout on ac97 bus (rdy)\n");
-+ return 0xffff;
-+ }
-+
-+ /* Do the read */
-+ out_be32(&priv->psc->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
-+
-+ /* Wait for the answer */
-+ timeout = 1000;
-+ while ((--timeout) && !(in_be16(&priv->psc->mpc52xx_psc_status) &
-+ MPC52xx_PSC_SR_DATA_VAL) )
-+ udelay(10);
-+
-+ if (!timeout) {
-+ printk(KERN_ERR DRV_NAME ": timeout on ac97 read (val)\n");
-+ return 0xffff;
-+ }
-+
-+ /* Get the data */
-+ val = in_be32(&priv->psc->ac97_data);
-+ if ( ((val>>24) & 0x7f) != reg ) {
-+ printk(KERN_ERR DRV_NAME ": reg echo error on ac97 read\n");
-+ return 0xffff;
-+ }
-+ val = (val >> 8) & 0xffff;
-+
-+ dev_dbg(priv->dev, "ac97 read ok: reg %04x val %04x\n",
-+ reg, val);
-+
-+ return (unsigned short) val;
-+}
-+
-+static void
-+mpc52xx_ac97_bus_write(struct snd_ac97 *ac97,
-+ unsigned short reg, unsigned short val)
-+{
-+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
-+ int timeout;
-+
-+ dev_dbg(priv->dev, "ac97 write: reg %04x val %04x\n",
-+ reg, val);
-+
-+ /* Wait for it to be ready */
-+ timeout = 1000;
-+ while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
-+ MPC52xx_PSC_SR_CMDSEND) )
-+ udelay(10);
-+
-+ if (!timeout) {
-+ printk(KERN_ERR DRV_NAME ": timeout on ac97 write\n");
-+ return;
-+ }
-+
-+ /* Write data */
-+ out_be32(&priv->psc->ac97_cmd, ((reg & 0x7f) << 24) | (val << 8));
-+}
-+
-+static void
-+mpc52xx_ac97_bus_reset(struct snd_ac97 *ac97)
-+{
-+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
-+
-+ dev_dbg(priv->dev, "ac97 codec reset\n");
-+
-+ /* Do a cold reset */
-+ out_8(&priv->psc->op1, 0x03);
-+ udelay(10);
-+ out_8(&priv->psc->op0, 0x02);
-+ udelay(50);
-+
-+ /* PSC recover from cold reset (cfr user manual, not sure if useful) */
-+ out_be32(&priv->psc->sicr, in_be32(&priv->psc->sicr));
-+}
-+
-+
-+static struct snd_ac97_bus_ops mpc52xx_ac97_bus_ops = {
-+ .read = mpc52xx_ac97_bus_read,
-+ .write = mpc52xx_ac97_bus_write,
-+ .reset = mpc52xx_ac97_bus_reset,
-+};
-+
-+
-+/* ======================================================================== */
-+/* Sound driver setup */
-+/* ======================================================================== */
-+
-+static int
-+mpc52xx_ac97_setup_pcm(struct mpc52xx_ac97_priv *priv)
-+{
-+ int rv;
-+
-+ rv = snd_pcm_new(priv->card, DRV_NAME "-pcm", 0, 1, 1, &priv->pcm);
-+ if (rv) {
-+ printk(KERN_ERR DRV_NAME ": snd_pcm_new failed\n");
-+ return rv;
-+ }
-+
-+ rv = snd_pcm_lib_preallocate_pages_for_all(priv->pcm,
-+ SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL),
-+ 128*1024, 128*1024);
-+ if (rv) {
-+ printk(KERN_ERR DRV_NAME
-+ ": snd_pcm_lib_preallocate_pages_for_all failed\n");
-+ return rv;
-+ }
-+
-+ snd_pcm_set_ops(priv->pcm, SNDRV_PCM_STREAM_PLAYBACK,
-+ &mpc52xx_ac97_playback_ops);
-+ snd_pcm_set_ops(priv->pcm, SNDRV_PCM_STREAM_CAPTURE,
-+ &mpc52xx_ac97_capture_ops);
-+
-+ priv->pcm->private_data = priv;
-+ priv->pcm->info_flags = 0;
-+
-+ strcpy(priv->pcm->name, "Freescale MPC52xx PSC-AC97 PCM");
-+
-+ return 0;
-+}
-+
-+static int
-+mpc52xx_ac97_setup_mixer(struct mpc52xx_ac97_priv *priv)
-+{
-+ struct snd_ac97_bus *ac97_bus;
-+ struct snd_ac97_template ac97_template;
-+ int rv;
-+
-+ rv = snd_ac97_bus(priv->card, 0, &mpc52xx_ac97_bus_ops, NULL, &ac97_bus);
-+ if (rv) {
-+ printk(KERN_ERR DRV_NAME ": snd_ac97_bus failed\n");
-+ return rv;
-+ }
-+
-+ memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
-+ ac97_template.private_data = priv;
-+
-+ rv = snd_ac97_mixer(ac97_bus, &ac97_template, &priv->ac97);
-+ if (rv) {
-+ printk(KERN_ERR DRV_NAME ": snd_ac97_mixer failed\n");
-+ return rv;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int
-+mpc52xx_ac97_hwinit(struct mpc52xx_ac97_priv *priv)
-+{
-+ /* Reset everything first by safety */
-+ out_8(&priv->psc->command,MPC52xx_PSC_RST_RX);
-+ out_8(&priv->psc->command,MPC52xx_PSC_RST_TX);
-+ out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
-+
-+ /* Do a cold reset of codec */
-+ out_8(&priv->psc->op1, 0x03);
-+ udelay(10);
-+ out_8(&priv->psc->op0, 0x02);
-+ udelay(50);
-+
-+ /* Configure AC97 enhanced mode */
-+ out_be32(&priv->psc->sicr, 0x03010000);
-+
-+ /* No slots active */
-+ out_be32(&priv->psc->ac97_slots, 0x00000000);
-+
-+ /* No IRQ */
-+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
-+
-+ /* FIFO levels */
-+ out_8(&priv->psc->rfcntl, 0x07);
-+ out_8(&priv->psc->tfcntl, 0x07);
-+ out_be16(&priv->psc->rfalarm, 0x80);
-+ out_be16(&priv->psc->tfalarm, 0x80);
-+
-+ /* Go */
-+ out_8(&priv->psc->command,MPC52xx_PSC_TX_ENABLE);
-+ out_8(&priv->psc->command,MPC52xx_PSC_RX_ENABLE);
-+
-+ return 0;
-+}
-+
-+static int
-+mpc52xx_ac97_hwshutdown(struct mpc52xx_ac97_priv *priv)
-+{
-+ /* No IRQ */
-+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
-+
-+ /* Disable TB & RX */
-+ out_8(&priv->psc->command,MPC52xx_PSC_RST_RX);
-+ out_8(&priv->psc->command,MPC52xx_PSC_RST_TX);
-+
-+ /* FIXME : Reset or put codec in low power ? */
-+
-+ return 0;
-+}
-+
-+
-+/* ======================================================================== */
-+/* OF Platform Driver */
-+/* ======================================================================== */
-+
-+static int __devinit
-+mpc52xx_ac97_probe(struct of_device *op, const struct of_device_id *match)
-+{
-+ struct device_node *dn = op->node;
-+ struct mpc52xx_ac97_priv *priv;
-+ struct snd_card *card;
-+ struct resource res;
-+ int rv;
-+
-+ dev_dbg(&op->dev, "probing MPC52xx PSC AC97 driver\n");
-+
-+ /* Get card structure */
-+ rv = -ENOMEM;
-+ card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-+ THIS_MODULE, sizeof(struct mpc52xx_ac97_priv));
-+ if (!card)
-+ goto err_early;
-+
-+ priv = card->private_data;
-+
-+ /* Init our private structure */
-+ priv->card = card;
-+ priv->dev = &op->dev;
-+
-+ /* Get resources (mem,irq,...) */
-+ rv = of_address_to_resource(dn, 0, &res);
-+ if (rv)
-+ goto err_early;
-+
-+ priv->mem_start = res.start;
-+ priv->mem_len = res.end - res.start + 1;
-+
-+ if (!request_mem_region(priv->mem_start, priv->mem_len, DRV_NAME)) {
-+ printk(KERN_ERR DRV_NAME ": request_mem_region failed\n");
-+ rv = -EBUSY;
-+ goto err_early;
-+ }
-+
-+ priv->psc = ioremap(priv->mem_start, priv->mem_len);
-+ if (!priv->psc) {
-+ printk(KERN_ERR DRV_NAME ": ioremap failed\n");
-+ rv = -ENOMEM;
-+ goto err_iomap;
-+ }
-+
-+ priv->irq = irq_of_parse_and_map(dn, 0);
-+ if (priv->irq == NO_IRQ) {
-+ printk(KERN_ERR DRV_NAME ": irq_of_parse_and_map failed\n");
-+ rv = -EBUSY;
-+ goto err_irqmap;
-+ }
-+
-+ /* Low level HW Init */
-+ mpc52xx_ac97_hwinit(priv);
-+
-+ /* Request IRQ now that we're 'stable' */
-+ rv = request_irq(priv->irq, mpc52xx_ac97_irq, 0, DRV_NAME, priv);
-+ if (rv < 0) {
-+ printk(KERN_ERR DRV_NAME ": request_irq failed\n");
-+ goto err_irqreq;
-+ }
-+
-+ /* Prepare sound stuff */
-+ rv = mpc52xx_ac97_setup_mixer(priv);
-+ if (rv)
-+ goto err_late;
-+
-+ rv = mpc52xx_ac97_setup_pcm(priv);
-+ if (rv)
-+ goto err_late;
-+
-+ /* Finally register the card */
-+ snprintf(card->shortname, sizeof(card->shortname), DRV_NAME);
-+ snprintf(card->longname, sizeof(card->longname),
-+ "Freescale MPC52xx PSC-AC97 (%s)", card->mixername);
-+
-+ rv = snd_card_register(card);
-+ if (rv) {
-+ printk(KERN_ERR DRV_NAME ": snd_card_register failed\n");
-+ goto err_late;
-+ }
-+
-+ dev_set_drvdata(&op->dev, priv);
-+
-+ return 0;
-+
-+err_late:
-+ free_irq(priv->irq, priv);
-+err_irqreq:
-+ mpc52xx_ac97_hwshutdown(priv);
-+ irq_dispose_mapping(priv->irq);
-+err_irqmap:
-+ iounmap(priv->psc);
-+err_iomap:
-+ release_mem_region(priv->mem_start, priv->mem_len);
-+err_early:
-+ if (card)
-+ snd_card_free(card);
-+ return rv;
-+}
-+
-+static int
-+mpc52xx_ac97_remove(struct of_device *op)
-+{
-+ struct mpc52xx_ac97_priv *priv;
-+
-+ dev_dbg(&op->dev, "removing MPC52xx PSC AC97 driver\n");
-+
-+ priv = dev_get_drvdata(&op->dev);
-+ if (priv) {
-+ /* Sound subsys shutdown */
-+ snd_card_free(priv->card);
-+
-+ /* Low level HW shutdown */
-+ mpc52xx_ac97_hwshutdown(priv);
-+
-+ /* Release resources */
-+ iounmap(priv->psc);
-+ free_irq(priv->irq, priv);
-+ irq_dispose_mapping(priv->irq);
-+ release_mem_region(priv->mem_start, priv->mem_len);
-+ }
-+
-+ dev_set_drvdata(&op->dev, NULL);
-+
-+ return 0;
-+}
-+
-+
-+static struct of_device_id mpc52xx_ac97_of_match[] = {
-+ {
-+/* .type = "ac97", FIXME Efika ... */
-+ .compatible = "mpc5200b-psc-ac97", /* B only for now */
-+ },
-+};
-+/* Prevent autoload during developpment phase ... */
-+/* MODULE_DEVICE_TABLE(of, mpc52xx_ac97_of_match); */
-+
-+
-+static struct of_platform_driver mpc52xx_ac97_of_driver = {
-+ .owner = THIS_MODULE,
-+ .name = DRV_NAME,
-+ .match_table = mpc52xx_ac97_of_match,
-+ .probe = mpc52xx_ac97_probe,
-+ .remove = mpc52xx_ac97_remove,
-+ .driver = {
-+ .name = DRV_NAME,
-+ },
-+};
-+
-+
-+/* ======================================================================== */
-+/* Module */
-+/* ======================================================================== */
-+
-+static int __init
-+mpc52xx_ac97_init(void)
-+{
-+ int rv;
-+
-+ /* Set port_config bits[25:26] to 01, keep the others as-is. This
-+ sets PSC2 to AC97 mode. */
-+ {
-+ void *mbar;
-+ u32 port_config;
-+ mbar = ioremap(0xf0000000, 0x100000);
-+ port_config = in_be32(mbar + 0xb00);
-+ printk(KERN_INFO "port_config was: %08x\n", port_config);
-+ port_config &= ~0x00000060;
-+ port_config |= 0x00000020;
-+ out_be32(mbar + 0xb00, port_config);
-+ printk(KERN_INFO "port_config now: %08x\n", port_config);
-+ iounmap(mbar);
-+ }
-+
-+ printk(KERN_INFO "Sound: MPC52xx PSC AC97 driver\n");
-+
-+ rv = of_register_platform_driver(&mpc52xx_ac97_of_driver);
-+ if (rv) {
-+ printk(KERN_ERR DRV_NAME ": "
-+ "of_register_platform_driver failed (%i)\n", rv);
-+ return rv;
-+ }
-+
-+ return 0;
-+}
-+
-+static void __exit
-+mpc52xx_ac97_exit(void)
-+{
-+ of_unregister_platform_driver(&mpc52xx_ac97_of_driver);
-+}
-+
-+module_init(mpc52xx_ac97_init);
-+module_exit(mpc52xx_ac97_exit);
-+
-+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
-+MODULE_DESCRIPTION(DRV_NAME ": Freescale MPC52xx PSC AC97 driver");
-+MODULE_LICENSE("GPL");
-+