]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.arch/ppc-efika-mpc52xx-ac97.patch
Imported linux-2.6.27.39 suse/xen patches.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / ppc-efika-mpc52xx-ac97.patch
CommitLineData
2cb7cef9
BS
1From: Juergen Beisert <jbe@pengutronix.de>
2Subject: RFC: MPC5200 PSC AC97 driver
3
4if someone is interested: Here the full patch to get sound support for
5MPC5200b and a current 2.6.25 kernel.
6
7Acked-by: Olaf Hering <olh@novell.com>
8
9---
10 arch/powerpc/include/asm/mpc52xx_psc.h | 4
11 arch/powerpc/kernel/prom_init.c | 3
12 sound/ppc/Kconfig | 15
13 sound/ppc/Makefile | 2
14 sound/ppc/mpc52xx_ac97.c | 807 +++++++++++++++++++++++++++++++++
15 5 files changed, 831 insertions(+)
16
17--- a/arch/powerpc/include/asm/mpc52xx_psc.h
18+++ b/arch/powerpc/include/asm/mpc52xx_psc.h
19@@ -28,6 +28,10 @@
20 #define MPC52xx_PSC_MAXNUM 6
21
22 /* Programmable Serial Controller (PSC) status register bits */
23+#define MPC52xx_PSC_SR_UNEX_RX 0x0001
24+#define MPC52xx_PSC_SR_DATA_VAL 0x0002
25+#define MPC52xx_PSC_SR_DATA_OVR 0x0004
26+#define MPC52xx_PSC_SR_CMDSEND 0x0008
27 #define MPC52xx_PSC_SR_CDE 0x0080
28 #define MPC52xx_PSC_SR_RXRDY 0x0100
29 #define MPC52xx_PSC_SR_RXFULL 0x0200
30--- a/arch/powerpc/kernel/prom_init.c
31+++ b/arch/powerpc/kernel/prom_init.c
32@@ -2189,6 +2189,7 @@ static void __init fixup_device_tree_efi
33
34 static void __init fixup_device_tree_efika(void)
35 {
36+ int sound_cell[1] = { 1 };
37 int sound_irq[3] = { 2, 2, 0 };
38 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
39 3,4,0, 3,5,0, 3,6,0, 3,7,0,
40@@ -2244,6 +2245,8 @@ static void __init fixup_device_tree_efi
41 prom_printf("Adding sound interrupts property\n");
42 prom_setprop(node, "/builtin/sound", "interrupts",
43 sound_irq, sizeof(sound_irq));
44+ prom_setprop(node, "/builtin/sound", "cell-index",
45+ sound_cell, sizeof(sound_cell));
46 }
47 }
48
49--- a/sound/ppc/Kconfig
50+++ b/sound/ppc/Kconfig
51@@ -48,4 +48,19 @@ config SND_PS3_DEFAULT_START_DELAY
52 depends on SND_PS3
53 default "2000"
54
55+
56+# ALSA ppc drivers
57+
58+menu "ALSA PPC devices"
59+ depends on SND!=n && PPC
60+
61+config SND_PPC_MPC52xx_AC97
62+ tristate "Freescale MPC52xx AC97 interface support"
63+ depends on SND && PPC_MPC52xx
64+ select SND_AC97_CODEC
65+ help
66+ Say Y or M if you want to support any AC97 codec attached to
67+ the Freescqle MPC52xx AC97 interface.
68+endmenu
69+
70 endif # SND_PPC
71--- a/sound/ppc/Makefile
72+++ b/sound/ppc/Makefile
73@@ -4,7 +4,9 @@
74 #
75
76 snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
77+snd-mpc52xx-ac97-objs := mpc52xx_ac97.o
78
79 # Toplevel Module Dependency
80 obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
81 obj-$(CONFIG_SND_PS3) += snd_ps3.o
82+obj-$(CONFIG_SND_PPC_MPC52xx_AC97) += snd-mpc52xx-ac97.o
83--- /dev/null
84+++ b/sound/ppc/mpc52xx_ac97.c
85@@ -0,0 +1,807 @@
86+/*
87+ * Driver for the PSC of the Freescale MPC52xx configured as AC97 interface
88+ *
89+ *
90+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
91+ *
92+ * This file is licensed under the terms of the GNU General Public License
93+ * version 2. This program is licensed "as is" without any warranty of any
94+ * kind, whether express or implied.
95+ */
96+#include <linux/kernel.h>
97+#include <linux/module.h>
98+#include <linux/interrupt.h>
99+#include <linux/spinlock.h>
100+
101+#include <sound/core.h>
102+#include <sound/initval.h>
103+#include <sound/pcm.h>
104+#include <sound/pcm_params.h>
105+#include <sound/ac97_codec.h>
106+
107+#include <asm/of_platform.h>
108+#include <linux/dma-mapping.h>
109+#include <asm/mpc52xx_psc.h>
110+
111+#include <sysdev/bestcomm/bestcomm.h>
112+#include <sysdev/bestcomm/gen_bd.h>
113+
114+
115+#define DRV_NAME "mpc52xx-psc-ac97"
116+
117+
118+/* ======================================================================== */
119+/* Structs / Defines */
120+/* ======================================================================== */
121+
122+/* Private structure */
123+struct mpc52xx_ac97_priv {
124+ struct device *dev;
125+ resource_size_t mem_start;
126+ resource_size_t mem_len;
127+ int irq;
128+ struct mpc52xx_psc __iomem *psc;
129+ struct mpc52xx_psc_fifo __iomem *fifo;
130+
131+ struct bcom_task *tsk_tx;
132+ spinlock_t dma_lock;
133+
134+ struct snd_card *card;
135+ struct snd_pcm *pcm;
136+ struct snd_ac97 *ac97;
137+
138+ struct snd_pcm_substream *substream_playback;
139+
140+ int period_byte_size;
141+ u32 period_start, period_end, period_next_p;
142+};
143+
144+/* Register bit definition (AC97 mode specific) */
145+#define PSC_AC97_SLOT_BIT(n) (1<<(12-n))
146+#define PSC_AC97_SLOTS_XMIT_SHIFT 16
147+#define PSC_AC97_SLOTS_RECV_SHIFT 0
148+
149+/* Bestcomm options */
150+#define AC97_TX_NUM_BD 32
151+#define AC97_RX_NUM_BD 32
152+
153+static int mpc52xx_ac97_tx_fill(struct mpc52xx_ac97_priv *priv)
154+{
155+ struct snd_pcm_runtime *rt;
156+
157+ u32 dma_data_ptr;
158+
159+ rt = priv->substream_playback->runtime;
160+
161+ dma_data_ptr = virt_to_phys(rt->dma_area);
162+
163+ priv->period_byte_size = frames_to_bytes(rt, rt->period_size);
164+ priv->period_start = dma_data_ptr;
165+ priv->period_end = dma_data_ptr + priv->period_byte_size * rt->periods;
166+ priv->period_next_p = dma_data_ptr;
167+
168+ spin_lock(&priv->dma_lock);
169+ while (!bcom_queue_full(priv->tsk_tx)) {
170+ struct bcom_gen_bd *bd;
171+
172+ /* Submit a new one */
173+ bd = (struct bcom_gen_bd *) bcom_prepare_next_buffer(priv->tsk_tx);
174+ bd->status = priv->period_byte_size;
175+ bd->buf_pa = priv->period_next_p;
176+ bcom_submit_next_buffer(priv->tsk_tx, NULL);
177+
178+ /* Next pointer */
179+ priv->period_next_p += priv->period_byte_size;
180+ if (priv->period_next_p >= priv->period_end)
181+ priv->period_next_p = priv->period_start;
182+ }
183+ spin_unlock(&priv->dma_lock);
184+
185+ return 0;
186+}
187+
188+
189+/* ======================================================================== */
190+/* ISR routine */
191+/* ======================================================================== */
192+
193+static irqreturn_t mpc52xx_ac97_tx_irq(int irq, void *dev_id)
194+{
195+ struct mpc52xx_ac97_priv *priv = dev_id;
196+ struct snd_pcm_runtime *rt;
197+ struct bcom_gen_bd *bd;
198+
199+ rt = priv->substream_playback->runtime;
200+
201+ if (!bcom_buffer_done(priv->tsk_tx)) {
202+ dev_dbg(priv->dev, "tx mismatch? Check correct output PSC\n");
203+ bcom_disable(priv->tsk_tx);
204+ }
205+
206+ spin_lock(&priv->dma_lock);
207+ while (bcom_buffer_done(priv->tsk_tx)) {
208+ /* Get the buffer back */
209+ bcom_retrieve_buffer(priv->tsk_tx, NULL, NULL);
210+
211+ /* Submit a new one */
212+ bd = (struct bcom_gen_bd *) bcom_prepare_next_buffer(priv->tsk_tx);
213+ bd->status = priv->period_byte_size;
214+ bd->buf_pa = priv->period_next_p;
215+ bcom_submit_next_buffer(priv->tsk_tx, NULL);
216+ bcom_enable(priv->tsk_tx);
217+
218+ /* Next pointer */
219+ priv->period_next_p += priv->period_byte_size;
220+ if (priv->period_next_p >= priv->period_end)
221+ priv->period_next_p = priv->period_start;
222+ }
223+ spin_unlock(&priv->dma_lock);
224+
225+ snd_pcm_period_elapsed(priv->substream_playback);
226+
227+ return IRQ_HANDLED;
228+}
229+
230+
231+static irqreturn_t mpc52xx_ac97_irq(int irq, void *dev_id)
232+{
233+ struct mpc52xx_ac97_priv *priv = dev_id;
234+
235+ static int icnt = 0;
236+
237+#if 1
238+ /* Anti Crash during dev ;) */
239+ if ((icnt++) > 5000)
240+ out_be16(&priv->psc->mpc52xx_psc_imr, 0);
241+#endif
242+
243+ /* Print statuts */
244+ dev_dbg(priv->dev, "isr: %04x", in_be16(&priv->psc->mpc52xx_psc_imr));
245+ out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
246+
247+ return IRQ_HANDLED;
248+}
249+
250+/* ======================================================================== */
251+/* PCM interface */
252+/* ======================================================================== */
253+
254+/* HW desc */
255+
256+static struct snd_pcm_hardware mpc52xx_ac97_hw = {
257+ .info = SNDRV_PCM_INFO_INTERLEAVED |
258+ SNDRV_PCM_INFO_MMAP |
259+ SNDRV_PCM_INFO_MMAP_VALID,
260+ .formats = SNDRV_PCM_FMTBIT_S32_BE,
261+ .rates = SNDRV_PCM_RATE_8000_48000,
262+ .rate_min = 8000,
263+ .rate_max = 48000,
264+ .channels_min = 1,
265+ .channels_max = 2, /* Support for more ? */
266+ .buffer_bytes_max = 1024*1024,
267+ .period_bytes_min = 512,
268+ .period_bytes_max = 16*1024,
269+ .periods_min = 8,
270+ .periods_max = 1024,
271+ .fifo_size = 512,
272+};
273+
274+
275+/* Playback */
276+
277+static int mpc52xx_ac97_playback_open(struct snd_pcm_substream *substream)
278+{
279+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
280+
281+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_open(%p)\n", substream);
282+
283+ substream->runtime->hw = mpc52xx_ac97_hw;
284+
285+ priv->substream_playback = substream;
286+
287+ return 0; /* FIXME */
288+}
289+
290+static int mpc52xx_ac97_playback_close(struct snd_pcm_substream *substream)
291+{
292+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
293+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_close(%p)\n", substream);
294+ priv->substream_playback = NULL;
295+ return 0; /* FIXME */
296+}
297+
298+static int mpc52xx_ac97_playback_prepare(struct snd_pcm_substream *substream)
299+{
300+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
301+
302+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_prepare(%p)\n", substream);
303+
304+ /* FIXME, need a spinlock to protect access */
305+ if (substream->runtime->channels == 1)
306+ out_be32(&priv->psc->ac97_slots, 0x01000000);
307+ else
308+ out_be32(&priv->psc->ac97_slots, 0x03000000);
309+
310+ snd_ac97_set_rate(priv->ac97, AC97_PCM_FRONT_DAC_RATE,
311+ substream->runtime->rate);
312+
313+ return 0; /* FIXME */
314+}
315+
316+
317+/* Capture */
318+
319+static int mpc52xx_ac97_capture_open(struct snd_pcm_substream *substream)
320+{
321+/* struct mpc52xx_ac97_priv *priv = substream->pcm->private_data; */
322+ return 0; /* FIXME */
323+}
324+
325+static int mpc52xx_ac97_capture_close(struct snd_pcm_substream *substream)
326+{
327+/* struct mpc52xx_ac97_priv *priv = substream->pcm->private_data; */
328+ return 0; /* FIXME */
329+}
330+
331+static int
332+mpc52xx_ac97_capture_prepare(struct snd_pcm_substream *substream)
333+{
334+/* struct mpc52xx_ac97_priv *priv = substream->pcm->private_data; */
335+ return 0; /* FIXME */
336+}
337+
338+
339+/* Common */
340+
341+static int mpc52xx_ac97_hw_params(struct snd_pcm_substream *substream,
342+ struct snd_pcm_hw_params *params)
343+{
344+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
345+ int rv;
346+
347+ dev_dbg(priv->dev, "mpc52xx_ac97_hw_params(%p)\n", substream);
348+
349+ rv = snd_pcm_lib_malloc_pages(substream,
350+ params_buffer_bytes(params));
351+ if (rv < 0) {
352+ printk(KERN_ERR "hw params failes\n"); /* FIXME */
353+ return rv;
354+ }
355+
356+ dev_dbg(priv->dev, "%d %d %d\n", params_buffer_bytes(params),
357+ params_period_bytes(params), params_periods(params));
358+
359+ return 0;
360+}
361+
362+static int mpc52xx_ac97_hw_free(struct snd_pcm_substream *substream)
363+{
364+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
365+
366+ dev_dbg(priv->dev, "mpc52xx_ac97_hw_free(%p)\n", substream);
367+
368+ return snd_pcm_lib_free_pages(substream);
369+}
370+
371+static int mpc52xx_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
372+{
373+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
374+ int rv = 0;
375+
376+ dev_dbg(priv->dev, "mpc52xx_ac97_trigger(%p,%d)\n", substream, cmd);
377+
378+ switch (cmd) {
379+ case SNDRV_PCM_TRIGGER_START:
380+ /* Enable TX taks */
381+ bcom_gen_bd_tx_reset(priv->tsk_tx);
382+ mpc52xx_ac97_tx_fill(priv);
383+ bcom_enable(priv->tsk_tx);
384+/*
385+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0800); // 0x0100
386+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0100); // 0x0100
387+*/
388+ /* FIXME: Shouldn't we check for overrun too ? */
389+ /* also, shouldn't we just activate TX here ? */
390+
391+ break;
392+
393+ case SNDRV_PCM_TRIGGER_STOP:
394+ /* Disable TX task */
395+ bcom_disable(priv->tsk_tx);
396+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000); // 0x0100
397+
398+ break;
399+
400+ default:
401+ rv = -EINVAL;
402+ }
403+
404+ /* FIXME */
405+ return rv;
406+}
407+
408+static snd_pcm_uframes_t mpc52xx_ac97_pointer(struct snd_pcm_substream *substream)
409+{
410+ struct snd_pcm_runtime *runtime = substream->runtime;
411+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
412+ u32 count;
413+
414+ count = priv->tsk_tx->bd[priv->tsk_tx->outdex].data[0] - priv->period_start;
415+
416+ return bytes_to_frames(runtime, count);
417+}
418+
419+
420+/* Ops */
421+
422+static struct snd_pcm_ops mpc52xx_ac97_playback_ops = {
423+ .open = mpc52xx_ac97_playback_open,
424+ .close = mpc52xx_ac97_playback_close,
425+ .ioctl = snd_pcm_lib_ioctl,
426+ .hw_params = mpc52xx_ac97_hw_params,
427+ .hw_free = mpc52xx_ac97_hw_free,
428+ .prepare = mpc52xx_ac97_playback_prepare,
429+ .trigger = mpc52xx_ac97_trigger,
430+ .pointer = mpc52xx_ac97_pointer,
431+};
432+
433+static struct snd_pcm_ops mpc52xx_ac97_capture_ops = {
434+ .open = mpc52xx_ac97_capture_open,
435+ .close = mpc52xx_ac97_capture_close,
436+ .ioctl = snd_pcm_lib_ioctl,
437+ .hw_params = mpc52xx_ac97_hw_params,
438+ .hw_free = mpc52xx_ac97_hw_free,
439+ .prepare = mpc52xx_ac97_capture_prepare,
440+ .trigger = mpc52xx_ac97_trigger,
441+ .pointer = mpc52xx_ac97_pointer,
442+};
443+
444+
445+/* ======================================================================== */
446+/* AC97 Bus interface */
447+/* ======================================================================== */
448+
449+static unsigned short mpc52xx_ac97_bus_read(struct snd_ac97 *ac97,
450+ unsigned short reg)
451+{
452+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
453+ int timeout;
454+ unsigned int val;
455+
456+ /* Wait for it to be ready */
457+ timeout = 1000;
458+ while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
459+ MPC52xx_PSC_SR_CMDSEND) )
460+ udelay(10);
461+
462+ if (!timeout) {
463+ printk(KERN_ERR DRV_NAME ": timeout on ac97 bus (rdy)\n");
464+ return 0xffff;
465+ }
466+
467+ /* Do the read */
468+ out_be32(&priv->psc->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
469+
470+ /* Wait for the answer */
471+ timeout = 1000;
472+ while ((--timeout) && !(in_be16(&priv->psc->mpc52xx_psc_status) &
473+ MPC52xx_PSC_SR_DATA_VAL) )
474+ udelay(10);
475+
476+ if (!timeout) {
477+ printk(KERN_ERR DRV_NAME ": timeout on ac97 read (val)\n");
478+ return 0xffff;
479+ }
480+
481+ /* Get the data */
482+ val = in_be32(&priv->psc->ac97_data);
483+ if ( ((val>>24) & 0x7f) != reg ) {
484+ printk(KERN_ERR DRV_NAME ": reg echo error on ac97 read\n");
485+ return 0xffff;
486+ }
487+ val = (val >> 8) & 0xffff;
488+
489+ return (unsigned short) val;
490+}
491+
492+static void mpc52xx_ac97_bus_write(struct snd_ac97 *ac97,
493+ unsigned short reg, unsigned short val)
494+{
495+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
496+ int timeout;
497+
498+ /* Wait for it to be ready */
499+ timeout = 1000;
500+ while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
501+ MPC52xx_PSC_SR_CMDSEND) )
502+ udelay(10);
503+
504+ if (!timeout) {
505+ printk(KERN_ERR DRV_NAME ": timeout on ac97 write\n");
506+ return;
507+ }
508+
509+ /* Write data */
510+ out_be32(&priv->psc->ac97_cmd, ((reg & 0x7f) << 24) | (val << 8));
511+}
512+
513+static void mpc52xx_ac97_bus_reset(struct snd_ac97 *ac97)
514+{
515+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
516+
517+ dev_dbg(priv->dev, "ac97 codec reset\n");
518+
519+ /* Do a cold reset */
520+ /*
521+ * Note: This could interfere with some external AC97 mixers, as it
522+ * could switch them into test mode, when SYNC or SDATA_OUT are not
523+ * low while RES is low!
524+ */
525+ out_8(&priv->psc->op1, 0x02);
526+ udelay(10);
527+ out_8(&priv->psc->op0, 0x02);
528+ udelay(50);
529+
530+ /* PSC recover from cold reset (cfr user manual, not sure if useful) */
531+ out_be32(&priv->psc->sicr, in_be32(&priv->psc->sicr));
532+}
533+
534+
535+static struct snd_ac97_bus_ops mpc52xx_ac97_bus_ops = {
536+ .read = mpc52xx_ac97_bus_read,
537+ .write = mpc52xx_ac97_bus_write,
538+ .reset = mpc52xx_ac97_bus_reset,
539+};
540+
541+
542+/* ======================================================================== */
543+/* Sound driver setup */
544+/* ======================================================================== */
545+
546+static int mpc52xx_ac97_setup_pcm(struct mpc52xx_ac97_priv *priv)
547+{
548+ int rv;
549+
550+ rv = snd_pcm_new(priv->card, DRV_NAME "-pcm", 0, 1, 1, &priv->pcm);
551+ if (rv) {
552+ dev_dbg(priv->dev, "%s: snd_pcm_new failed\n", DRV_NAME);
553+ return rv;
554+ }
555+
556+ rv = snd_pcm_lib_preallocate_pages_for_all(priv->pcm,
557+ SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL),
558+ 128*1024, 128*1024);
559+ if (rv) {
560+ dev_dbg(priv->dev,
561+ "%s: snd_pcm_lib_preallocate_pages_for_all failed\n",
562+ DRV_NAME);
563+ return rv;
564+ }
565+
566+ snd_pcm_set_ops(priv->pcm, SNDRV_PCM_STREAM_PLAYBACK,
567+ &mpc52xx_ac97_playback_ops);
568+ snd_pcm_set_ops(priv->pcm, SNDRV_PCM_STREAM_CAPTURE,
569+ &mpc52xx_ac97_capture_ops);
570+
571+ priv->pcm->private_data = priv;
572+ priv->pcm->info_flags = 0;
573+
574+ strcpy(priv->pcm->name, "Freescale MPC52xx PSC-AC97 PCM");
575+
576+ return 0;
577+}
578+
579+static int mpc52xx_ac97_setup_mixer(struct mpc52xx_ac97_priv *priv)
580+{
581+ struct snd_ac97_bus *ac97_bus;
582+ struct snd_ac97_template ac97_template;
583+ int rv;
584+
585+ rv = snd_ac97_bus(priv->card, 0, &mpc52xx_ac97_bus_ops, NULL, &ac97_bus);
586+ if (rv) {
587+ printk(KERN_ERR DRV_NAME ": snd_ac97_bus failed\n");
588+ return rv;
589+ }
590+
591+ memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
592+ ac97_template.private_data = priv;
593+
594+ rv = snd_ac97_mixer(ac97_bus, &ac97_template, &priv->ac97);
595+ if (rv) {
596+ printk(KERN_ERR DRV_NAME ": snd_ac97_mixer failed\n");
597+ return rv;
598+ }
599+
600+ return 0;
601+}
602+
603+static int mpc52xx_ac97_hwinit(struct mpc52xx_ac97_priv *priv)
604+{
605+ /* Reset everything first by safety */
606+ out_8(&priv->psc->command,MPC52xx_PSC_RST_RX);
607+ out_8(&priv->psc->command,MPC52xx_PSC_RST_TX);
608+ out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
609+
610+ /* Do a cold reset of codec */
611+ /*
612+ * Note: This could interfere with some external AC97 mixers, as it
613+ * could switch them into test mode, when SYNC or SDATA_OUT are not
614+ * low while RES is low!
615+ */
616+ out_8(&priv->psc->op1, 0x02);
617+ udelay(10);
618+ out_8(&priv->psc->op0, 0x02);
619+ udelay(50);
620+
621+ /* Configure AC97 enhanced mode */
622+ out_be32(&priv->psc->sicr, 0x03010000);
623+
624+ /* No slots active */
625+ out_be32(&priv->psc->ac97_slots, 0x00000000);
626+
627+ /* No IRQ */
628+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
629+
630+ /* FIFO levels */
631+ out_8(&priv->fifo->rfcntl, 0x07);
632+ out_8(&priv->fifo->tfcntl, 0x07);
633+ out_be16(&priv->fifo->rfalarm, 0x80);
634+ out_be16(&priv->fifo->tfalarm, 0x80);
635+
636+ /* Go */
637+ out_8(&priv->psc->command,MPC52xx_PSC_TX_ENABLE);
638+ out_8(&priv->psc->command,MPC52xx_PSC_RX_ENABLE);
639+
640+ return 0;
641+}
642+
643+static int mpc52xx_ac97_hwshutdown(struct mpc52xx_ac97_priv *priv)
644+{
645+ /* No IRQ */
646+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
647+
648+ /* Disable TB & RX */
649+ out_8(&priv->psc->command,MPC52xx_PSC_RST_RX);
650+ out_8(&priv->psc->command,MPC52xx_PSC_RST_TX);
651+
652+ /* FIXME : Reset or put codec in low power ? */
653+
654+ return 0;
655+}
656+
657+/* ======================================================================== */
658+/* OF Platform Driver */
659+/* ======================================================================== */
660+
661+static int __devinit
662+mpc52xx_ac97_probe(struct of_device *op, const struct of_device_id *match)
663+{
664+ struct device_node *dn = op->node;
665+ struct mpc52xx_ac97_priv *priv;
666+ struct snd_card *card;
667+ struct resource res;
668+ int tx_initiator;
669+ int rv;
670+ const unsigned int *devno;
671+
672+ dev_dbg(&op->dev, "probing MPC52xx PSC AC97 driver\n");
673+
674+ /* Get card structure */
675+ rv = -ENOMEM;
676+ card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
677+ THIS_MODULE, sizeof(struct mpc52xx_ac97_priv));
678+ if (!card)
679+ goto err_early;
680+
681+ priv = card->private_data;
682+
683+ /* Init our private structure */
684+ priv->card = card;
685+ priv->dev = &op->dev;
686+
687+ /* Get resources (mem,irq,...) */
688+ rv = of_address_to_resource(dn, 0, &res);
689+ if (rv)
690+ goto err_early;
691+
692+ priv->mem_start = res.start;
693+ priv->mem_len = res.end - res.start + 1;
694+
695+ if (!request_mem_region(priv->mem_start, priv->mem_len, DRV_NAME)) {
696+ dev_err(&op->dev, "%s: request_mem_region failed\n", DRV_NAME);
697+ rv = -EBUSY;
698+ goto err_early;
699+ }
700+
701+ priv->psc = ioremap(priv->mem_start, priv->mem_len);
702+ if (!priv->psc) {
703+ dev_err(&op->dev, "%s: ioremap failed\n", DRV_NAME);
704+ rv = -ENOMEM;
705+ goto err_iomap;
706+ }
707+ /* the fifo starts right after psc ends */
708+ priv->fifo = (struct mpc52xx_psc_fifo*)&priv->psc[1]; /* FIXME */
709+
710+ priv->irq = irq_of_parse_and_map(dn, 0);
711+ if (priv->irq == NO_IRQ) {
712+ dev_err(&op->dev, "%s: irq_of_parse_and_map failed\n",
713+ DRV_NAME);
714+ rv = -EBUSY;
715+ goto err_irqmap;
716+ }
717+
718+ /* Setup Bestcomm tasks */
719+ spin_lock_init(&priv->dma_lock);
720+
721+ /*
722+ * PSC1 or PSC2 can be configured for AC97 usage. Select the right
723+ * channel, to let the BCOMM unit does its job correctly.
724+ */
725+ devno = of_get_property(dn, "cell-index", NULL);
726+ switch (*devno) {
727+ case 0: /* PSC1 */
728+ tx_initiator = 14;
729+ break;
730+ case 1: /* PSC2 */
731+ tx_initiator = 12;
732+ break;
733+ default:
734+ dev_dbg(priv->dev, "Unknown PSC unit for AC97 usage!\n");
735+ rv = -ENODEV;
736+ goto err_irq;
737+ }
738+
739+ priv->tsk_tx = bcom_gen_bd_tx_init(AC97_TX_NUM_BD,
740+ priv->mem_start + sizeof(struct mpc52xx_psc) +
741+ offsetof(struct mpc52xx_psc_fifo, tfdata),
742+ tx_initiator,
743+ 2); /* ipr : FIXME */
744+ if (!priv->tsk_tx) {
745+ dev_err(&op->dev, "%s: bcom_gen_bd_tx_init failed\n",
746+ DRV_NAME);
747+ rv = -ENOMEM;
748+ goto err_bcomm;
749+ }
750+
751+ /* Low level HW Init */
752+ mpc52xx_ac97_hwinit(priv);
753+
754+ /* Request IRQ now that we're 'stable' */
755+ rv = request_irq(priv->irq, mpc52xx_ac97_irq, 0, DRV_NAME, priv);
756+ if (rv < 0) {
757+ dev_err(&op->dev, "%s: request_irq failed\n", DRV_NAME);
758+ goto err_irqreq;
759+ }
760+
761+ rv = request_irq(bcom_get_task_irq(priv->tsk_tx),
762+ mpc52xx_ac97_tx_irq, 0, DRV_NAME "_tx", priv);
763+ if (rv < 0) {
764+ dev_err(&op->dev, "%s: request_irq failed\n", DRV_NAME);
765+ goto err_txirqreq;
766+ }
767+
768+ /* Prepare sound stuff */
769+ rv = mpc52xx_ac97_setup_mixer(priv);
770+ if (rv)
771+ goto err_late;
772+
773+ rv = mpc52xx_ac97_setup_pcm(priv);
774+ if (rv)
775+ goto err_late;
776+
777+ /* Finally register the card */
778+ snprintf(card->shortname, sizeof(card->shortname), DRV_NAME);
779+ snprintf(card->longname, sizeof(card->longname),
780+ "Freescale MPC52xx PSC-AC97 (%s)", card->mixername);
781+
782+ rv = snd_card_register(card);
783+ if (rv) {
784+ dev_err(&op->dev, "%s: snd_card_register failed\n", DRV_NAME);
785+ goto err_late;
786+ }
787+
788+ dev_set_drvdata(&op->dev, priv);
789+
790+ return 0;
791+
792+err_late:
793+ free_irq(bcom_get_task_irq(priv->tsk_tx), priv);
794+err_txirqreq:
795+ free_irq(priv->irq, priv);
796+err_irqreq:
797+ bcom_gen_bd_tx_release(priv->tsk_tx);
798+err_bcomm:
799+ mpc52xx_ac97_hwshutdown(priv);
800+err_irq:
801+ irq_dispose_mapping(priv->irq);
802+err_irqmap:
803+ iounmap(priv->psc);
804+err_iomap:
805+ release_mem_region(priv->mem_start, priv->mem_len);
806+err_early:
807+ if (card)
808+ snd_card_free(card);
809+ return rv;
810+}
811+
812+static int mpc52xx_ac97_remove(struct of_device *op)
813+{
814+ struct mpc52xx_ac97_priv *priv;
815+
816+ dev_dbg(&op->dev, "removing MPC52xx PSC AC97 driver\n");
817+
818+ priv = dev_get_drvdata(&op->dev);
819+ if (priv) {
820+ /* Sound subsys shutdown */
821+ snd_card_free(priv->card);
822+
823+ /* Low level HW shutdown */
824+ mpc52xx_ac97_hwshutdown(priv);
825+
826+ /* Release bestcomm tasks */
827+ free_irq(bcom_get_task_irq(priv->tsk_tx), priv);
828+ bcom_gen_bd_tx_release(priv->tsk_tx);
829+
830+ /* Release resources */
831+ iounmap(priv->psc);
832+ free_irq(priv->irq, priv);
833+ irq_dispose_mapping(priv->irq);
834+ release_mem_region(priv->mem_start, priv->mem_len);
835+ }
836+
837+ dev_set_drvdata(&op->dev, NULL);
838+
839+ return 0;
840+}
841+
842+
843+static struct of_device_id mpc52xx_ac97_of_match[] = {
844+ {
845+ .type = "sound",
846+ .compatible = "mpc5200b-psc-ac97", /* B only for now */
847+ }, { }
848+};
849+MODULE_DEVICE_TABLE(of, mpc52xx_ac97_of_match);
850+static struct of_platform_driver mpc52xx_ac97_of_driver = {
851+ .owner = THIS_MODULE,
852+ .name = DRV_NAME,
853+ .match_table = mpc52xx_ac97_of_match,
854+ .probe = mpc52xx_ac97_probe,
855+ .remove = mpc52xx_ac97_remove,
856+ .driver = {
857+ .name = DRV_NAME,
858+ },
859+};
860+
861+/* ======================================================================== */
862+/* Module */
863+/* ======================================================================== */
864+
865+static int __init mpc52xx_ac97_init(void)
866+{
867+ int rv;
868+
869+ printk(KERN_INFO "Sound: MPC52xx PSC AC97 driver\n");
870+
871+ rv = of_register_platform_driver(&mpc52xx_ac97_of_driver);
872+ if (rv) {
873+ printk(KERN_ERR DRV_NAME ": "
874+ "of_register_platform_driver failed (%i)\n", rv);
875+ return rv;
876+ }
877+
878+ return 0;
879+}
880+
881+static void __exit mpc52xx_ac97_exit(void)
882+{
883+ of_unregister_platform_driver(&mpc52xx_ac97_of_driver);
884+}
885+
886+module_init(mpc52xx_ac97_init);
887+module_exit(mpc52xx_ac97_exit);
888+
889+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
890+MODULE_DESCRIPTION(DRV_NAME ": Freescale MPC52xx PSC AC97 driver");
891+MODULE_LICENSE("GPL");
892+