aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 11:32:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-25 11:32:05 -0400
commit33081adf8b89d5a716d7e1c60171768d39795b39 (patch)
tree275de58bbbb5f7ddffcdc087844cfc7fbe4315be /sound/soc/fsl
parentc55960499f810357a29659b32d6ea594abee9237 (diff)
parent506ecbca71d07fa327dd986be1682e90885678ee (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (365 commits) ALSA: hda - Disable sticky PCM stream assignment for AD codecs ALSA: usb - Creative USB X-Fi volume knob support ALSA: ca0106: Use card specific dac id for mute controls. ALSA: ca0106: Allow different sound cards to use different SPI channel mappings. ALSA: ca0106: Create a nice spot for mapping channels to dacs. ALSA: ca0106: Move enabling of front dac out of hardcoded setup sequence. ALSA: ca0106: Pull out dac powering routine into separate function. ALSA: ca0106 - add Sound Blaster 5.1vx info. ASoC: tlv320dac33: Use usleep_range for delays ALSA: usb-audio: add Novation Launchpad support ALSA: hda - Add workarounds for CT-IBG controllers ALSA: hda - Fix wrong TLV mute bit for STAC/IDT codecs ASoC: tpa6130a2: Error handling for broken chip ASoC: max98088: Staticise m98088_eq_band ASoC: soc-core: Fix codec->name memory leak ALSA: hda - Apply ideapad quirk to Acer laptops with Cxt5066 ALSA: hda - Add some workarounds for Creative IBG ALSA: hda - Fix wrong SPDIF NID assignment for CA0110 ALSA: hda - Fix codec rename rules for ALC662-compatible codecs ALSA: hda - Add alc_init_jacks() call to other codecs ...
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/Kconfig27
-rw-r--r--sound/soc/fsl/Makefile11
-rw-r--r--sound/soc/fsl/efika-audio-fabric.c20
-rw-r--r--sound/soc/fsl/fsl_dma.c458
-rw-r--r--sound/soc/fsl/fsl_dma.h20
-rw-r--r--sound/soc/fsl/fsl_ssi.c298
-rw-r--r--sound/soc/fsl/fsl_ssi.h26
-rw-r--r--sound/soc/fsl/mpc5200_dma.c66
-rw-r--r--sound/soc/fsl/mpc5200_dma.h5
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c34
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.h2
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c19
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c660
-rw-r--r--sound/soc/fsl/p1022_ds.c591
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c21
-rw-r--r--sound/soc/fsl/soc-of-simple.c172
16 files changed, 1486 insertions, 944 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 8cb65ccad35f..d754d34d68a6 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,27 +1,36 @@
1config SND_SOC_OF_SIMPLE
2 tristate
3
4config SND_MPC52xx_DMA 1config SND_MPC52xx_DMA
5 tristate 2 tristate
6 3
7# ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers 4# ASoC platform support for the Freescale PowerPC SOCs that have an SSI and
8# for the SSI and the Elo DMA controller. You will still need to select 5# an Elo DMA controller, such as the MPC8610 and P1022. You will still need to
9# a platform driver and a codec driver. 6# select a platform driver and a codec driver.
10config SND_SOC_MPC8610 7config SND_SOC_POWERPC_SSI
11 tristate 8 tristate
12 depends on MPC8610 9 depends on FSL_SOC
13 10
14config SND_SOC_MPC8610_HPCD 11config SND_SOC_MPC8610_HPCD
15 tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" 12 tristate "ALSA SoC support for the Freescale MPC8610 HPCD board"
16 # I2C is necessary for the CS4270 driver 13 # I2C is necessary for the CS4270 driver
17 depends on MPC8610_HPCD && I2C 14 depends on MPC8610_HPCD && I2C
18 select SND_SOC_MPC8610 15 select SND_SOC_POWERPC_SSI
19 select SND_SOC_CS4270 16 select SND_SOC_CS4270
20 select SND_SOC_CS4270_VD33_ERRATA 17 select SND_SOC_CS4270_VD33_ERRATA
21 default y if MPC8610_HPCD 18 default y if MPC8610_HPCD
22 help 19 help
23 Say Y if you want to enable audio on the Freescale MPC8610 HPCD. 20 Say Y if you want to enable audio on the Freescale MPC8610 HPCD.
24 21
22config SND_SOC_P1022_DS
23 tristate "ALSA SoC support for the Freescale P1022 DS board"
24 # I2C is necessary for the WM8776 driver
25 depends on P1022_DS && I2C
26 select SND_SOC_POWERPC_SSI
27 select SND_SOC_WM8776
28 default y if P1022_DS
29 help
30 Say Y if you want to enable audio on the Freescale P1022 DS board.
31 This will also include the Wolfson Microelectronics WM8776 codec
32 driver.
33
25config SND_SOC_MPC5200_I2S 34config SND_SOC_MPC5200_I2S
26 tristate "Freescale MPC5200 PSC in I2S mode driver" 35 tristate "Freescale MPC5200 PSC in I2S mode driver"
27 depends on PPC_MPC52xx && PPC_BESTCOMM 36 depends on PPC_MPC52xx && PPC_BESTCOMM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index a83a73967ec6..b4a38c0ac58c 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -1,14 +1,15 @@
1# Simple machine driver that extracts configuration from the OF device tree
2obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o
3
4# MPC8610 HPCD Machine Support 1# MPC8610 HPCD Machine Support
5snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o 2snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o
6obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o 3obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
7 4
8# MPC8610 Platform Support 5# P1022 DS Machine Support
6snd-soc-p1022-ds-objs := p1022_ds.o
7obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
8
9# Freescale PowerPC SSI/DMA Platform Support
9snd-soc-fsl-ssi-objs := fsl_ssi.o 10snd-soc-fsl-ssi-objs := fsl_ssi.o
10snd-soc-fsl-dma-objs := fsl_dma.o 11snd-soc-fsl-dma-objs := fsl_dma.o
11obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o 12obj-$(CONFIG_SND_SOC_POWERPC_SSI) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o
12 13
13# MPC5200 Platform Support 14# MPC5200 Platform Support
14obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o 15obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c
index 1a5b8e0d6a34..53251e6b5bd5 100644
--- a/sound/soc/fsl/efika-audio-fabric.c
+++ b/sound/soc/fsl/efika-audio-fabric.c
@@ -24,7 +24,6 @@
24#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
25#include <sound/initval.h> 25#include <sound/initval.h>
26#include <sound/soc.h> 26#include <sound/soc.h>
27#include <sound/soc-of-simple.h>
28 27
29#include "mpc5200_dma.h" 28#include "mpc5200_dma.h"
30#include "mpc5200_psc_ac97.h" 29#include "mpc5200_psc_ac97.h"
@@ -32,21 +31,24 @@
32 31
33#define DRV_NAME "efika-audio-fabric" 32#define DRV_NAME "efika-audio-fabric"
34 33
35static struct snd_soc_device device;
36static struct snd_soc_card card; 34static struct snd_soc_card card;
37 35
38static struct snd_soc_dai_link efika_fabric_dai[] = { 36static struct snd_soc_dai_link efika_fabric_dai[] = {
39{ 37{
40 .name = "AC97", 38 .name = "AC97",
41 .stream_name = "AC97 Analog", 39 .stream_name = "AC97 Analog",
42 .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_ANALOG], 40 .codec_dai_name = "stac9766-hifi-analog",
43 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], 41 .cpu_dai_name = "mpc5200-psc-ac97.0",
42 .platform_name = "mpc5200-pcm-audio",
43 .codec_name = "stac9766-codec",
44}, 44},
45{ 45{
46 .name = "AC97", 46 .name = "AC97",
47 .stream_name = "AC97 IEC958", 47 .stream_name = "AC97 IEC958",
48 .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_DIGITAL], 48 .codec_dai_name = "stac9766-hifi-IEC958",
49 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], 49 .cpu_dai_name = "mpc5200-psc-ac97.1",
50 .platform_name = "mpc5200-pcm-audio",
51 .codec_name = "stac9766-codec",
50}, 52},
51}; 53};
52 54
@@ -58,13 +60,10 @@ static __init int efika_fabric_init(void)
58 if (!of_machine_is_compatible("bplan,efika")) 60 if (!of_machine_is_compatible("bplan,efika"))
59 return -ENODEV; 61 return -ENODEV;
60 62
61 card.platform = &mpc5200_audio_dma_platform;
62 card.name = "Efika"; 63 card.name = "Efika";
63 card.dai_link = efika_fabric_dai; 64 card.dai_link = efika_fabric_dai;
64 card.num_links = ARRAY_SIZE(efika_fabric_dai); 65 card.num_links = ARRAY_SIZE(efika_fabric_dai);
65 66
66 device.card = &card;
67 device.codec_dev = &soc_codec_dev_stac9766;
68 67
69 pdev = platform_device_alloc("soc-audio", 1); 68 pdev = platform_device_alloc("soc-audio", 1);
70 if (!pdev) { 69 if (!pdev) {
@@ -72,8 +71,7 @@ static __init int efika_fabric_init(void)
72 return -ENODEV; 71 return -ENODEV;
73 } 72 }
74 73
75 platform_set_drvdata(pdev, &device); 74 platform_set_drvdata(pdev, &card);
76 device.dev = &pdev->dev;
77 75
78 rc = platform_device_add(pdev); 76 rc = platform_device_add(pdev);
79 if (rc) { 77 if (rc) {
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 410c7496a18d..4cf98c03af22 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -3,10 +3,11 @@
3 * 3 *
4 * Author: Timur Tabi <timur@freescale.com> 4 * Author: Timur Tabi <timur@freescale.com>
5 * 5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed 6 * Copyright 2007-2010 Freescale Semiconductor, Inc.
7 * under the terms of the GNU General Public License version 2. This 7 *
8 * program is licensed "as is" without any warranty of any kind, whether 8 * This file is licensed under the terms of the GNU General Public License
9 * express or implied. 9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
10 * 11 *
11 * This driver implements ASoC support for the Elo DMA controller, which is 12 * This driver implements ASoC support for the Elo DMA controller, which is
12 * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms, 13 * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms,
@@ -20,6 +21,9 @@
20#include <linux/interrupt.h> 21#include <linux/interrupt.h>
21#include <linux/delay.h> 22#include <linux/delay.h>
22#include <linux/gfp.h> 23#include <linux/gfp.h>
24#include <linux/of_platform.h>
25#include <linux/list.h>
26#include <linux/slab.h>
23 27
24#include <sound/core.h> 28#include <sound/core.h>
25#include <sound/pcm.h> 29#include <sound/pcm.h>
@@ -29,6 +33,7 @@
29#include <asm/io.h> 33#include <asm/io.h>
30 34
31#include "fsl_dma.h" 35#include "fsl_dma.h"
36#include "fsl_ssi.h" /* For the offset of stx0 and srx0 */
32 37
33/* 38/*
34 * The formats that the DMA controller supports, which is anything 39 * The formats that the DMA controller supports, which is anything
@@ -52,26 +57,16 @@
52#define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ 57#define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
53 SNDRV_PCM_RATE_CONTINUOUS) 58 SNDRV_PCM_RATE_CONTINUOUS)
54 59
55/* DMA global data. This structure is used by fsl_dma_open() to determine 60struct dma_object {
56 * which DMA channels to assign to a substream. Unfortunately, ASoC V1 does 61 struct snd_soc_platform_driver dai;
57 * not allow the machine driver to provide this information to the PCM
58 * driver in advance, and there's no way to differentiate between the two
59 * DMA controllers. So for now, this driver only supports one SSI device
60 * using two DMA channels. We cannot support multiple DMA devices.
61 *
62 * ssi_stx_phys: bus address of SSI STX register
63 * ssi_srx_phys: bus address of SSI SRX register
64 * dma_channel: pointer to the DMA channel's registers
65 * irq: IRQ for this DMA channel
66 * assigned: set to 1 if that DMA channel is assigned to a substream
67 */
68static struct {
69 dma_addr_t ssi_stx_phys; 62 dma_addr_t ssi_stx_phys;
70 dma_addr_t ssi_srx_phys; 63 dma_addr_t ssi_srx_phys;
71 struct ccsr_dma_channel __iomem *dma_channel[2]; 64 unsigned int ssi_fifo_depth;
72 unsigned int irq[2]; 65 struct ccsr_dma_channel __iomem *channel;
73 unsigned int assigned[2]; 66 unsigned int irq;
74} dma_global_data; 67 bool assigned;
68 char path[1];
69};
75 70
76/* 71/*
77 * The number of DMA links to use. Two is the bare minimum, but if you 72 * The number of DMA links to use. Two is the bare minimum, but if you
@@ -88,8 +83,6 @@ static struct {
88 * structure. 83 * structure.
89 * 84 *
90 * @link[]: array of link descriptors 85 * @link[]: array of link descriptors
91 * @controller_id: which DMA controller (0, 1, ...)
92 * @channel_id: which DMA channel on the controller (0, 1, 2, ...)
93 * @dma_channel: pointer to the DMA channel's registers 86 * @dma_channel: pointer to the DMA channel's registers
94 * @irq: IRQ for this DMA channel 87 * @irq: IRQ for this DMA channel
95 * @substream: pointer to the substream object, needed by the ISR 88 * @substream: pointer to the substream object, needed by the ISR
@@ -104,12 +97,11 @@ static struct {
104 */ 97 */
105struct fsl_dma_private { 98struct fsl_dma_private {
106 struct fsl_dma_link_descriptor link[NUM_DMA_LINKS]; 99 struct fsl_dma_link_descriptor link[NUM_DMA_LINKS];
107 unsigned int controller_id;
108 unsigned int channel_id;
109 struct ccsr_dma_channel __iomem *dma_channel; 100 struct ccsr_dma_channel __iomem *dma_channel;
110 unsigned int irq; 101 unsigned int irq;
111 struct snd_pcm_substream *substream; 102 struct snd_pcm_substream *substream;
112 dma_addr_t ssi_sxx_phys; 103 dma_addr_t ssi_sxx_phys;
104 unsigned int ssi_fifo_depth;
113 dma_addr_t ld_buf_phys; 105 dma_addr_t ld_buf_phys;
114 unsigned int current_link; 106 unsigned int current_link;
115 dma_addr_t dma_buf_phys; 107 dma_addr_t dma_buf_phys;
@@ -185,13 +177,23 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)
185 struct fsl_dma_link_descriptor *link = 177 struct fsl_dma_link_descriptor *link =
186 &dma_private->link[dma_private->current_link]; 178 &dma_private->link[dma_private->current_link];
187 179
188 /* Update our link descriptors to point to the next period */ 180 /* Update our link descriptors to point to the next period. On a 36-bit
189 if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 181 * system, we also need to update the ESAD bits. We also set (keep) the
190 link->source_addr = 182 * snoop bits. See the comments in fsl_dma_hw_params() about snooping.
191 cpu_to_be32(dma_private->dma_buf_next); 183 */
192 else 184 if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
193 link->dest_addr = 185 link->source_addr = cpu_to_be32(dma_private->dma_buf_next);
194 cpu_to_be32(dma_private->dma_buf_next); 186#ifdef CONFIG_PHYS_64BIT
187 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
188 upper_32_bits(dma_private->dma_buf_next));
189#endif
190 } else {
191 link->dest_addr = cpu_to_be32(dma_private->dma_buf_next);
192#ifdef CONFIG_PHYS_64BIT
193 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
194 upper_32_bits(dma_private->dma_buf_next));
195#endif
196 }
195 197
196 /* Update our variables for next time */ 198 /* Update our variables for next time */
197 dma_private->dma_buf_next += dma_private->period_size; 199 dma_private->dma_buf_next += dma_private->period_size;
@@ -212,6 +214,9 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)
212static irqreturn_t fsl_dma_isr(int irq, void *dev_id) 214static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
213{ 215{
214 struct fsl_dma_private *dma_private = dev_id; 216 struct fsl_dma_private *dma_private = dev_id;
217 struct snd_pcm_substream *substream = dma_private->substream;
218 struct snd_soc_pcm_runtime *rtd = substream->private_data;
219 struct device *dev = rtd->platform->dev;
215 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; 220 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
216 irqreturn_t ret = IRQ_NONE; 221 irqreturn_t ret = IRQ_NONE;
217 u32 sr, sr2 = 0; 222 u32 sr, sr2 = 0;
@@ -222,11 +227,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
222 sr = in_be32(&dma_channel->sr); 227 sr = in_be32(&dma_channel->sr);
223 228
224 if (sr & CCSR_DMA_SR_TE) { 229 if (sr & CCSR_DMA_SR_TE) {
225 dev_err(dma_private->substream->pcm->card->dev, 230 dev_err(dev, "dma transmit error\n");
226 "DMA transmit error (controller=%u channel=%u irq=%u\n", 231 fsl_dma_abort_stream(substream);
227 dma_private->controller_id,
228 dma_private->channel_id, irq);
229 fsl_dma_abort_stream(dma_private->substream);
230 sr2 |= CCSR_DMA_SR_TE; 232 sr2 |= CCSR_DMA_SR_TE;
231 ret = IRQ_HANDLED; 233 ret = IRQ_HANDLED;
232 } 234 }
@@ -235,11 +237,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
235 ret = IRQ_HANDLED; 237 ret = IRQ_HANDLED;
236 238
237 if (sr & CCSR_DMA_SR_PE) { 239 if (sr & CCSR_DMA_SR_PE) {
238 dev_err(dma_private->substream->pcm->card->dev, 240 dev_err(dev, "dma programming error\n");
239 "DMA%u programming error (channel=%u irq=%u)\n", 241 fsl_dma_abort_stream(substream);
240 dma_private->controller_id,
241 dma_private->channel_id, irq);
242 fsl_dma_abort_stream(dma_private->substream);
243 sr2 |= CCSR_DMA_SR_PE; 242 sr2 |= CCSR_DMA_SR_PE;
244 ret = IRQ_HANDLED; 243 ret = IRQ_HANDLED;
245 } 244 }
@@ -253,8 +252,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
253 ret = IRQ_HANDLED; 252 ret = IRQ_HANDLED;
254 253
255 if (sr & CCSR_DMA_SR_EOSI) { 254 if (sr & CCSR_DMA_SR_EOSI) {
256 struct snd_pcm_substream *substream = dma_private->substream;
257
258 /* Tell ALSA we completed a period. */ 255 /* Tell ALSA we completed a period. */
259 snd_pcm_period_elapsed(substream); 256 snd_pcm_period_elapsed(substream);
260 257
@@ -288,11 +285,19 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
288 * This function is called when the codec driver calls snd_soc_new_pcms(), 285 * This function is called when the codec driver calls snd_soc_new_pcms(),
289 * once for each .dai_link in the machine driver's snd_soc_card 286 * once for each .dai_link in the machine driver's snd_soc_card
290 * structure. 287 * structure.
288 *
289 * snd_dma_alloc_pages() is just a front-end to dma_alloc_coherent(), which
290 * (currently) always allocates the DMA buffer in lowmem, even if GFP_HIGHMEM
291 * is specified. Therefore, any DMA buffers we allocate will always be in low
292 * memory, but we support for 36-bit physical addresses anyway.
293 *
294 * Regardless of where the memory is actually allocated, since the device can
295 * technically DMA to any 36-bit address, we do need to set the DMA mask to 36.
291 */ 296 */
292static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, 297static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
293 struct snd_pcm *pcm) 298 struct snd_pcm *pcm)
294{ 299{
295 static u64 fsl_dma_dmamask = DMA_BIT_MASK(32); 300 static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
296 int ret; 301 int ret;
297 302
298 if (!card->dev->dma_mask) 303 if (!card->dev->dma_mask)
@@ -301,25 +306,29 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
301 if (!card->dev->coherent_dma_mask) 306 if (!card->dev->coherent_dma_mask)
302 card->dev->coherent_dma_mask = fsl_dma_dmamask; 307 card->dev->coherent_dma_mask = fsl_dma_dmamask;
303 308
304 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, 309 /* Some codecs have separate DAIs for playback and capture, so we
305 fsl_dma_hardware.buffer_bytes_max, 310 * should allocate a DMA buffer only for the streams that are valid.
306 &pcm->streams[0].substream->dma_buffer); 311 */
307 if (ret) { 312
308 dev_err(card->dev, 313 if (dai->driver->playback.channels_min) {
309 "Can't allocate playback DMA buffer (size=%u)\n", 314 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
310 fsl_dma_hardware.buffer_bytes_max); 315 fsl_dma_hardware.buffer_bytes_max,
311 return -ENOMEM; 316 &pcm->streams[0].substream->dma_buffer);
317 if (ret) {
318 dev_err(card->dev, "can't alloc playback dma buffer\n");
319 return ret;
320 }
312 } 321 }
313 322
314 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, 323 if (dai->driver->capture.channels_min) {
315 fsl_dma_hardware.buffer_bytes_max, 324 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
316 &pcm->streams[1].substream->dma_buffer); 325 fsl_dma_hardware.buffer_bytes_max,
317 if (ret) { 326 &pcm->streams[1].substream->dma_buffer);
318 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); 327 if (ret) {
319 dev_err(card->dev, 328 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
320 "Can't allocate capture DMA buffer (size=%u)\n", 329 dev_err(card->dev, "can't alloc capture dma buffer\n");
321 fsl_dma_hardware.buffer_bytes_max); 330 return ret;
322 return -ENOMEM; 331 }
323 } 332 }
324 333
325 return 0; 334 return 0;
@@ -390,6 +399,10 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
390static int fsl_dma_open(struct snd_pcm_substream *substream) 399static int fsl_dma_open(struct snd_pcm_substream *substream)
391{ 400{
392 struct snd_pcm_runtime *runtime = substream->runtime; 401 struct snd_pcm_runtime *runtime = substream->runtime;
402 struct snd_soc_pcm_runtime *rtd = substream->private_data;
403 struct device *dev = rtd->platform->dev;
404 struct dma_object *dma =
405 container_of(rtd->platform->driver, struct dma_object, dai);
393 struct fsl_dma_private *dma_private; 406 struct fsl_dma_private *dma_private;
394 struct ccsr_dma_channel __iomem *dma_channel; 407 struct ccsr_dma_channel __iomem *dma_channel;
395 dma_addr_t ld_buf_phys; 408 dma_addr_t ld_buf_phys;
@@ -407,52 +420,45 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
407 ret = snd_pcm_hw_constraint_integer(runtime, 420 ret = snd_pcm_hw_constraint_integer(runtime,
408 SNDRV_PCM_HW_PARAM_PERIODS); 421 SNDRV_PCM_HW_PARAM_PERIODS);
409 if (ret < 0) { 422 if (ret < 0) {
410 dev_err(substream->pcm->card->dev, "invalid buffer size\n"); 423 dev_err(dev, "invalid buffer size\n");
411 return ret; 424 return ret;
412 } 425 }
413 426
414 channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; 427 channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
415 428
416 if (dma_global_data.assigned[channel]) { 429 if (dma->assigned) {
417 dev_err(substream->pcm->card->dev, 430 dev_err(dev, "dma channel already assigned\n");
418 "DMA channel already assigned\n");
419 return -EBUSY; 431 return -EBUSY;
420 } 432 }
421 433
422 dma_private = dma_alloc_coherent(substream->pcm->card->dev, 434 dma_private = dma_alloc_coherent(dev, sizeof(struct fsl_dma_private),
423 sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL); 435 &ld_buf_phys, GFP_KERNEL);
424 if (!dma_private) { 436 if (!dma_private) {
425 dev_err(substream->pcm->card->dev, 437 dev_err(dev, "can't allocate dma private data\n");
426 "can't allocate DMA private data\n");
427 return -ENOMEM; 438 return -ENOMEM;
428 } 439 }
429 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 440 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
430 dma_private->ssi_sxx_phys = dma_global_data.ssi_stx_phys; 441 dma_private->ssi_sxx_phys = dma->ssi_stx_phys;
431 else 442 else
432 dma_private->ssi_sxx_phys = dma_global_data.ssi_srx_phys; 443 dma_private->ssi_sxx_phys = dma->ssi_srx_phys;
433 444
434 dma_private->dma_channel = dma_global_data.dma_channel[channel]; 445 dma_private->ssi_fifo_depth = dma->ssi_fifo_depth;
435 dma_private->irq = dma_global_data.irq[channel]; 446 dma_private->dma_channel = dma->channel;
447 dma_private->irq = dma->irq;
436 dma_private->substream = substream; 448 dma_private->substream = substream;
437 dma_private->ld_buf_phys = ld_buf_phys; 449 dma_private->ld_buf_phys = ld_buf_phys;
438 dma_private->dma_buf_phys = substream->dma_buffer.addr; 450 dma_private->dma_buf_phys = substream->dma_buffer.addr;
439 451
440 /* We only support one DMA controller for now */
441 dma_private->controller_id = 0;
442 dma_private->channel_id = channel;
443
444 ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private); 452 ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private);
445 if (ret) { 453 if (ret) {
446 dev_err(substream->pcm->card->dev, 454 dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
447 "can't register ISR for IRQ %u (ret=%i)\n",
448 dma_private->irq, ret); 455 dma_private->irq, ret);
449 dma_free_coherent(substream->pcm->card->dev, 456 dma_free_coherent(dev, sizeof(struct fsl_dma_private),
450 sizeof(struct fsl_dma_private),
451 dma_private, dma_private->ld_buf_phys); 457 dma_private, dma_private->ld_buf_phys);
452 return ret; 458 return ret;
453 } 459 }
454 460
455 dma_global_data.assigned[channel] = 1; 461 dma->assigned = 1;
456 462
457 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 463 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
458 snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); 464 snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware);
@@ -546,13 +552,15 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
546{ 552{
547 struct snd_pcm_runtime *runtime = substream->runtime; 553 struct snd_pcm_runtime *runtime = substream->runtime;
548 struct fsl_dma_private *dma_private = runtime->private_data; 554 struct fsl_dma_private *dma_private = runtime->private_data;
555 struct snd_soc_pcm_runtime *rtd = substream->private_data;
556 struct device *dev = rtd->platform->dev;
549 557
550 /* Number of bits per sample */ 558 /* Number of bits per sample */
551 unsigned int sample_size = 559 unsigned int sample_bits =
552 snd_pcm_format_physical_width(params_format(hw_params)); 560 snd_pcm_format_physical_width(params_format(hw_params));
553 561
554 /* Number of bytes per frame */ 562 /* Number of bytes per frame */
555 unsigned int frame_size = 2 * (sample_size / 8); 563 unsigned int sample_bytes = sample_bits / 8;
556 564
557 /* Bus address of SSI STX register */ 565 /* Bus address of SSI STX register */
558 dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys; 566 dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys;
@@ -592,7 +600,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
592 * that offset here. While we're at it, also tell the DMA controller 600 * that offset here. While we're at it, also tell the DMA controller
593 * how much data to transfer per sample. 601 * how much data to transfer per sample.
594 */ 602 */
595 switch (sample_size) { 603 switch (sample_bits) {
596 case 8: 604 case 8:
597 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; 605 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
598 ssi_sxx_phys += 3; 606 ssi_sxx_phys += 3;
@@ -606,23 +614,42 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
606 break; 614 break;
607 default: 615 default:
608 /* We should never get here */ 616 /* We should never get here */
609 dev_err(substream->pcm->card->dev, 617 dev_err(dev, "unsupported sample size %u\n", sample_bits);
610 "unsupported sample size %u\n", sample_size);
611 return -EINVAL; 618 return -EINVAL;
612 } 619 }
613 620
614 /* 621 /*
615 * BWC should always be a multiple of the frame size. BWC determines 622 * BWC determines how many bytes are sent/received before the DMA
616 * how many bytes are sent/received before the DMA controller checks the 623 * controller checks the SSI to see if it needs to stop. BWC should
617 * SSI to see if it needs to stop. For playback, the transmit FIFO can 624 * always be a multiple of the frame size, so that we always transmit
618 * hold three frames, so we want to send two frames at a time. For 625 * whole frames. Each frame occupies two slots in the FIFO. The
619 * capture, the receive FIFO is triggered when it contains one frame, so 626 * parameter for CCSR_DMA_MR_BWC() is rounded down the next power of two
620 * we want to receive one frame at a time. 627 * (MR[BWC] can only represent even powers of two).
628 *
629 * To simplify the process, we set BWC to the largest value that is
630 * less than or equal to the FIFO watermark. For playback, this ensures
631 * that we transfer the maximum amount without overrunning the FIFO.
632 * For capture, this ensures that we transfer the maximum amount without
633 * underrunning the FIFO.
634 *
635 * f = SSI FIFO depth
636 * w = SSI watermark value (which equals f - 2)
637 * b = DMA bandwidth count (in bytes)
638 * s = sample size (in bytes, which equals frame_size * 2)
639 *
640 * For playback, we never transmit more than the transmit FIFO
641 * watermark, otherwise we might write more data than the FIFO can hold.
642 * The watermark is equal to the FIFO depth minus two.
643 *
644 * For capture, two equations must hold:
645 * w > f - (b / s)
646 * w >= b / s
647 *
648 * So, b > 2 * s, but b must also be <= s * w. To simplify, we set
649 * b = s * w, which is equal to
650 * (dma_private->ssi_fifo_depth - 2) * sample_bytes.
621 */ 651 */
622 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 652 mr |= CCSR_DMA_MR_BWC((dma_private->ssi_fifo_depth - 2) * sample_bytes);
623 mr |= CCSR_DMA_MR_BWC(2 * frame_size);
624 else
625 mr |= CCSR_DMA_MR_BWC(frame_size);
626 653
627 out_be32(&dma_channel->mr, mr); 654 out_be32(&dma_channel->mr, mr);
628 655
@@ -631,12 +658,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
631 658
632 link->count = cpu_to_be32(period_size); 659 link->count = cpu_to_be32(period_size);
633 660
634 /* Even though the DMA controller supports 36-bit addressing, 661 /* The snoop bit tells the DMA controller whether it should tell
635 * for simplicity we allow only 32-bit addresses for the audio
636 * buffer itself. This was enforced in fsl_dma_new() with the
637 * DMA mask.
638 *
639 * The snoop bit tells the DMA controller whether it should tell
640 * the ECM to snoop during a read or write to an address. For 662 * the ECM to snoop during a read or write to an address. For
641 * audio, we use DMA to transfer data between memory and an I/O 663 * audio, we use DMA to transfer data between memory and an I/O
642 * device (the SSI's STX0 or SRX0 register). Snooping is only 664 * device (the SSI's STX0 or SRX0 register). Snooping is only
@@ -651,20 +673,24 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
651 * flush out the data for the previous period. So if you 673 * flush out the data for the previous period. So if you
652 * increased period_bytes_min to a large enough size, you might 674 * increased period_bytes_min to a large enough size, you might
653 * get more performance by not snooping, and you'll still be 675 * get more performance by not snooping, and you'll still be
654 * okay. 676 * okay. You'll need to update fsl_dma_update_pointers() also.
655 */ 677 */
656 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 678 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
657 link->source_addr = cpu_to_be32(temp_addr); 679 link->source_addr = cpu_to_be32(temp_addr);
658 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); 680 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
681 upper_32_bits(temp_addr));
659 682
660 link->dest_addr = cpu_to_be32(ssi_sxx_phys); 683 link->dest_addr = cpu_to_be32(ssi_sxx_phys);
661 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); 684 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP |
685 upper_32_bits(ssi_sxx_phys));
662 } else { 686 } else {
663 link->source_addr = cpu_to_be32(ssi_sxx_phys); 687 link->source_addr = cpu_to_be32(ssi_sxx_phys);
664 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); 688 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP |
689 upper_32_bits(ssi_sxx_phys));
665 690
666 link->dest_addr = cpu_to_be32(temp_addr); 691 link->dest_addr = cpu_to_be32(temp_addr);
667 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); 692 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
693 upper_32_bits(temp_addr));
668 } 694 }
669 695
670 temp_addr += period_size; 696 temp_addr += period_size;
@@ -689,14 +715,29 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
689{ 715{
690 struct snd_pcm_runtime *runtime = substream->runtime; 716 struct snd_pcm_runtime *runtime = substream->runtime;
691 struct fsl_dma_private *dma_private = runtime->private_data; 717 struct fsl_dma_private *dma_private = runtime->private_data;
718 struct snd_soc_pcm_runtime *rtd = substream->private_data;
719 struct device *dev = rtd->platform->dev;
692 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; 720 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
693 dma_addr_t position; 721 dma_addr_t position;
694 snd_pcm_uframes_t frames; 722 snd_pcm_uframes_t frames;
695 723
696 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 724 /* Obtain the current DMA pointer, but don't read the ESAD bits if we
725 * only have 32-bit DMA addresses. This function is typically called
726 * in interrupt context, so we need to optimize it.
727 */
728 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
697 position = in_be32(&dma_channel->sar); 729 position = in_be32(&dma_channel->sar);
698 else 730#ifdef CONFIG_PHYS_64BIT
731 position |= (u64)(in_be32(&dma_channel->satr) &
732 CCSR_DMA_ATR_ESAD_MASK) << 32;
733#endif
734 } else {
699 position = in_be32(&dma_channel->dar); 735 position = in_be32(&dma_channel->dar);
736#ifdef CONFIG_PHYS_64BIT
737 position |= (u64)(in_be32(&dma_channel->datr) &
738 CCSR_DMA_ATR_ESAD_MASK) << 32;
739#endif
740 }
700 741
701 /* 742 /*
702 * When capture is started, the SSI immediately starts to fill its FIFO. 743 * When capture is started, the SSI immediately starts to fill its FIFO.
@@ -710,8 +751,7 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
710 751
711 if ((position < dma_private->dma_buf_phys) || 752 if ((position < dma_private->dma_buf_phys) ||
712 (position > dma_private->dma_buf_end)) { 753 (position > dma_private->dma_buf_end)) {
713 dev_err(substream->pcm->card->dev, 754 dev_err(dev, "dma pointer is out of range, halting stream\n");
714 "dma pointer is out of range, halting stream\n");
715 return SNDRV_PCM_POS_XRUN; 755 return SNDRV_PCM_POS_XRUN;
716 } 756 }
717 757
@@ -772,26 +812,28 @@ static int fsl_dma_close(struct snd_pcm_substream *substream)
772{ 812{
773 struct snd_pcm_runtime *runtime = substream->runtime; 813 struct snd_pcm_runtime *runtime = substream->runtime;
774 struct fsl_dma_private *dma_private = runtime->private_data; 814 struct fsl_dma_private *dma_private = runtime->private_data;
775 int dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; 815 struct snd_soc_pcm_runtime *rtd = substream->private_data;
816 struct device *dev = rtd->platform->dev;
817 struct dma_object *dma =
818 container_of(rtd->platform->driver, struct dma_object, dai);
776 819
777 if (dma_private) { 820 if (dma_private) {
778 if (dma_private->irq) 821 if (dma_private->irq)
779 free_irq(dma_private->irq, dma_private); 822 free_irq(dma_private->irq, dma_private);
780 823
781 if (dma_private->ld_buf_phys) { 824 if (dma_private->ld_buf_phys) {
782 dma_unmap_single(substream->pcm->card->dev, 825 dma_unmap_single(dev, dma_private->ld_buf_phys,
783 dma_private->ld_buf_phys, 826 sizeof(dma_private->link),
784 sizeof(dma_private->link), DMA_TO_DEVICE); 827 DMA_TO_DEVICE);
785 } 828 }
786 829
787 /* Deallocate the fsl_dma_private structure */ 830 /* Deallocate the fsl_dma_private structure */
788 dma_free_coherent(substream->pcm->card->dev, 831 dma_free_coherent(dev, sizeof(struct fsl_dma_private),
789 sizeof(struct fsl_dma_private), 832 dma_private, dma_private->ld_buf_phys);
790 dma_private, dma_private->ld_buf_phys);
791 substream->runtime->private_data = NULL; 833 substream->runtime->private_data = NULL;
792 } 834 }
793 835
794 dma_global_data.assigned[dir] = 0; 836 dma->assigned = 0;
795 837
796 return 0; 838 return 0;
797} 839}
@@ -814,6 +856,37 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)
814 } 856 }
815} 857}
816 858
859/**
860 * find_ssi_node -- returns the SSI node that points to his DMA channel node
861 *
862 * Although this DMA driver attempts to operate independently of the other
863 * devices, it still needs to determine some information about the SSI device
864 * that it's working with. Unfortunately, the device tree does not contain
865 * a pointer from the DMA channel node to the SSI node -- the pointer goes the
866 * other way. So we need to scan the device tree for SSI nodes until we find
867 * the one that points to the given DMA channel node. It's ugly, but at least
868 * it's contained in this one function.
869 */
870static struct device_node *find_ssi_node(struct device_node *dma_channel_np)
871{
872 struct device_node *ssi_np, *np;
873
874 for_each_compatible_node(ssi_np, NULL, "fsl,mpc8610-ssi") {
875 /* Check each DMA phandle to see if it points to us. We
876 * assume that device_node pointers are a valid comparison.
877 */
878 np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0);
879 if (np == dma_channel_np)
880 return ssi_np;
881
882 np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0);
883 if (np == dma_channel_np)
884 return ssi_np;
885 }
886
887 return NULL;
888}
889
817static struct snd_pcm_ops fsl_dma_ops = { 890static struct snd_pcm_ops fsl_dma_ops = {
818 .open = fsl_dma_open, 891 .open = fsl_dma_open,
819 .close = fsl_dma_close, 892 .close = fsl_dma_close,
@@ -823,59 +896,114 @@ static struct snd_pcm_ops fsl_dma_ops = {
823 .pointer = fsl_dma_pointer, 896 .pointer = fsl_dma_pointer,
824}; 897};
825 898
826struct snd_soc_platform fsl_soc_platform = { 899static int __devinit fsl_soc_dma_probe(struct platform_device *pdev,
827 .name = "fsl-dma", 900 const struct of_device_id *match)
828 .pcm_ops = &fsl_dma_ops, 901 {
829 .pcm_new = fsl_dma_new, 902 struct dma_object *dma;
830 .pcm_free = fsl_dma_free_dma_buffers, 903 struct device_node *np = pdev->dev.of_node;
831}; 904 struct device_node *ssi_np;
832EXPORT_SYMBOL_GPL(fsl_soc_platform); 905 struct resource res;
906 const uint32_t *iprop;
907 int ret;
833 908
834/** 909 /* Find the SSI node that points to us. */
835 * fsl_dma_configure: store the DMA parameters from the fabric driver. 910 ssi_np = find_ssi_node(np);
836 * 911 if (!ssi_np) {
837 * This function is called by the ASoC fabric driver to give us the DMA and 912 dev_err(&pdev->dev, "cannot find parent SSI node\n");
838 * SSI channel information. 913 return -ENODEV;
839 * 914 }
840 * Unfortunately, ASoC V1 does make it possible to determine the DMA/SSI 915
841 * data when a substream is created, so for now we need to store this data 916 ret = of_address_to_resource(ssi_np, 0, &res);
842 * into a global variable. This means that we can only support one DMA 917 if (ret) {
843 * controller, and hence only one SSI. 918 dev_err(&pdev->dev, "could not determine resources for %s\n",
844 */ 919 ssi_np->full_name);
845int fsl_dma_configure(struct fsl_dma_info *dma_info) 920 of_node_put(ssi_np);
921 return ret;
922 }
923
924 dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL);
925 if (!dma) {
926 dev_err(&pdev->dev, "could not allocate dma object\n");
927 of_node_put(ssi_np);
928 return -ENOMEM;
929 }
930
931 strcpy(dma->path, np->full_name);
932 dma->dai.ops = &fsl_dma_ops;
933 dma->dai.pcm_new = fsl_dma_new;
934 dma->dai.pcm_free = fsl_dma_free_dma_buffers;
935
936 /* Store the SSI-specific information that we need */
937 dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0);
938 dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0);
939
940 iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
941 if (iprop)
942 dma->ssi_fifo_depth = *iprop;
943 else
944 /* Older 8610 DTs didn't have the fifo-depth property */
945 dma->ssi_fifo_depth = 8;
946
947 of_node_put(ssi_np);
948
949 ret = snd_soc_register_platform(&pdev->dev, &dma->dai);
950 if (ret) {
951 dev_err(&pdev->dev, "could not register platform\n");
952 kfree(dma);
953 return ret;
954 }
955
956 dma->channel = of_iomap(np, 0);
957 dma->irq = irq_of_parse_and_map(np, 0);
958
959 dev_set_drvdata(&pdev->dev, dma);
960
961 return 0;
962}
963
964static int __devexit fsl_soc_dma_remove(struct platform_device *pdev)
846{ 965{
847 static int initialized; 966 struct dma_object *dma = dev_get_drvdata(&pdev->dev);
848 967
849 /* We only support one DMA controller for now */ 968 snd_soc_unregister_platform(&pdev->dev);
850 if (initialized) 969 iounmap(dma->channel);
851 return 0; 970 irq_dispose_mapping(dma->irq);
971 kfree(dma);
852 972
853 dma_global_data.ssi_stx_phys = dma_info->ssi_stx_phys; 973 return 0;
854 dma_global_data.ssi_srx_phys = dma_info->ssi_srx_phys;
855 dma_global_data.dma_channel[0] = dma_info->dma_channel[0];
856 dma_global_data.dma_channel[1] = dma_info->dma_channel[1];
857 dma_global_data.irq[0] = dma_info->dma_irq[0];
858 dma_global_data.irq[1] = dma_info->dma_irq[1];
859 dma_global_data.assigned[0] = 0;
860 dma_global_data.assigned[1] = 0;
861
862 initialized = 1;
863 return 1;
864} 974}
865EXPORT_SYMBOL_GPL(fsl_dma_configure);
866 975
867static int __init fsl_soc_platform_init(void) 976static const struct of_device_id fsl_soc_dma_ids[] = {
977 { .compatible = "fsl,ssi-dma-channel", },
978 {}
979};
980MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids);
981
982static struct of_platform_driver fsl_soc_dma_driver = {
983 .driver = {
984 .name = "fsl-pcm-audio",
985 .owner = THIS_MODULE,
986 .of_match_table = fsl_soc_dma_ids,
987 },
988 .probe = fsl_soc_dma_probe,
989 .remove = __devexit_p(fsl_soc_dma_remove),
990};
991
992static int __init fsl_soc_dma_init(void)
868{ 993{
869 return snd_soc_register_platform(&fsl_soc_platform); 994 pr_info("Freescale Elo DMA ASoC PCM Driver\n");
995
996 return of_register_platform_driver(&fsl_soc_dma_driver);
870} 997}
871module_init(fsl_soc_platform_init);
872 998
873static void __exit fsl_soc_platform_exit(void) 999static void __exit fsl_soc_dma_exit(void)
874{ 1000{
875 snd_soc_unregister_platform(&fsl_soc_platform); 1001 of_unregister_platform_driver(&fsl_soc_dma_driver);
876} 1002}
877module_exit(fsl_soc_platform_exit); 1003
1004module_init(fsl_soc_dma_init);
1005module_exit(fsl_soc_dma_exit);
878 1006
879MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 1007MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
880MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module"); 1008MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver");
881MODULE_LICENSE("GPL"); 1009MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_dma.h b/sound/soc/fsl/fsl_dma.h
index 385d4a42603c..78fee97e8036 100644
--- a/sound/soc/fsl/fsl_dma.h
+++ b/sound/soc/fsl/fsl_dma.h
@@ -126,24 +126,4 @@ struct fsl_dma_link_descriptor {
126 u8 res[4]; /* Reserved */ 126 u8 res[4]; /* Reserved */
127} __attribute__ ((aligned(32), packed)); 127} __attribute__ ((aligned(32), packed));
128 128
129/* DMA information needed to create a snd_soc_dai object
130 *
131 * ssi_stx_phys: bus address of SSI STX register to use
132 * ssi_srx_phys: bus address of SSI SRX register to use
133 * dma[0]: points to the DMA channel to use for playback
134 * dma[1]: points to the DMA channel to use for capture
135 * dma_irq[0]: IRQ of the DMA channel to use for playback
136 * dma_irq[1]: IRQ of the DMA channel to use for capture
137 */
138struct fsl_dma_info {
139 dma_addr_t ssi_stx_phys;
140 dma_addr_t ssi_srx_phys;
141 struct ccsr_dma_channel __iomem *dma_channel[2];
142 unsigned int dma_irq[2];
143};
144
145extern struct snd_soc_platform fsl_soc_platform;
146
147int fsl_dma_configure(struct fsl_dma_info *dma_info);
148
149#endif 129#endif
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 762c1b8e8e4e..4cc167a7aeb8 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -3,10 +3,11 @@
3 * 3 *
4 * Author: Timur Tabi <timur@freescale.com> 4 * Author: Timur Tabi <timur@freescale.com>
5 * 5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed 6 * Copyright 2007-2010 Freescale Semiconductor, Inc.
7 * under the terms of the GNU General Public License version 2. This 7 *
8 * program is licensed "as is" without any warranty of any kind, whether 8 * This file is licensed under the terms of the GNU General Public License
9 * express or implied. 9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
10 */ 11 */
11 12
12#include <linux/init.h> 13#include <linux/init.h>
@@ -15,6 +16,7 @@
15#include <linux/device.h> 16#include <linux/device.h>
16#include <linux/delay.h> 17#include <linux/delay.h>
17#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/of_platform.h>
18 20
19#include <sound/core.h> 21#include <sound/core.h>
20#include <sound/pcm.h> 22#include <sound/pcm.h>
@@ -22,8 +24,6 @@
22#include <sound/initval.h> 24#include <sound/initval.h>
23#include <sound/soc.h> 25#include <sound/soc.h>
24 26
25#include <asm/immap_86xx.h>
26
27#include "fsl_ssi.h" 27#include "fsl_ssi.h"
28 28
29/** 29/**
@@ -71,33 +71,32 @@
71/** 71/**
72 * fsl_ssi_private: per-SSI private data 72 * fsl_ssi_private: per-SSI private data
73 * 73 *
74 * @name: short name for this device ("SSI0", "SSI1", etc)
75 * @ssi: pointer to the SSI's registers 74 * @ssi: pointer to the SSI's registers
76 * @ssi_phys: physical address of the SSI registers 75 * @ssi_phys: physical address of the SSI registers
77 * @irq: IRQ of this SSI 76 * @irq: IRQ of this SSI
78 * @first_stream: pointer to the stream that was opened first 77 * @first_stream: pointer to the stream that was opened first
79 * @second_stream: pointer to second stream 78 * @second_stream: pointer to second stream
80 * @dev: struct device pointer
81 * @playback: the number of playback streams opened 79 * @playback: the number of playback streams opened
82 * @capture: the number of capture streams opened 80 * @capture: the number of capture streams opened
83 * @asynchronous: 0=synchronous mode, 1=asynchronous mode 81 * @asynchronous: 0=synchronous mode, 1=asynchronous mode
84 * @cpu_dai: the CPU DAI for this device 82 * @cpu_dai: the CPU DAI for this device
85 * @dev_attr: the sysfs device attribute structure 83 * @dev_attr: the sysfs device attribute structure
86 * @stats: SSI statistics 84 * @stats: SSI statistics
85 * @name: name for this device
87 */ 86 */
88struct fsl_ssi_private { 87struct fsl_ssi_private {
89 char name[8];
90 struct ccsr_ssi __iomem *ssi; 88 struct ccsr_ssi __iomem *ssi;
91 dma_addr_t ssi_phys; 89 dma_addr_t ssi_phys;
92 unsigned int irq; 90 unsigned int irq;
93 struct snd_pcm_substream *first_stream; 91 struct snd_pcm_substream *first_stream;
94 struct snd_pcm_substream *second_stream; 92 struct snd_pcm_substream *second_stream;
95 struct device *dev;
96 unsigned int playback; 93 unsigned int playback;
97 unsigned int capture; 94 unsigned int capture;
98 int asynchronous; 95 int asynchronous;
99 struct snd_soc_dai cpu_dai; 96 unsigned int fifo_depth;
97 struct snd_soc_dai_driver cpu_dai_drv;
100 struct device_attribute dev_attr; 98 struct device_attribute dev_attr;
99 struct platform_device *pdev;
101 100
102 struct { 101 struct {
103 unsigned int rfrc; 102 unsigned int rfrc;
@@ -122,6 +121,8 @@ struct fsl_ssi_private {
122 unsigned int tfe1; 121 unsigned int tfe1;
123 unsigned int tfe0; 122 unsigned int tfe0;
124 } stats; 123 } stats;
124
125 char name[1];
125}; 126};
126 127
127/** 128/**
@@ -280,7 +281,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
280 struct snd_soc_dai *dai) 281 struct snd_soc_dai *dai)
281{ 282{
282 struct snd_soc_pcm_runtime *rtd = substream->private_data; 283 struct snd_soc_pcm_runtime *rtd = substream->private_data;
283 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 284 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
284 285
285 /* 286 /*
286 * If this is the first stream opened, then request the IRQ 287 * If this is the first stream opened, then request the IRQ
@@ -290,6 +291,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
290 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 291 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
291 int ret; 292 int ret;
292 293
294 /* The 'name' should not have any slashes in it. */
293 ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, 295 ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0,
294 ssi_private->name, ssi_private); 296 ssi_private->name, ssi_private);
295 if (ret < 0) { 297 if (ret < 0) {
@@ -336,11 +338,20 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
336 338
337 /* 339 /*
338 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We 340 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
339 * don't use FIFO 1. Since the SSI only supports stereo, the 341 * don't use FIFO 1. We program the transmit water to signal a
340 * watermark should never be an odd number. 342 * DMA transfer if there are only two (or fewer) elements left
343 * in the FIFO. Two elements equals one frame (left channel,
344 * right channel). This value, however, depends on the depth of
345 * the transmit buffer.
346 *
347 * We program the receive FIFO to notify us if at least two
348 * elements (one frame) have been written to the FIFO. We could
349 * make this value larger (and maybe we should), but this way
350 * data will be written to memory as soon as it's available.
341 */ 351 */
342 out_be32(&ssi->sfcsr, 352 out_be32(&ssi->sfcsr,
343 CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2)); 353 CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
354 CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2));
344 355
345 /* 356 /*
346 * We keep the SSI disabled because if we enable it, then the 357 * We keep the SSI disabled because if we enable it, then the
@@ -422,7 +433,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
422static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, 433static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
423 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) 434 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
424{ 435{
425 struct fsl_ssi_private *ssi_private = cpu_dai->private_data; 436 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
426 437
427 if (substream == ssi_private->first_stream) { 438 if (substream == ssi_private->first_stream) {
428 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 439 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
@@ -458,7 +469,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
458 struct snd_soc_dai *dai) 469 struct snd_soc_dai *dai)
459{ 470{
460 struct snd_soc_pcm_runtime *rtd = substream->private_data; 471 struct snd_soc_pcm_runtime *rtd = substream->private_data;
461 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 472 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
462 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 473 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
463 474
464 switch (cmd) { 475 switch (cmd) {
@@ -497,7 +508,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
497 struct snd_soc_dai *dai) 508 struct snd_soc_dai *dai)
498{ 509{
499 struct snd_soc_pcm_runtime *rtd = substream->private_data; 510 struct snd_soc_pcm_runtime *rtd = substream->private_data;
500 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 511 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
501 512
502 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 513 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
503 ssi_private->playback--; 514 ssi_private->playback--;
@@ -523,56 +534,15 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
523 } 534 }
524} 535}
525 536
526/**
527 * fsl_ssi_set_sysclk: set the clock frequency and direction
528 *
529 * This function is called by the machine driver to tell us what the clock
530 * frequency and direction are.
531 *
532 * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN),
533 * and we don't care about the frequency. Return an error if the direction
534 * is not SND_SOC_CLOCK_IN.
535 *
536 * @clk_id: reserved, should be zero
537 * @freq: the frequency of the given clock ID, currently ignored
538 * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
539 */
540static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai,
541 int clk_id, unsigned int freq, int dir)
542{
543
544 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
545}
546
547/**
548 * fsl_ssi_set_fmt: set the serial format.
549 *
550 * This function is called by the machine driver to tell us what serial
551 * format to use.
552 *
553 * Currently, we only support I2S mode. Return an error if the format is
554 * not SND_SOC_DAIFMT_I2S.
555 *
556 * @format: one of SND_SOC_DAIFMT_xxx
557 */
558static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
559{
560 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
561}
562
563/**
564 * fsl_ssi_dai_template: template CPU DAI for the SSI
565 */
566static struct snd_soc_dai_ops fsl_ssi_dai_ops = { 537static struct snd_soc_dai_ops fsl_ssi_dai_ops = {
567 .startup = fsl_ssi_startup, 538 .startup = fsl_ssi_startup,
568 .hw_params = fsl_ssi_hw_params, 539 .hw_params = fsl_ssi_hw_params,
569 .shutdown = fsl_ssi_shutdown, 540 .shutdown = fsl_ssi_shutdown,
570 .trigger = fsl_ssi_trigger, 541 .trigger = fsl_ssi_trigger,
571 .set_sysclk = fsl_ssi_set_sysclk,
572 .set_fmt = fsl_ssi_set_fmt,
573}; 542};
574 543
575static struct snd_soc_dai fsl_ssi_dai_template = { 544/* Template for the CPU dai driver structure */
545static struct snd_soc_dai_driver fsl_ssi_dai_template = {
576 .playback = { 546 .playback = {
577 /* The SSI does not support monaural audio. */ 547 /* The SSI does not support monaural audio. */
578 .channels_min = 2, 548 .channels_min = 2,
@@ -640,95 +610,195 @@ static ssize_t fsl_sysfs_ssi_show(struct device *dev,
640} 610}
641 611
642/** 612/**
643 * fsl_ssi_create_dai: create a snd_soc_dai structure 613 * Make every character in a string lower-case
644 *
645 * This function is called by the machine driver to create a snd_soc_dai
646 * structure. The function creates an ssi_private object, which contains
647 * the snd_soc_dai. It also creates the sysfs statistics device.
648 */ 614 */
649struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) 615static void make_lowercase(char *s)
616{
617 char *p = s;
618 char c;
619
620 while ((c = *p)) {
621 if ((c >= 'A') && (c <= 'Z'))
622 *p = c + ('a' - 'A');
623 p++;
624 }
625}
626
627static int __devinit fsl_ssi_probe(struct platform_device *pdev,
628 const struct of_device_id *match)
650{ 629{
651 struct snd_soc_dai *fsl_ssi_dai;
652 struct fsl_ssi_private *ssi_private; 630 struct fsl_ssi_private *ssi_private;
653 int ret = 0; 631 int ret = 0;
654 struct device_attribute *dev_attr; 632 struct device_attribute *dev_attr = NULL;
633 struct device_node *np = pdev->dev.of_node;
634 const char *p, *sprop;
635 const uint32_t *iprop;
636 struct resource res;
637 char name[64];
638
639 /* SSIs that are not connected on the board should have a
640 * status = "disabled"
641 * property in their device tree nodes.
642 */
643 if (!of_device_is_available(np))
644 return -ENODEV;
645
646 /* Check for a codec-handle property. */
647 if (!of_get_property(np, "codec-handle", NULL)) {
648 dev_err(&pdev->dev, "missing codec-handle property\n");
649 return -ENODEV;
650 }
655 651
656 ssi_private = kzalloc(sizeof(struct fsl_ssi_private), GFP_KERNEL); 652 /* We only support the SSI in "I2S Slave" mode */
653 sprop = of_get_property(np, "fsl,mode", NULL);
654 if (!sprop || strcmp(sprop, "i2s-slave")) {
655 dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop);
656 return -ENODEV;
657 }
658
659 /* The DAI name is the last part of the full name of the node. */
660 p = strrchr(np->full_name, '/') + 1;
661 ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p),
662 GFP_KERNEL);
657 if (!ssi_private) { 663 if (!ssi_private) {
658 dev_err(ssi_info->dev, "could not allocate DAI object\n"); 664 dev_err(&pdev->dev, "could not allocate DAI object\n");
659 return NULL; 665 return -ENOMEM;
660 } 666 }
661 memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template,
662 sizeof(struct snd_soc_dai));
663 667
664 fsl_ssi_dai = &ssi_private->cpu_dai; 668 strcpy(ssi_private->name, p);
665 dev_attr = &ssi_private->dev_attr;
666 669
667 sprintf(ssi_private->name, "ssi%u", (u8) ssi_info->id); 670 /* Initialize this copy of the CPU DAI driver structure */
668 ssi_private->ssi = ssi_info->ssi; 671 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
669 ssi_private->ssi_phys = ssi_info->ssi_phys; 672 sizeof(fsl_ssi_dai_template));
670 ssi_private->irq = ssi_info->irq; 673 ssi_private->cpu_dai_drv.name = ssi_private->name;
671 ssi_private->dev = ssi_info->dev;
672 ssi_private->asynchronous = ssi_info->asynchronous;
673 674
674 dev_set_drvdata(ssi_private->dev, fsl_ssi_dai); 675 /* Get the addresses and IRQ */
676 ret = of_address_to_resource(np, 0, &res);
677 if (ret) {
678 dev_err(&pdev->dev, "could not determine device resources\n");
679 kfree(ssi_private);
680 return ret;
681 }
682 ssi_private->ssi = ioremap(res.start, 1 + res.end - res.start);
683 ssi_private->ssi_phys = res.start;
684 ssi_private->irq = irq_of_parse_and_map(np, 0);
685
686 /* Are the RX and the TX clocks locked? */
687 if (of_find_property(np, "fsl,ssi-asynchronous", NULL))
688 ssi_private->asynchronous = 1;
689 else
690 ssi_private->cpu_dai_drv.symmetric_rates = 1;
691
692 /* Determine the FIFO depth. */
693 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
694 if (iprop)
695 ssi_private->fifo_depth = *iprop;
696 else
697 /* Older 8610 DTs didn't have the fifo-depth property */
698 ssi_private->fifo_depth = 8;
675 699
676 /* Initialize the the device_attribute structure */ 700 /* Initialize the the device_attribute structure */
677 dev_attr->attr.name = "ssi-stats"; 701 dev_attr = &ssi_private->dev_attr;
702 dev_attr->attr.name = "statistics";
678 dev_attr->attr.mode = S_IRUGO; 703 dev_attr->attr.mode = S_IRUGO;
679 dev_attr->show = fsl_sysfs_ssi_show; 704 dev_attr->show = fsl_sysfs_ssi_show;
680 705
681 ret = device_create_file(ssi_private->dev, dev_attr); 706 ret = device_create_file(&pdev->dev, dev_attr);
682 if (ret) { 707 if (ret) {
683 dev_err(ssi_info->dev, "could not create sysfs %s file\n", 708 dev_err(&pdev->dev, "could not create sysfs %s file\n",
684 ssi_private->dev_attr.attr.name); 709 ssi_private->dev_attr.attr.name);
685 kfree(fsl_ssi_dai); 710 goto error;
686 return NULL;
687 } 711 }
688 712
689 fsl_ssi_dai->private_data = ssi_private; 713 /* Register with ASoC */
690 fsl_ssi_dai->name = ssi_private->name; 714 dev_set_drvdata(&pdev->dev, ssi_private);
691 fsl_ssi_dai->id = ssi_info->id; 715
692 fsl_ssi_dai->dev = ssi_info->dev; 716 ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv);
693 fsl_ssi_dai->symmetric_rates = 1; 717 if (ret) {
718 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
719 goto error;
720 }
694 721
695 ret = snd_soc_register_dai(fsl_ssi_dai); 722 /* Trigger the machine driver's probe function. The platform driver
696 if (ret != 0) { 723 * name of the machine driver is taken from the /model property of the
697 dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret); 724 * device tree. We also pass the address of the CPU DAI driver
698 kfree(fsl_ssi_dai); 725 * structure.
699 return NULL; 726 */
727 sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
728 /* Sometimes the model name has a "fsl," prefix, so we strip that. */
729 p = strrchr(sprop, ',');
730 if (p)
731 sprop = p + 1;
732 snprintf(name, sizeof(name), "snd-soc-%s", sprop);
733 make_lowercase(name);
734
735 ssi_private->pdev =
736 platform_device_register_data(&pdev->dev, name, 0, NULL, 0);
737 if (IS_ERR(ssi_private->pdev)) {
738 ret = PTR_ERR(ssi_private->pdev);
739 dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
740 goto error;
700 } 741 }
701 742
702 return fsl_ssi_dai; 743 return 0;
744
745error:
746 snd_soc_unregister_dai(&pdev->dev);
747 dev_set_drvdata(&pdev->dev, NULL);
748 if (dev_attr)
749 device_remove_file(&pdev->dev, dev_attr);
750 irq_dispose_mapping(ssi_private->irq);
751 iounmap(ssi_private->ssi);
752 kfree(ssi_private);
753
754 return ret;
703} 755}
704EXPORT_SYMBOL_GPL(fsl_ssi_create_dai);
705 756
706/** 757static int fsl_ssi_remove(struct platform_device *pdev)
707 * fsl_ssi_destroy_dai: destroy the snd_soc_dai object
708 *
709 * This function undoes the operations of fsl_ssi_create_dai()
710 */
711void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
712{ 758{
713 struct fsl_ssi_private *ssi_private = 759 struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
714 container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai);
715
716 device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
717 760
718 snd_soc_unregister_dai(&ssi_private->cpu_dai); 761 platform_device_unregister(ssi_private->pdev);
762 snd_soc_unregister_dai(&pdev->dev);
763 device_remove_file(&pdev->dev, &ssi_private->dev_attr);
719 764
720 kfree(ssi_private); 765 kfree(ssi_private);
766 dev_set_drvdata(&pdev->dev, NULL);
767
768 return 0;
721} 769}
722EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); 770
771static const struct of_device_id fsl_ssi_ids[] = {
772 { .compatible = "fsl,mpc8610-ssi", },
773 {}
774};
775MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
776
777static struct of_platform_driver fsl_ssi_driver = {
778 .driver = {
779 .name = "fsl-ssi-dai",
780 .owner = THIS_MODULE,
781 .of_match_table = fsl_ssi_ids,
782 },
783 .probe = fsl_ssi_probe,
784 .remove = fsl_ssi_remove,
785};
723 786
724static int __init fsl_ssi_init(void) 787static int __init fsl_ssi_init(void)
725{ 788{
726 printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n"); 789 printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
727 790
728 return 0; 791 return of_register_platform_driver(&fsl_ssi_driver);
729} 792}
793
794static void __exit fsl_ssi_exit(void)
795{
796 of_unregister_platform_driver(&fsl_ssi_driver);
797}
798
730module_init(fsl_ssi_init); 799module_init(fsl_ssi_init);
800module_exit(fsl_ssi_exit);
731 801
732MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 802MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
733MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); 803MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
734MODULE_LICENSE("GPL"); 804MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index eade01feaab6..217300029b5b 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -196,31 +196,5 @@ struct ccsr_ssi {
196#define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT) 196#define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT)
197#define CCSR_SSI_SOR_SYNRST 0x00000001 197#define CCSR_SSI_SOR_SYNRST 0x00000001
198 198
199/* Instantiation data for an SSI interface
200 *
201 * This structure contains all the information that the the SSI driver needs
202 * to instantiate an SSI interface with ALSA. The machine driver should
203 * create this structure, fill it in, call fsl_ssi_create_dai(), and then
204 * delete the structure.
205 *
206 * id: which SSI this is (0, 1, etc. )
207 * ssi: pointer to the SSI's registers
208 * ssi_phys: physical address of the SSI registers
209 * irq: IRQ of this SSI
210 * dev: struct device, used to create the sysfs statistics file
211 * asynchronous: 0=synchronous mode, 1=asynchronous mode
212*/
213struct fsl_ssi_info {
214 unsigned int id;
215 struct ccsr_ssi __iomem *ssi;
216 dma_addr_t ssi_phys;
217 unsigned int irq;
218 struct device *dev;
219 int asynchronous;
220};
221
222struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
223void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai);
224
225#endif 199#endif
226 200
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 3dcd1469f283..dce6b551cd78 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -9,6 +9,8 @@
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/of_device.h> 10#include <linux/of_device.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/of_device.h>
13#include <linux/of_platform.h>
12 14
13#include <sound/soc.h> 15#include <sound/soc.h>
14 16
@@ -107,7 +109,7 @@ static int psc_dma_hw_free(struct snd_pcm_substream *substream)
107static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd) 109static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
108{ 110{
109 struct snd_soc_pcm_runtime *rtd = substream->private_data; 111 struct snd_soc_pcm_runtime *rtd = substream->private_data;
110 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 112 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
111 struct snd_pcm_runtime *runtime = substream->runtime; 113 struct snd_pcm_runtime *runtime = substream->runtime;
112 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); 114 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
113 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 115 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
@@ -212,7 +214,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream)
212{ 214{
213 struct snd_pcm_runtime *runtime = substream->runtime; 215 struct snd_pcm_runtime *runtime = substream->runtime;
214 struct snd_soc_pcm_runtime *rtd = substream->private_data; 216 struct snd_soc_pcm_runtime *rtd = substream->private_data;
215 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 217 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
216 struct psc_dma_stream *s; 218 struct psc_dma_stream *s;
217 int rc; 219 int rc;
218 220
@@ -239,7 +241,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream)
239static int psc_dma_close(struct snd_pcm_substream *substream) 241static int psc_dma_close(struct snd_pcm_substream *substream)
240{ 242{
241 struct snd_soc_pcm_runtime *rtd = substream->private_data; 243 struct snd_soc_pcm_runtime *rtd = substream->private_data;
242 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 244 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
243 struct psc_dma_stream *s; 245 struct psc_dma_stream *s;
244 246
245 dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream); 247 dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream);
@@ -264,7 +266,7 @@ static snd_pcm_uframes_t
264psc_dma_pointer(struct snd_pcm_substream *substream) 266psc_dma_pointer(struct snd_pcm_substream *substream)
265{ 267{
266 struct snd_soc_pcm_runtime *rtd = substream->private_data; 268 struct snd_soc_pcm_runtime *rtd = substream->private_data;
267 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 269 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
268 struct psc_dma_stream *s; 270 struct psc_dma_stream *s;
269 dma_addr_t count; 271 dma_addr_t count;
270 272
@@ -302,11 +304,11 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
302 struct snd_pcm *pcm) 304 struct snd_pcm *pcm)
303{ 305{
304 struct snd_soc_pcm_runtime *rtd = pcm->private_data; 306 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
305 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 307 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
306 size_t size = psc_dma_hardware.buffer_bytes_max; 308 size_t size = psc_dma_hardware.buffer_bytes_max;
307 int rc = 0; 309 int rc = 0;
308 310
309 dev_dbg(rtd->socdev->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", 311 dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
310 card, dai, pcm); 312 card, dai, pcm);
311 313
312 if (!card->dev->dma_mask) 314 if (!card->dev->dma_mask)
@@ -328,8 +330,8 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
328 goto capture_alloc_err; 330 goto capture_alloc_err;
329 } 331 }
330 332
331 if (rtd->socdev->card->codec->ac97) 333 if (rtd->codec->ac97)
332 rtd->socdev->card->codec->ac97->private_data = psc_dma; 334 rtd->codec->ac97->private_data = psc_dma;
333 335
334 return 0; 336 return 0;
335 337
@@ -349,7 +351,7 @@ static void psc_dma_free(struct snd_pcm *pcm)
349 struct snd_pcm_substream *substream; 351 struct snd_pcm_substream *substream;
350 int stream; 352 int stream;
351 353
352 dev_dbg(rtd->socdev->dev, "psc_dma_free(pcm=%p)\n", pcm); 354 dev_dbg(rtd->platform->dev, "psc_dma_free(pcm=%p)\n", pcm);
353 355
354 for (stream = 0; stream < 2; stream++) { 356 for (stream = 0; stream < 2; stream++) {
355 substream = pcm->streams[stream].substream; 357 substream = pcm->streams[stream].substream;
@@ -361,15 +363,14 @@ static void psc_dma_free(struct snd_pcm *pcm)
361 } 363 }
362} 364}
363 365
364struct snd_soc_platform mpc5200_audio_dma_platform = { 366static struct snd_soc_platform_driver mpc5200_audio_dma_platform = {
365 .name = "mpc5200-psc-audio", 367 .ops = &psc_dma_ops,
366 .pcm_ops = &psc_dma_ops,
367 .pcm_new = &psc_dma_new, 368 .pcm_new = &psc_dma_new,
368 .pcm_free = &psc_dma_free, 369 .pcm_free = &psc_dma_free,
369}; 370};
370EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform);
371 371
372int mpc5200_audio_dma_create(struct platform_device *op) 372static int mpc5200_hpcd_probe(struct of_device *op,
373 const struct of_device_id *match)
373{ 374{
374 phys_addr_t fifo; 375 phys_addr_t fifo;
375 struct psc_dma *psc_dma; 376 struct psc_dma *psc_dma;
@@ -475,7 +476,7 @@ int mpc5200_audio_dma_create(struct platform_device *op)
475 dev_set_drvdata(&op->dev, psc_dma); 476 dev_set_drvdata(&op->dev, psc_dma);
476 477
477 /* Tell the ASoC OF helpers about it */ 478 /* Tell the ASoC OF helpers about it */
478 return snd_soc_register_platform(&mpc5200_audio_dma_platform); 479 return snd_soc_register_platform(&op->dev, &mpc5200_audio_dma_platform);
479out_irq: 480out_irq:
480 free_irq(psc_dma->irq, psc_dma); 481 free_irq(psc_dma->irq, psc_dma);
481 free_irq(psc_dma->capture.irq, &psc_dma->capture); 482 free_irq(psc_dma->capture.irq, &psc_dma->capture);
@@ -486,15 +487,14 @@ out_unmap:
486 iounmap(regs); 487 iounmap(regs);
487 return ret; 488 return ret;
488} 489}
489EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
490 490
491int mpc5200_audio_dma_destroy(struct platform_device *op) 491static int mpc5200_hpcd_remove(struct of_device *op)
492{ 492{
493 struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); 493 struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
494 494
495 dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n"); 495 dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n");
496 496
497 snd_soc_unregister_platform(&mpc5200_audio_dma_platform); 497 snd_soc_unregister_platform(&op->dev);
498 498
499 bcom_gen_bd_rx_release(psc_dma->capture.bcom_task); 499 bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);
500 bcom_gen_bd_tx_release(psc_dma->playback.bcom_task); 500 bcom_gen_bd_tx_release(psc_dma->playback.bcom_task);
@@ -510,7 +510,35 @@ int mpc5200_audio_dma_destroy(struct platform_device *op)
510 510
511 return 0; 511 return 0;
512} 512}
513EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); 513
514static struct of_device_id mpc5200_hpcd_match[] = {
515 {
516 .compatible = "fsl,mpc5200-pcm",
517 },
518 {}
519};
520MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match);
521
522static struct of_platform_driver mpc5200_hpcd_of_driver = {
523 .owner = THIS_MODULE,
524 .name = "mpc5200-pcm-audio",
525 .match_table = mpc5200_hpcd_match,
526 .probe = mpc5200_hpcd_probe,
527 .remove = mpc5200_hpcd_remove,
528};
529
530static int __init mpc5200_hpcd_init(void)
531{
532 return of_register_platform_driver(&mpc5200_hpcd_of_driver);
533}
534
535static void __exit mpc5200_hpcd_exit(void)
536{
537 of_unregister_platform_driver(&mpc5200_hpcd_of_driver);
538}
539
540module_init(mpc5200_hpcd_init);
541module_exit(mpc5200_hpcd_exit);
514 542
515MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); 543MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
516MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); 544MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
index ca99586f2ad9..a3c0cd5382fb 100644
--- a/sound/soc/fsl/mpc5200_dma.h
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -81,9 +81,4 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)
81 return &psc_dma->playback; 81 return &psc_dma->playback;
82} 82}
83 83
84int mpc5200_audio_dma_create(struct platform_device *op);
85int mpc5200_audio_dma_destroy(struct platform_device *op);
86
87extern struct snd_soc_platform mpc5200_audio_dma_platform;
88
89#endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ 84#endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index a9560235daee..40acc8e2b1ca 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -143,7 +143,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
143 struct snd_pcm_hw_params *params, 143 struct snd_pcm_hw_params *params,
144 struct snd_soc_dai *cpu_dai) 144 struct snd_soc_dai *cpu_dai)
145{ 145{
146 struct psc_dma *psc_dma = cpu_dai->private_data; 146 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
147 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); 147 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
148 148
149 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" 149 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
@@ -166,7 +166,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
166 struct snd_pcm_hw_params *params, 166 struct snd_pcm_hw_params *params,
167 struct snd_soc_dai *cpu_dai) 167 struct snd_soc_dai *cpu_dai)
168{ 168{
169 struct psc_dma *psc_dma = cpu_dai->private_data; 169 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
170 170
171 dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream); 171 dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream);
172 172
@@ -181,8 +181,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
181static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, 181static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
182 struct snd_soc_dai *dai) 182 struct snd_soc_dai *dai)
183{ 183{
184 struct snd_soc_pcm_runtime *rtd = substream->private_data; 184 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(dai);
185 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
186 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); 185 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
187 186
188 switch (cmd) { 187 switch (cmd) {
@@ -207,10 +206,9 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
207 return 0; 206 return 0;
208} 207}
209 208
210static int psc_ac97_probe(struct platform_device *pdev, 209static int psc_ac97_probe(struct snd_soc_dai *cpu_dai)
211 struct snd_soc_dai *cpu_dai)
212{ 210{
213 struct psc_dma *psc_dma = cpu_dai->private_data; 211 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
214 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 212 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
215 213
216 /* Go */ 214 /* Go */
@@ -237,9 +235,8 @@ static struct snd_soc_dai_ops psc_ac97_digital_ops = {
237 .hw_params = psc_ac97_hw_digital_params, 235 .hw_params = psc_ac97_hw_digital_params,
238}; 236};
239 237
240struct snd_soc_dai psc_ac97_dai[] = { 238static struct snd_soc_dai_driver psc_ac97_dai[] = {
241{ 239{
242 .name = "AC97",
243 .ac97_control = 1, 240 .ac97_control = 1,
244 .probe = psc_ac97_probe, 241 .probe = psc_ac97_probe,
245 .playback = { 242 .playback = {
@@ -257,7 +254,6 @@ struct snd_soc_dai psc_ac97_dai[] = {
257 .ops = &psc_ac97_analog_ops, 254 .ops = &psc_ac97_analog_ops,
258}, 255},
259{ 256{
260 .name = "SPDIF",
261 .ac97_control = 1, 257 .ac97_control = 1,
262 .playback = { 258 .playback = {
263 .channels_min = 1, 259 .channels_min = 1,
@@ -268,7 +264,6 @@ struct snd_soc_dai psc_ac97_dai[] = {
268 }, 264 },
269 .ops = &psc_ac97_digital_ops, 265 .ops = &psc_ac97_digital_ops,
270} }; 266} };
271EXPORT_SYMBOL_GPL(psc_ac97_dai);
272 267
273 268
274 269
@@ -280,18 +275,11 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai);
280static int __devinit psc_ac97_of_probe(struct platform_device *op, 275static int __devinit psc_ac97_of_probe(struct platform_device *op,
281 const struct of_device_id *match) 276 const struct of_device_id *match)
282{ 277{
283 int rc, i; 278 int rc;
284 struct snd_ac97 ac97; 279 struct snd_ac97 ac97;
285 struct mpc52xx_psc __iomem *regs; 280 struct mpc52xx_psc __iomem *regs;
286 281
287 rc = mpc5200_audio_dma_create(op); 282 rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
288 if (rc != 0)
289 return rc;
290
291 for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
292 psc_ac97_dai[i].dev = &op->dev;
293
294 rc = snd_soc_register_dais(psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
295 if (rc != 0) { 283 if (rc != 0) {
296 dev_err(&op->dev, "Failed to register DAI\n"); 284 dev_err(&op->dev, "Failed to register DAI\n");
297 return rc; 285 return rc;
@@ -301,9 +289,6 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op,
301 regs = psc_dma->psc_regs; 289 regs = psc_dma->psc_regs;
302 ac97.private_data = psc_dma; 290 ac97.private_data = psc_dma;
303 291
304 for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
305 psc_ac97_dai[i].private_data = psc_dma;
306
307 psc_dma->imr = 0; 292 psc_dma->imr = 0;
308 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); 293 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
309 294
@@ -319,7 +304,8 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op,
319 304
320static int __devexit psc_ac97_of_remove(struct platform_device *op) 305static int __devexit psc_ac97_of_remove(struct platform_device *op)
321{ 306{
322 return mpc5200_audio_dma_destroy(op); 307 snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai));
308 return 0;
323} 309}
324 310
325/* Match table for of_platform binding */ 311/* Match table for of_platform binding */
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.h b/sound/soc/fsl/mpc5200_psc_ac97.h
index 4bc18c35c369..e881e784b270 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.h
+++ b/sound/soc/fsl/mpc5200_psc_ac97.h
@@ -7,8 +7,6 @@
7#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ 7#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
8#define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ 8#define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
9 9
10extern struct snd_soc_dai psc_ac97_dai[];
11
12#define MPC5200_AC97_NORMAL 0 10#define MPC5200_AC97_NORMAL 0
13#define MPC5200_AC97_SPDIF 1 11#define MPC5200_AC97_SPDIF 1
14 12
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 534f04cb15d7..74ffed41340f 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -40,7 +40,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
40 struct snd_soc_dai *dai) 40 struct snd_soc_dai *dai)
41{ 41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data; 42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 43 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
44 u32 mode; 44 u32 mode;
45 45
46 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" 46 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
@@ -88,7 +88,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
88static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, 88static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
89 int clk_id, unsigned int freq, int dir) 89 int clk_id, unsigned int freq, int dir)
90{ 90{
91 struct psc_dma *psc_dma = cpu_dai->private_data; 91 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
92 dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n", 92 dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",
93 cpu_dai, dir); 93 cpu_dai, dir);
94 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; 94 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
@@ -107,7 +107,7 @@ static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
107 */ 107 */
108static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) 108static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
109{ 109{
110 struct psc_dma *psc_dma = cpu_dai->private_data; 110 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
111 dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n", 111 dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",
112 cpu_dai, format); 112 cpu_dai, format);
113 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; 113 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
@@ -129,8 +129,7 @@ static struct snd_soc_dai_ops psc_i2s_dai_ops = {
129 .set_fmt = psc_i2s_set_fmt, 129 .set_fmt = psc_i2s_set_fmt,
130}; 130};
131 131
132struct snd_soc_dai psc_i2s_dai[] = {{ 132static struct snd_soc_dai_driver psc_i2s_dai[] = {{
133 .name = "I2S",
134 .playback = { 133 .playback = {
135 .channels_min = 2, 134 .channels_min = 2,
136 .channels_max = 2, 135 .channels_max = 2,
@@ -145,7 +144,6 @@ struct snd_soc_dai psc_i2s_dai[] = {{
145 }, 144 },
146 .ops = &psc_i2s_dai_ops, 145 .ops = &psc_i2s_dai_ops,
147} }; 146} };
148EXPORT_SYMBOL_GPL(psc_i2s_dai);
149 147
150/* --------------------------------------------------------------------- 148/* ---------------------------------------------------------------------
151 * OF platform bus binding code: 149 * OF platform bus binding code:
@@ -159,11 +157,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op,
159 struct psc_dma *psc_dma; 157 struct psc_dma *psc_dma;
160 struct mpc52xx_psc __iomem *regs; 158 struct mpc52xx_psc __iomem *regs;
161 159
162 rc = mpc5200_audio_dma_create(op); 160 rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
163 if (rc != 0)
164 return rc;
165
166 rc = snd_soc_register_dais(psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
167 if (rc != 0) { 161 if (rc != 0) {
168 pr_err("Failed to register DAI\n"); 162 pr_err("Failed to register DAI\n");
169 return 0; 163 return 0;
@@ -207,7 +201,8 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op,
207 201
208static int __devexit psc_i2s_of_remove(struct platform_device *op) 202static int __devexit psc_i2s_of_remove(struct platform_device *op)
209{ 203{
210 return mpc5200_audio_dma_destroy(op); 204 snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai));
205 return 0;
211} 206}
212 207
213/* Match table for of_platform binding */ 208/* Match table for of_platform binding */
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 3b13b8d65262..0d7dcf1e4863 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -1,85 +1,97 @@
1/** 1/**
2 * Freescale MPC8610HPCD ALSA SoC Fabric driver 2 * Freescale MPC8610HPCD ALSA SoC Machine driver
3 * 3 *
4 * Author: Timur Tabi <timur@freescale.com> 4 * Author: Timur Tabi <timur@freescale.com>
5 * 5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed 6 * Copyright 2007-2010 Freescale Semiconductor, Inc.
7 * under the terms of the GNU General Public License version 2. This 7 *
8 * program is licensed "as is" without any warranty of any kind, whether 8 * This file is licensed under the terms of the GNU General Public License
9 * express or implied. 9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
10 */ 11 */
11 12
12#include <linux/slab.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/of_device.h> 15#include <linux/of_device.h>
16#include <linux/of_platform.h> 16#include <linux/slab.h>
17#include <sound/soc.h> 17#include <sound/soc.h>
18#include <asm/immap_86xx.h> 18#include <asm/fsl_guts.h>
19 19
20#include "../codecs/cs4270.h"
21#include "fsl_dma.h" 20#include "fsl_dma.h"
22#include "fsl_ssi.h" 21#include "fsl_ssi.h"
23 22
23/* There's only one global utilities register */
24static phys_addr_t guts_phys;
25
26#define DAI_NAME_SIZE 32
27
24/** 28/**
25 * mpc8610_hpcd_data: fabric-specific ASoC device data 29 * mpc8610_hpcd_data: machine-specific ASoC device data
26 * 30 *
27 * This structure contains data for a single sound platform device on an 31 * This structure contains data for a single sound platform device on an
28 * MPC8610 HPCD. Some of the data is taken from the device tree. 32 * MPC8610 HPCD. Some of the data is taken from the device tree.
29 */ 33 */
30struct mpc8610_hpcd_data { 34struct mpc8610_hpcd_data {
31 struct snd_soc_device sound_devdata; 35 struct snd_soc_dai_link dai[2];
32 struct snd_soc_dai_link dai; 36 struct snd_soc_card card;
33 struct snd_soc_card machine;
34 unsigned int dai_format; 37 unsigned int dai_format;
35 unsigned int codec_clk_direction; 38 unsigned int codec_clk_direction;
36 unsigned int cpu_clk_direction; 39 unsigned int cpu_clk_direction;
37 unsigned int clk_frequency; 40 unsigned int clk_frequency;
38 struct ccsr_guts __iomem *guts; 41 unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */
39 struct ccsr_ssi __iomem *ssi; 42 unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */
40 unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */
41 unsigned int ssi_irq;
42 unsigned int dma_id; /* 0 = DMA1, 1 = DMA2, etc */
43 unsigned int dma_irq[2];
44 struct ccsr_dma_channel __iomem *dma[2];
45 unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ 43 unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
44 char codec_dai_name[DAI_NAME_SIZE];
45 char codec_name[DAI_NAME_SIZE];
46 char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
46}; 47};
47 48
48/** 49/**
49 * mpc8610_hpcd_machine_probe: initialize the board 50 * mpc8610_hpcd_machine_probe: initialize the board
50 * 51 *
51 * This function is called when platform_device_add() is called. It is used 52 * This function is used to initialize the board-specific hardware.
52 * to initialize the board-specific hardware.
53 * 53 *
54 * Here we program the DMACR and PMUXCR registers. 54 * Here we program the DMACR and PMUXCR registers.
55 */ 55 */
56static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) 56static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
57{ 57{
58 struct snd_soc_card *card = platform_get_drvdata(sound_device);
58 struct mpc8610_hpcd_data *machine_data = 59 struct mpc8610_hpcd_data *machine_data =
59 sound_device->dev.platform_data; 60 container_of(card, struct mpc8610_hpcd_data, card);
61 struct ccsr_guts_86xx __iomem *guts;
60 62
61 /* Program the signal routing between the SSI and the DMA */ 63 guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
62 guts_set_dmacr(machine_data->guts, machine_data->dma_id, 64 if (!guts) {
63 machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI); 65 dev_err(card->dev, "could not map global utilities\n");
64 guts_set_dmacr(machine_data->guts, machine_data->dma_id, 66 return -ENOMEM;
65 machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI); 67 }
66 68
67 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, 69 /* Program the signal routing between the SSI and the DMA */
68 machine_data->dma_channel_id[0], 0); 70 guts_set_dmacr(guts, machine_data->dma_id[0],
69 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, 71 machine_data->dma_channel_id[0],
70 machine_data->dma_channel_id[1], 0); 72 CCSR_GUTS_DMACR_DEV_SSI);
73 guts_set_dmacr(guts, machine_data->dma_id[1],
74 machine_data->dma_channel_id[1],
75 CCSR_GUTS_DMACR_DEV_SSI);
76
77 guts_set_pmuxcr_dma(guts, machine_data->dma_id[0],
78 machine_data->dma_channel_id[0], 0);
79 guts_set_pmuxcr_dma(guts, machine_data->dma_id[1],
80 machine_data->dma_channel_id[1], 0);
71 81
72 switch (machine_data->ssi_id) { 82 switch (machine_data->ssi_id) {
73 case 0: 83 case 0:
74 clrsetbits_be32(&machine_data->guts->pmuxcr, 84 clrsetbits_be32(&guts->pmuxcr,
75 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI); 85 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI);
76 break; 86 break;
77 case 1: 87 case 1:
78 clrsetbits_be32(&machine_data->guts->pmuxcr, 88 clrsetbits_be32(&guts->pmuxcr,
79 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI); 89 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI);
80 break; 90 break;
81 } 91 }
82 92
93 iounmap(guts);
94
83 return 0; 95 return 0;
84} 96}
85 97
@@ -93,38 +105,15 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
93static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) 105static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
94{ 106{
95 struct snd_soc_pcm_runtime *rtd = substream->private_data; 107 struct snd_soc_pcm_runtime *rtd = substream->private_data;
96 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
97 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
98 struct mpc8610_hpcd_data *machine_data = 108 struct mpc8610_hpcd_data *machine_data =
99 rtd->socdev->dev->platform_data; 109 container_of(rtd->card, struct mpc8610_hpcd_data, card);
110 struct device *dev = rtd->card->dev;
100 int ret = 0; 111 int ret = 0;
101 112
102 /* Tell the CPU driver what the serial protocol is. */
103 ret = snd_soc_dai_set_fmt(cpu_dai, machine_data->dai_format);
104 if (ret < 0) {
105 dev_err(substream->pcm->card->dev,
106 "could not set CPU driver audio format\n");
107 return ret;
108 }
109
110 /* Tell the codec driver what the serial protocol is. */ 113 /* Tell the codec driver what the serial protocol is. */
111 ret = snd_soc_dai_set_fmt(codec_dai, machine_data->dai_format); 114 ret = snd_soc_dai_set_fmt(rtd->codec_dai, machine_data->dai_format);
112 if (ret < 0) { 115 if (ret < 0) {
113 dev_err(substream->pcm->card->dev, 116 dev_err(dev, "could not set codec driver audio format\n");
114 "could not set codec driver audio format\n");
115 return ret;
116 }
117
118 /*
119 * Tell the CPU driver what the clock frequency is, and whether it's a
120 * slave or master.
121 */
122 ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
123 machine_data->clk_frequency,
124 machine_data->cpu_clk_direction);
125 if (ret < 0) {
126 dev_err(substream->pcm->card->dev,
127 "could not set CPU driver clock parameters\n");
128 return ret; 117 return ret;
129 } 118 }
130 119
@@ -132,12 +121,11 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
132 * Tell the codec driver what the MCLK frequency is, and whether it's 121 * Tell the codec driver what the MCLK frequency is, and whether it's
133 * a slave or master. 122 * a slave or master.
134 */ 123 */
135 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 124 ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0,
136 machine_data->clk_frequency, 125 machine_data->clk_frequency,
137 machine_data->codec_clk_direction); 126 machine_data->codec_clk_direction);
138 if (ret < 0) { 127 if (ret < 0) {
139 dev_err(substream->pcm->card->dev, 128 dev_err(dev, "could not set codec driver clock params\n");
140 "could not set codec driver clock params\n");
141 return ret; 129 return ret;
142 } 130 }
143 131
@@ -150,116 +138,255 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
150 * This function is called to remove the sound device for one SSI. We 138 * This function is called to remove the sound device for one SSI. We
151 * de-program the DMACR and PMUXCR register. 139 * de-program the DMACR and PMUXCR register.
152 */ 140 */
153int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) 141static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
154{ 142{
143 struct snd_soc_card *card = platform_get_drvdata(sound_device);
155 struct mpc8610_hpcd_data *machine_data = 144 struct mpc8610_hpcd_data *machine_data =
156 sound_device->dev.platform_data; 145 container_of(card, struct mpc8610_hpcd_data, card);
146 struct ccsr_guts_86xx __iomem *guts;
147
148 guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
149 if (!guts) {
150 dev_err(card->dev, "could not map global utilities\n");
151 return -ENOMEM;
152 }
157 153
158 /* Restore the signal routing */ 154 /* Restore the signal routing */
159 155
160 guts_set_dmacr(machine_data->guts, machine_data->dma_id, 156 guts_set_dmacr(guts, machine_data->dma_id[0],
161 machine_data->dma_channel_id[0], 0); 157 machine_data->dma_channel_id[0], 0);
162 guts_set_dmacr(machine_data->guts, machine_data->dma_id, 158 guts_set_dmacr(guts, machine_data->dma_id[1],
163 machine_data->dma_channel_id[1], 0); 159 machine_data->dma_channel_id[1], 0);
164 160
165 switch (machine_data->ssi_id) { 161 switch (machine_data->ssi_id) {
166 case 0: 162 case 0:
167 clrsetbits_be32(&machine_data->guts->pmuxcr, 163 clrsetbits_be32(&guts->pmuxcr,
168 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA); 164 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA);
169 break; 165 break;
170 case 1: 166 case 1:
171 clrsetbits_be32(&machine_data->guts->pmuxcr, 167 clrsetbits_be32(&guts->pmuxcr,
172 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA); 168 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA);
173 break; 169 break;
174 } 170 }
175 171
172 iounmap(guts);
173
176 return 0; 174 return 0;
177} 175}
178 176
179/** 177/**
180 * mpc8610_hpcd_ops: ASoC fabric driver operations 178 * mpc8610_hpcd_ops: ASoC machine driver operations
181 */ 179 */
182static struct snd_soc_ops mpc8610_hpcd_ops = { 180static struct snd_soc_ops mpc8610_hpcd_ops = {
183 .startup = mpc8610_hpcd_startup, 181 .startup = mpc8610_hpcd_startup,
184}; 182};
185 183
186/** 184/**
187 * mpc8610_hpcd_probe: OF probe function for the fabric driver 185 * get_node_by_phandle_name - get a node by its phandle name
188 * 186 *
189 * This function gets called when an SSI node is found in the device tree. 187 * This function takes a node, the name of a property in that node, and a
188 * compatible string. Assuming the property is a phandle to another node,
189 * it returns that node, (optionally) if that node is compatible.
190 * 190 *
191 * Although this is a fabric driver, the SSI node is the "master" node with 191 * If the property is not a phandle, or the node it points to is not compatible
192 * respect to audio hardware connections. Therefore, we create a new ASoC 192 * with the specific string, then NULL is returned.
193 * device for each new SSI node that has a codec attached. 193 */
194static struct device_node *get_node_by_phandle_name(struct device_node *np,
195 const char *name,
196 const char *compatible)
197{
198 const phandle *ph;
199 int len;
200
201 ph = of_get_property(np, name, &len);
202 if (!ph || (len != sizeof(phandle)))
203 return NULL;
204
205 np = of_find_node_by_phandle(*ph);
206 if (!np)
207 return NULL;
208
209 if (compatible && !of_device_is_compatible(np, compatible)) {
210 of_node_put(np);
211 return NULL;
212 }
213
214 return np;
215}
216
217/**
218 * get_parent_cell_index -- return the cell-index of the parent of a node
219 *
220 * Return the value of the cell-index property of the parent of the given
221 * node. This is used for DMA channel nodes that need to know the DMA ID
222 * of the controller they are on.
223 */
224static int get_parent_cell_index(struct device_node *np)
225{
226 struct device_node *parent = of_get_parent(np);
227 const u32 *iprop;
228
229 if (!parent)
230 return -1;
231
232 iprop = of_get_property(parent, "cell-index", NULL);
233 of_node_put(parent);
234
235 if (!iprop)
236 return -1;
237
238 return *iprop;
239}
240
241/**
242 * codec_node_dev_name - determine the dev_name for a codec node
194 * 243 *
195 * FIXME: Currently, we only support one DMA controller, so if there are 244 * This function determines the dev_name for an I2C node. This is the name
196 * multiple SSI nodes with codecs, only the first will be supported. 245 * that would be returned by dev_name() if this device_node were part of a
246 * 'struct device' It's ugly and hackish, but it works.
197 * 247 *
198 * FIXME: Even if we did support multiple DMA controllers, we have no 248 * The dev_name for such devices include the bus number and I2C address. For
199 * mechanism for assigning DMA controllers and channels to the individual 249 * example, "cs4270-codec.0-004f".
200 * SSI devices. We also probably aren't compatible with the generic Elo DMA
201 * device driver.
202 */ 250 */
203static int mpc8610_hpcd_probe(struct platform_device *ofdev, 251static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
204 const struct of_device_id *match)
205{ 252{
206 struct device_node *np = ofdev->dev.of_node;
207 struct device_node *codec_np = NULL;
208 struct device_node *guts_np = NULL;
209 struct device_node *dma_np = NULL;
210 struct device_node *dma_channel_np = NULL;
211 const phandle *codec_ph;
212 const char *sprop;
213 const u32 *iprop; 253 const u32 *iprop;
254 int bus, addr;
255 char temp[DAI_NAME_SIZE];
256
257 of_modalias_node(np, temp, DAI_NAME_SIZE);
258
259 iprop = of_get_property(np, "reg", NULL);
260 if (!iprop)
261 return -EINVAL;
262
263 addr = *iprop;
264
265 bus = get_parent_cell_index(np);
266 if (bus < 0)
267 return bus;
268
269 snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
270
271 return 0;
272}
273
274static int get_dma_channel(struct device_node *ssi_np,
275 const char *compatible,
276 struct snd_soc_dai_link *dai,
277 unsigned int *dma_channel_id,
278 unsigned int *dma_id)
279{
214 struct resource res; 280 struct resource res;
281 struct device_node *dma_channel_np;
282 const u32 *iprop;
283 int ret;
284
285 dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
286 "fsl,ssi-dma-channel");
287 if (!dma_channel_np)
288 return -EINVAL;
289
290 /* Determine the dev_name for the device_node. This code mimics the
291 * behavior of of_device_make_bus_id(). We need this because ASoC uses
292 * the dev_name() of the device to match the platform (DMA) device with
293 * the CPU (SSI) device. It's all ugly and hackish, but it works (for
294 * now).
295 *
296 * dai->platform name should already point to an allocated buffer.
297 */
298 ret = of_address_to_resource(dma_channel_np, 0, &res);
299 if (ret)
300 return ret;
301 snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
302 (unsigned long long) res.start, dma_channel_np->name);
303
304 iprop = of_get_property(dma_channel_np, "cell-index", NULL);
305 if (!iprop) {
306 of_node_put(dma_channel_np);
307 return -EINVAL;
308 }
309
310 *dma_channel_id = *iprop;
311 *dma_id = get_parent_cell_index(dma_channel_np);
312 of_node_put(dma_channel_np);
313
314 return 0;
315}
316
317/**
318 * mpc8610_hpcd_probe: platform probe function for the machine driver
319 *
320 * Although this is a machine driver, the SSI node is the "master" node with
321 * respect to audio hardware connections. Therefore, we create a new ASoC
322 * device for each new SSI node that has a codec attached.
323 */
324static int mpc8610_hpcd_probe(struct platform_device *pdev)
325{
326 struct device *dev = pdev->dev.parent;
327 /* ssi_pdev is the platform device for the SSI node that probed us */
328 struct platform_device *ssi_pdev =
329 container_of(dev, struct platform_device, dev);
330 struct device_node *np = ssi_pdev->dev.of_node;
331 struct device_node *codec_np = NULL;
215 struct platform_device *sound_device = NULL; 332 struct platform_device *sound_device = NULL;
216 struct mpc8610_hpcd_data *machine_data; 333 struct mpc8610_hpcd_data *machine_data;
217 struct fsl_ssi_info ssi_info;
218 struct fsl_dma_info dma_info;
219 int ret = -ENODEV; 334 int ret = -ENODEV;
220 unsigned int playback_dma_channel; 335 const char *sprop;
221 unsigned int capture_dma_channel; 336 const u32 *iprop;
337
338 /* We are only interested in SSIs with a codec phandle in them,
339 * so let's make sure this SSI has one. The MPC8610 HPCD only
340 * knows about the CS4270 codec, so reject anything else.
341 */
342 codec_np = get_node_by_phandle_name(np, "codec-handle",
343 "cirrus,cs4270");
344 if (!codec_np) {
345 dev_err(dev, "invalid codec node\n");
346 return -EINVAL;
347 }
222 348
223 machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); 349 machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL);
224 if (!machine_data) 350 if (!machine_data)
225 return -ENOMEM; 351 return -ENOMEM;
226 352
227 memset(&ssi_info, 0, sizeof(ssi_info)); 353 machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
228 memset(&dma_info, 0, sizeof(dma_info)); 354 machine_data->dai[0].ops = &mpc8610_hpcd_ops;
229 355
230 ssi_info.dev = &ofdev->dev; 356 /* Determine the codec name, it will be used as the codec DAI name */
231 357 ret = codec_node_dev_name(codec_np, machine_data->codec_name,
232 /* 358 DAI_NAME_SIZE);
233 * We are only interested in SSIs with a codec phandle in them, so let's 359 if (ret) {
234 * make sure this SSI has one. 360 dev_err(&pdev->dev, "invalid codec node %s\n",
235 */ 361 codec_np->full_name);
236 codec_ph = of_get_property(np, "codec-handle", NULL); 362 ret = -EINVAL;
237 if (!codec_ph)
238 goto error; 363 goto error;
364 }
365 machine_data->dai[0].codec_name = machine_data->codec_name;
239 366
240 codec_np = of_find_node_by_phandle(*codec_ph); 367 /* The DAI name from the codec (snd_soc_dai_driver.name) */
241 if (!codec_np) 368 machine_data->dai[0].codec_dai_name = "cs4270-hifi";
242 goto error;
243 369
244 /* The MPC8610 HPCD only knows about the CS4270 codec, so reject 370 /* We register two DAIs per SSI, one for playback and the other for
245 anything else. */ 371 * capture. Currently, we only support codecs that have one DAI for
246 if (!of_device_is_compatible(codec_np, "cirrus,cs4270")) 372 * both playback and capture.
247 goto error; 373 */
374 memcpy(&machine_data->dai[1], &machine_data->dai[0],
375 sizeof(struct snd_soc_dai_link));
248 376
249 /* Get the device ID */ 377 /* Get the device ID */
250 iprop = of_get_property(np, "cell-index", NULL); 378 iprop = of_get_property(np, "cell-index", NULL);
251 if (!iprop) { 379 if (!iprop) {
252 dev_err(&ofdev->dev, "cell-index property not found\n"); 380 dev_err(&pdev->dev, "cell-index property not found\n");
253 ret = -EINVAL; 381 ret = -EINVAL;
254 goto error; 382 goto error;
255 } 383 }
256 machine_data->ssi_id = *iprop; 384 machine_data->ssi_id = *iprop;
257 ssi_info.id = *iprop;
258 385
259 /* Get the serial format and clock direction. */ 386 /* Get the serial format and clock direction. */
260 sprop = of_get_property(np, "fsl,mode", NULL); 387 sprop = of_get_property(np, "fsl,mode", NULL);
261 if (!sprop) { 388 if (!sprop) {
262 dev_err(&ofdev->dev, "fsl,mode property not found\n"); 389 dev_err(&pdev->dev, "fsl,mode property not found\n");
263 ret = -EINVAL; 390 ret = -EINVAL;
264 goto error; 391 goto error;
265 } 392 }
@@ -269,15 +396,14 @@ static int mpc8610_hpcd_probe(struct platform_device *ofdev,
269 machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; 396 machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
270 machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; 397 machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
271 398
272 /* 399 /* In i2s-slave mode, the codec has its own clock source, so we
273 * In i2s-slave mode, the codec has its own clock source, so we
274 * need to get the frequency from the device tree and pass it to 400 * need to get the frequency from the device tree and pass it to
275 * the codec driver. 401 * the codec driver.
276 */ 402 */
277 iprop = of_get_property(codec_np, "clock-frequency", NULL); 403 iprop = of_get_property(codec_np, "clock-frequency", NULL);
278 if (!iprop || !*iprop) { 404 if (!iprop || !*iprop) {
279 dev_err(&ofdev->dev, "codec bus-frequency property " 405 dev_err(&pdev->dev, "codec bus-frequency "
280 "is missing or invalid\n"); 406 "property is missing or invalid\n");
281 ret = -EINVAL; 407 ret = -EINVAL;
282 goto error; 408 goto error;
283 } 409 }
@@ -311,317 +437,153 @@ static int mpc8610_hpcd_probe(struct platform_device *ofdev,
311 machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; 437 machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
312 machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; 438 machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
313 } else { 439 } else {
314 dev_err(&ofdev->dev, 440 dev_err(&pdev->dev,
315 "unrecognized fsl,mode property \"%s\"\n", sprop); 441 "unrecognized fsl,mode property '%s'\n", sprop);
316 ret = -EINVAL; 442 ret = -EINVAL;
317 goto error; 443 goto error;
318 } 444 }
319 445
320 if (!machine_data->clk_frequency) { 446 if (!machine_data->clk_frequency) {
321 dev_err(&ofdev->dev, "unknown clock frequency\n"); 447 dev_err(&pdev->dev, "unknown clock frequency\n");
322 ret = -EINVAL; 448 ret = -EINVAL;
323 goto error; 449 goto error;
324 } 450 }
325 451
326 /* Read the SSI information from the device tree */ 452 /* Find the playback DMA channel to use. */
327 ret = of_address_to_resource(np, 0, &res); 453 machine_data->dai[0].platform_name = machine_data->platform_name[0];
454 ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0],
455 &machine_data->dma_channel_id[0],
456 &machine_data->dma_id[0]);
328 if (ret) { 457 if (ret) {
329 dev_err(&ofdev->dev, "could not obtain SSI address\n"); 458 dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");
330 goto error;
331 }
332 if (!res.start) {
333 dev_err(&ofdev->dev, "invalid SSI address\n");
334 goto error;
335 }
336 ssi_info.ssi_phys = res.start;
337
338 machine_data->ssi = ioremap(ssi_info.ssi_phys, sizeof(struct ccsr_ssi));
339 if (!machine_data->ssi) {
340 dev_err(&ofdev->dev, "could not map SSI address %x\n",
341 ssi_info.ssi_phys);
342 ret = -EINVAL;
343 goto error;
344 }
345 ssi_info.ssi = machine_data->ssi;
346
347
348 /* Get the IRQ of the SSI */
349 machine_data->ssi_irq = irq_of_parse_and_map(np, 0);
350 if (!machine_data->ssi_irq) {
351 dev_err(&ofdev->dev, "could not get SSI IRQ\n");
352 ret = -EINVAL;
353 goto error;
354 }
355 ssi_info.irq = machine_data->ssi_irq;
356
357 /* Do we want to use asynchronous mode? */
358 ssi_info.asynchronous =
359 of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0;
360 if (ssi_info.asynchronous)
361 dev_info(&ofdev->dev, "using asynchronous mode\n");
362
363 /* Map the global utilities registers. */
364 guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
365 if (!guts_np) {
366 dev_err(&ofdev->dev, "could not obtain address of GUTS\n");
367 ret = -EINVAL;
368 goto error;
369 }
370 machine_data->guts = of_iomap(guts_np, 0);
371 of_node_put(guts_np);
372 if (!machine_data->guts) {
373 dev_err(&ofdev->dev, "could not map GUTS\n");
374 ret = -EINVAL;
375 goto error;
376 }
377
378 /* Find the DMA channels to use. Both SSIs need to use the same DMA
379 * controller, so let's use DMA#1.
380 */
381 for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") {
382 iprop = of_get_property(dma_np, "cell-index", NULL);
383 if (iprop && (*iprop == 0)) {
384 of_node_put(dma_np);
385 break;
386 }
387 }
388 if (!dma_np) {
389 dev_err(&ofdev->dev, "could not find DMA node\n");
390 ret = -EINVAL;
391 goto error;
392 }
393 machine_data->dma_id = *iprop;
394
395 /* SSI1 needs to use DMA Channels 0 and 1, and SSI2 needs to use DMA
396 * channels 2 and 3. This is just how the MPC8610 is wired
397 * internally.
398 */
399 playback_dma_channel = (machine_data->ssi_id == 0) ? 0 : 2;
400 capture_dma_channel = (machine_data->ssi_id == 0) ? 1 : 3;
401
402 /*
403 * Find the DMA channels to use.
404 */
405 while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) {
406 iprop = of_get_property(dma_channel_np, "cell-index", NULL);
407 if (iprop && (*iprop == playback_dma_channel)) {
408 /* dma_channel[0] and dma_irq[0] are for playback */
409 dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0);
410 dma_info.dma_irq[0] =
411 irq_of_parse_and_map(dma_channel_np, 0);
412 machine_data->dma_channel_id[0] = *iprop;
413 continue;
414 }
415 if (iprop && (*iprop == capture_dma_channel)) {
416 /* dma_channel[1] and dma_irq[1] are for capture */
417 dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0);
418 dma_info.dma_irq[1] =
419 irq_of_parse_and_map(dma_channel_np, 0);
420 machine_data->dma_channel_id[1] = *iprop;
421 continue;
422 }
423 }
424 if (!dma_info.dma_channel[0] || !dma_info.dma_channel[1] ||
425 !dma_info.dma_irq[0] || !dma_info.dma_irq[1]) {
426 dev_err(&ofdev->dev, "could not find DMA channels\n");
427 ret = -EINVAL;
428 goto error; 459 goto error;
429 } 460 }
430 461
431 dma_info.ssi_stx_phys = ssi_info.ssi_phys + 462 /* Find the capture DMA channel to use. */
432 offsetof(struct ccsr_ssi, stx0); 463 machine_data->dai[1].platform_name = machine_data->platform_name[1];
433 dma_info.ssi_srx_phys = ssi_info.ssi_phys + 464 ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1],
434 offsetof(struct ccsr_ssi, srx0); 465 &machine_data->dma_channel_id[1],
435 466 &machine_data->dma_id[1]);
436 /* We have the DMA information, so tell the DMA driver what it is */ 467 if (ret) {
437 if (!fsl_dma_configure(&dma_info)) { 468 dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");
438 dev_err(&ofdev->dev, "could not instantiate DMA device\n");
439 ret = -EBUSY;
440 goto error; 469 goto error;
441 } 470 }
442 471
443 /* 472 /* Initialize our DAI data structure. */
444 * Initialize our DAI data structure. We should probably get this 473 machine_data->dai[0].stream_name = "playback";
445 * information from the device tree. 474 machine_data->dai[1].stream_name = "capture";
446 */ 475 machine_data->dai[0].name = machine_data->dai[0].stream_name;
447 machine_data->dai.name = "CS4270"; 476 machine_data->dai[1].name = machine_data->dai[1].stream_name;
448 machine_data->dai.stream_name = "CS4270";
449
450 machine_data->dai.cpu_dai = fsl_ssi_create_dai(&ssi_info);
451 machine_data->dai.codec_dai = &cs4270_dai; /* The codec_dai we want */
452 machine_data->dai.ops = &mpc8610_hpcd_ops;
453 477
454 machine_data->machine.probe = mpc8610_hpcd_machine_probe; 478 machine_data->card.probe = mpc8610_hpcd_machine_probe;
455 machine_data->machine.remove = mpc8610_hpcd_machine_remove; 479 machine_data->card.remove = mpc8610_hpcd_machine_remove;
456 machine_data->machine.name = "MPC8610 HPCD"; 480 machine_data->card.name = pdev->name; /* The platform driver name */
457 machine_data->machine.num_links = 1; 481 machine_data->card.num_links = 2;
458 machine_data->machine.dai_link = &machine_data->dai; 482 machine_data->card.dai_link = machine_data->dai;
459 483
460 /* Allocate a new audio platform device structure */ 484 /* Allocate a new audio platform device structure */
461 sound_device = platform_device_alloc("soc-audio", -1); 485 sound_device = platform_device_alloc("soc-audio", -1);
462 if (!sound_device) { 486 if (!sound_device) {
463 dev_err(&ofdev->dev, "platform device allocation failed\n"); 487 dev_err(&pdev->dev, "platform device alloc failed\n");
464 ret = -ENOMEM; 488 ret = -ENOMEM;
465 goto error; 489 goto error;
466 } 490 }
467 491
468 machine_data->sound_devdata.card = &machine_data->machine; 492 /* Associate the card data with the sound device */
469 machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270; 493 platform_set_drvdata(sound_device, &machine_data->card);
470 machine_data->machine.platform = &fsl_soc_platform;
471
472 sound_device->dev.platform_data = machine_data;
473
474 494
475 /* Set the platform device and ASoC device to point to each other */ 495 /* Register with ASoC */
476 platform_set_drvdata(sound_device, &machine_data->sound_devdata);
477
478 machine_data->sound_devdata.dev = &sound_device->dev;
479
480
481 /* Tell ASoC to probe us. This will call mpc8610_hpcd_machine.probe(),
482 if it exists. */
483 ret = platform_device_add(sound_device); 496 ret = platform_device_add(sound_device);
484
485 if (ret) { 497 if (ret) {
486 dev_err(&ofdev->dev, "platform device add failed\n"); 498 dev_err(&pdev->dev, "platform device add failed\n");
487 goto error; 499 goto error;
488 } 500 }
489 501
490 dev_set_drvdata(&ofdev->dev, sound_device); 502 of_node_put(codec_np);
491 503
492 return 0; 504 return 0;
493 505
494error: 506error:
495 of_node_put(codec_np); 507 of_node_put(codec_np);
496 of_node_put(guts_np);
497 of_node_put(dma_np);
498 of_node_put(dma_channel_np);
499 508
500 if (sound_device) 509 if (sound_device)
501 platform_device_unregister(sound_device); 510 platform_device_unregister(sound_device);
502 511
503 if (machine_data->dai.cpu_dai)
504 fsl_ssi_destroy_dai(machine_data->dai.cpu_dai);
505
506 if (ssi_info.ssi)
507 iounmap(ssi_info.ssi);
508
509 if (ssi_info.irq)
510 irq_dispose_mapping(ssi_info.irq);
511
512 if (dma_info.dma_channel[0])
513 iounmap(dma_info.dma_channel[0]);
514
515 if (dma_info.dma_channel[1])
516 iounmap(dma_info.dma_channel[1]);
517
518 if (dma_info.dma_irq[0])
519 irq_dispose_mapping(dma_info.dma_irq[0]);
520
521 if (dma_info.dma_irq[1])
522 irq_dispose_mapping(dma_info.dma_irq[1]);
523
524 if (machine_data->guts)
525 iounmap(machine_data->guts);
526
527 kfree(machine_data); 512 kfree(machine_data);
528 513
529 return ret; 514 return ret;
530} 515}
531 516
532/** 517/**
533 * mpc8610_hpcd_remove: remove the OF device 518 * mpc8610_hpcd_remove: remove the platform device
534 * 519 *
535 * This function is called when the OF device is removed. 520 * This function is called when the platform device is removed.
536 */ 521 */
537static int mpc8610_hpcd_remove(struct platform_device *ofdev) 522static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
538{ 523{
539 struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); 524 struct platform_device *sound_device = dev_get_drvdata(&pdev->dev);
525 struct snd_soc_card *card = platform_get_drvdata(sound_device);
540 struct mpc8610_hpcd_data *machine_data = 526 struct mpc8610_hpcd_data *machine_data =
541 sound_device->dev.platform_data; 527 container_of(card, struct mpc8610_hpcd_data, card);
542 528
543 platform_device_unregister(sound_device); 529 platform_device_unregister(sound_device);
544 530
545 if (machine_data->dai.cpu_dai)
546 fsl_ssi_destroy_dai(machine_data->dai.cpu_dai);
547
548 if (machine_data->ssi)
549 iounmap(machine_data->ssi);
550
551 if (machine_data->dma[0])
552 iounmap(machine_data->dma[0]);
553
554 if (machine_data->dma[1])
555 iounmap(machine_data->dma[1]);
556
557 if (machine_data->dma_irq[0])
558 irq_dispose_mapping(machine_data->dma_irq[0]);
559
560 if (machine_data->dma_irq[1])
561 irq_dispose_mapping(machine_data->dma_irq[1]);
562
563 if (machine_data->guts)
564 iounmap(machine_data->guts);
565
566 kfree(machine_data); 531 kfree(machine_data);
567 sound_device->dev.platform_data = NULL; 532 sound_device->dev.platform_data = NULL;
568 533
569 dev_set_drvdata(&ofdev->dev, NULL); 534 dev_set_drvdata(&pdev->dev, NULL);
570 535
571 return 0; 536 return 0;
572} 537}
573 538
574static struct of_device_id mpc8610_hpcd_match[] = { 539static struct platform_driver mpc8610_hpcd_driver = {
575 { 540 .probe = mpc8610_hpcd_probe,
576 .compatible = "fsl,mpc8610-ssi", 541 .remove = __devexit_p(mpc8610_hpcd_remove),
577 },
578 {}
579};
580MODULE_DEVICE_TABLE(of, mpc8610_hpcd_match);
581
582static struct of_platform_driver mpc8610_hpcd_of_driver = {
583 .driver = { 542 .driver = {
584 .name = "mpc8610_hpcd", 543 /* The name must match the 'model' property in the device tree,
544 * in lowercase letters.
545 */
546 .name = "snd-soc-mpc8610hpcd",
585 .owner = THIS_MODULE, 547 .owner = THIS_MODULE,
586 .of_match_table = mpc8610_hpcd_match,
587 }, 548 },
588 .probe = mpc8610_hpcd_probe,
589 .remove = mpc8610_hpcd_remove,
590}; 549};
591 550
592/** 551/**
593 * mpc8610_hpcd_init: fabric driver initialization. 552 * mpc8610_hpcd_init: machine driver initialization.
594 * 553 *
595 * This function is called when this module is loaded. 554 * This function is called when this module is loaded.
596 */ 555 */
597static int __init mpc8610_hpcd_init(void) 556static int __init mpc8610_hpcd_init(void)
598{ 557{
599 int ret; 558 struct device_node *guts_np;
600 559 struct resource res;
601 printk(KERN_INFO "Freescale MPC8610 HPCD ALSA SoC fabric driver\n");
602 560
603 ret = of_register_platform_driver(&mpc8610_hpcd_of_driver); 561 pr_info("Freescale MPC8610 HPCD ALSA SoC machine driver\n");
604 562
605 if (ret) 563 /* Get the physical address of the global utilities registers */
606 printk(KERN_ERR 564 guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
607 "mpc8610-hpcd: failed to register platform driver\n"); 565 if (of_address_to_resource(guts_np, 0, &res)) {
566 pr_err("mpc8610-hpcd: missing/invalid global utilities node\n");
567 return -EINVAL;
568 }
569 guts_phys = res.start;
608 570
609 return ret; 571 return platform_driver_register(&mpc8610_hpcd_driver);
610} 572}
611 573
612/** 574/**
613 * mpc8610_hpcd_exit: fabric driver exit 575 * mpc8610_hpcd_exit: machine driver exit
614 * 576 *
615 * This function is called when this driver is unloaded. 577 * This function is called when this driver is unloaded.
616 */ 578 */
617static void __exit mpc8610_hpcd_exit(void) 579static void __exit mpc8610_hpcd_exit(void)
618{ 580{
619 of_unregister_platform_driver(&mpc8610_hpcd_of_driver); 581 platform_driver_unregister(&mpc8610_hpcd_driver);
620} 582}
621 583
622module_init(mpc8610_hpcd_init); 584module_init(mpc8610_hpcd_init);
623module_exit(mpc8610_hpcd_exit); 585module_exit(mpc8610_hpcd_exit);
624 586
625MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 587MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
626MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC fabric driver"); 588MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC machine driver");
627MODULE_LICENSE("GPL"); 589MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
new file mode 100644
index 000000000000..63b9eaa1ebc2
--- /dev/null
+++ b/sound/soc/fsl/p1022_ds.c
@@ -0,0 +1,591 @@
1/**
2 * Freescale P1022DS ALSA SoC Machine driver
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
6 * Copyright 2010 Freescale Semiconductor, Inc.
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
11 */
12
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/of_device.h>
16#include <linux/slab.h>
17#include <sound/soc.h>
18#include <asm/fsl_guts.h>
19
20#include "fsl_dma.h"
21#include "fsl_ssi.h"
22
23/* P1022-specific PMUXCR and DMUXCR bit definitions */
24
25#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK 0x0001c000
26#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI 0x00010000
27#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI 0x00018000
28
29#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK 0x00000c00
30#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI 0x00000000
31
32#define CCSR_GUTS_DMUXCR_PAD 1 /* DMA controller/channel set to pad */
33#define CCSR_GUTS_DMUXCR_SSI 2 /* DMA controller/channel set to SSI */
34
35/*
36 * Set the DMACR register in the GUTS
37 *
38 * The DMACR register determines the source of initiated transfers for each
39 * channel on each DMA controller. Rather than have a bunch of repetitive
40 * macros for the bit patterns, we just have a function that calculates
41 * them.
42 *
43 * guts: Pointer to GUTS structure
44 * co: The DMA controller (0 or 1)
45 * ch: The channel on the DMA controller (0, 1, 2, or 3)
46 * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
47 */
48static inline void guts_set_dmuxcr(struct ccsr_guts_85xx __iomem *guts,
49 unsigned int co, unsigned int ch, unsigned int device)
50{
51 unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
52
53 clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift);
54}
55
56/* There's only one global utilities register */
57static phys_addr_t guts_phys;
58
59#define DAI_NAME_SIZE 32
60
61/**
62 * machine_data: machine-specific ASoC device data
63 *
64 * This structure contains data for a single sound platform device on an
65 * P1022 DS. Some of the data is taken from the device tree.
66 */
67struct machine_data {
68 struct snd_soc_dai_link dai[2];
69 struct snd_soc_card card;
70 unsigned int dai_format;
71 unsigned int codec_clk_direction;
72 unsigned int cpu_clk_direction;
73 unsigned int clk_frequency;
74 unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */
75 unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */
76 unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
77 char codec_name[DAI_NAME_SIZE];
78 char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
79};
80
81/**
82 * p1022_ds_machine_probe: initialize the board
83 *
84 * This function is used to initialize the board-specific hardware.
85 *
86 * Here we program the DMACR and PMUXCR registers.
87 */
88static int p1022_ds_machine_probe(struct platform_device *sound_device)
89{
90 struct snd_soc_card *card = platform_get_drvdata(sound_device);
91 struct machine_data *mdata =
92 container_of(card, struct machine_data, card);
93 struct ccsr_guts_85xx __iomem *guts;
94
95 guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
96 if (!guts) {
97 dev_err(card->dev, "could not map global utilities\n");
98 return -ENOMEM;
99 }
100
101 /* Enable SSI Tx signal */
102 clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK,
103 CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI);
104
105 /* Enable SSI Rx signal */
106 clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK,
107 CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI);
108
109 /* Enable DMA Channel for SSI */
110 guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0],
111 CCSR_GUTS_DMUXCR_SSI);
112
113 guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1],
114 CCSR_GUTS_DMUXCR_SSI);
115
116 iounmap(guts);
117
118 return 0;
119}
120
121/**
122 * p1022_ds_startup: program the board with various hardware parameters
123 *
124 * This function takes board-specific information, like clock frequencies
125 * and serial data formats, and passes that information to the codec and
126 * transport drivers.
127 */
128static int p1022_ds_startup(struct snd_pcm_substream *substream)
129{
130 struct snd_soc_pcm_runtime *rtd = substream->private_data;
131 struct machine_data *mdata =
132 container_of(rtd->card, struct machine_data, card);
133 struct device *dev = rtd->card->dev;
134 int ret = 0;
135
136 /* Tell the codec driver what the serial protocol is. */
137 ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format);
138 if (ret < 0) {
139 dev_err(dev, "could not set codec driver audio format\n");
140 return ret;
141 }
142
143 /*
144 * Tell the codec driver what the MCLK frequency is, and whether it's
145 * a slave or master.
146 */
147 ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, mdata->clk_frequency,
148 mdata->codec_clk_direction);
149 if (ret < 0) {
150 dev_err(dev, "could not set codec driver clock params\n");
151 return ret;
152 }
153
154 return 0;
155}
156
157/**
158 * p1022_ds_machine_remove: Remove the sound device
159 *
160 * This function is called to remove the sound device for one SSI. We
161 * de-program the DMACR and PMUXCR register.
162 */
163static int p1022_ds_machine_remove(struct platform_device *sound_device)
164{
165 struct snd_soc_card *card = platform_get_drvdata(sound_device);
166 struct machine_data *mdata =
167 container_of(card, struct machine_data, card);
168 struct ccsr_guts_85xx __iomem *guts;
169
170 guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
171 if (!guts) {
172 dev_err(card->dev, "could not map global utilities\n");
173 return -ENOMEM;
174 }
175
176 /* Restore the signal routing */
177 clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK);
178 clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK);
179 guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0);
180 guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0);
181
182 iounmap(guts);
183
184 return 0;
185}
186
187/**
188 * p1022_ds_ops: ASoC machine driver operations
189 */
190static struct snd_soc_ops p1022_ds_ops = {
191 .startup = p1022_ds_startup,
192};
193
194/**
195 * get_node_by_phandle_name - get a node by its phandle name
196 *
197 * This function takes a node, the name of a property in that node, and a
198 * compatible string. Assuming the property is a phandle to another node,
199 * it returns that node, (optionally) if that node is compatible.
200 *
201 * If the property is not a phandle, or the node it points to is not compatible
202 * with the specific string, then NULL is returned.
203 */
204static struct device_node *get_node_by_phandle_name(struct device_node *np,
205 const char *name, const char *compatible)
206{
207 np = of_parse_phandle(np, name, 0);
208 if (!np)
209 return NULL;
210
211 if (!of_device_is_compatible(np, compatible)) {
212 of_node_put(np);
213 return NULL;
214 }
215
216 return np;
217}
218
219/**
220 * get_parent_cell_index -- return the cell-index of the parent of a node
221 *
222 * Return the value of the cell-index property of the parent of the given
223 * node. This is used for DMA channel nodes that need to know the DMA ID
224 * of the controller they are on.
225 */
226static int get_parent_cell_index(struct device_node *np)
227{
228 struct device_node *parent = of_get_parent(np);
229 const u32 *iprop;
230 int ret = -1;
231
232 if (!parent)
233 return -1;
234
235 iprop = of_get_property(parent, "cell-index", NULL);
236 if (iprop)
237 ret = *iprop;
238
239 of_node_put(parent);
240
241 return ret;
242}
243
244/**
245 * codec_node_dev_name - determine the dev_name for a codec node
246 *
247 * This function determines the dev_name for an I2C node. This is the name
248 * that would be returned by dev_name() if this device_node were part of a
249 * 'struct device' It's ugly and hackish, but it works.
250 *
251 * The dev_name for such devices include the bus number and I2C address. For
252 * example, "cs4270-codec.0-004f".
253 */
254static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
255{
256 const u32 *iprop;
257 int bus, addr;
258 char temp[DAI_NAME_SIZE];
259
260 of_modalias_node(np, temp, DAI_NAME_SIZE);
261
262 iprop = of_get_property(np, "reg", NULL);
263 if (!iprop)
264 return -EINVAL;
265
266 addr = *iprop;
267
268 bus = get_parent_cell_index(np);
269 if (bus < 0)
270 return bus;
271
272 snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
273
274 return 0;
275}
276
277static int get_dma_channel(struct device_node *ssi_np,
278 const char *compatible,
279 struct snd_soc_dai_link *dai,
280 unsigned int *dma_channel_id,
281 unsigned int *dma_id)
282{
283 struct resource res;
284 struct device_node *dma_channel_np;
285 const u32 *iprop;
286 int ret;
287
288 dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
289 "fsl,ssi-dma-channel");
290 if (!dma_channel_np)
291 return -EINVAL;
292
293 /* Determine the dev_name for the device_node. This code mimics the
294 * behavior of of_device_make_bus_id(). We need this because ASoC uses
295 * the dev_name() of the device to match the platform (DMA) device with
296 * the CPU (SSI) device. It's all ugly and hackish, but it works (for
297 * now).
298 *
299 * dai->platform name should already point to an allocated buffer.
300 */
301 ret = of_address_to_resource(dma_channel_np, 0, &res);
302 if (ret)
303 return ret;
304 snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
305 (unsigned long long) res.start, dma_channel_np->name);
306
307 iprop = of_get_property(dma_channel_np, "cell-index", NULL);
308 if (!iprop) {
309 of_node_put(dma_channel_np);
310 return -EINVAL;
311 }
312
313 *dma_channel_id = *iprop;
314 *dma_id = get_parent_cell_index(dma_channel_np);
315 of_node_put(dma_channel_np);
316
317 return 0;
318}
319
320/**
321 * p1022_ds_probe: platform probe function for the machine driver
322 *
323 * Although this is a machine driver, the SSI node is the "master" node with
324 * respect to audio hardware connections. Therefore, we create a new ASoC
325 * device for each new SSI node that has a codec attached.
326 */
327static int p1022_ds_probe(struct platform_device *pdev)
328{
329 struct device *dev = pdev->dev.parent;
330 /* ssi_pdev is the platform device for the SSI node that probed us */
331 struct platform_device *ssi_pdev =
332 container_of(dev, struct platform_device, dev);
333 struct device_node *np = ssi_pdev->dev.of_node;
334 struct device_node *codec_np = NULL;
335 struct platform_device *sound_device = NULL;
336 struct machine_data *mdata;
337 int ret = -ENODEV;
338 const char *sprop;
339 const u32 *iprop;
340
341 /* Find the codec node for this SSI. */
342 codec_np = of_parse_phandle(np, "codec-handle", 0);
343 if (!codec_np) {
344 dev_err(dev, "could not find codec node\n");
345 return -EINVAL;
346 }
347
348 mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL);
349 if (!mdata) {
350 ret = -ENOMEM;
351 goto error_put;
352 }
353
354 mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
355 mdata->dai[0].ops = &p1022_ds_ops;
356
357 /* Determine the codec name, it will be used as the codec DAI name */
358 ret = codec_node_dev_name(codec_np, mdata->codec_name, DAI_NAME_SIZE);
359 if (ret) {
360 dev_err(&pdev->dev, "invalid codec node %s\n",
361 codec_np->full_name);
362 ret = -EINVAL;
363 goto error;
364 }
365 mdata->dai[0].codec_name = mdata->codec_name;
366
367 /* We register two DAIs per SSI, one for playback and the other for
368 * capture. We support codecs that have separate DAIs for both playback
369 * and capture.
370 */
371 memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link));
372
373 /* The DAI names from the codec (snd_soc_dai_driver.name) */
374 mdata->dai[0].codec_dai_name = "wm8776-hifi-playback";
375 mdata->dai[1].codec_dai_name = "wm8776-hifi-capture";
376
377 /* Get the device ID */
378 iprop = of_get_property(np, "cell-index", NULL);
379 if (!iprop) {
380 dev_err(&pdev->dev, "cell-index property not found\n");
381 ret = -EINVAL;
382 goto error;
383 }
384 mdata->ssi_id = *iprop;
385
386 /* Get the serial format and clock direction. */
387 sprop = of_get_property(np, "fsl,mode", NULL);
388 if (!sprop) {
389 dev_err(&pdev->dev, "fsl,mode property not found\n");
390 ret = -EINVAL;
391 goto error;
392 }
393
394 if (strcasecmp(sprop, "i2s-slave") == 0) {
395 mdata->dai_format = SND_SOC_DAIFMT_I2S;
396 mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
397 mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
398
399 /* In i2s-slave mode, the codec has its own clock source, so we
400 * need to get the frequency from the device tree and pass it to
401 * the codec driver.
402 */
403 iprop = of_get_property(codec_np, "clock-frequency", NULL);
404 if (!iprop || !*iprop) {
405 dev_err(&pdev->dev, "codec bus-frequency "
406 "property is missing or invalid\n");
407 ret = -EINVAL;
408 goto error;
409 }
410 mdata->clk_frequency = *iprop;
411 } else if (strcasecmp(sprop, "i2s-master") == 0) {
412 mdata->dai_format = SND_SOC_DAIFMT_I2S;
413 mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
414 mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
415 } else if (strcasecmp(sprop, "lj-slave") == 0) {
416 mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
417 mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
418 mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
419 } else if (strcasecmp(sprop, "lj-master") == 0) {
420 mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
421 mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
422 mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
423 } else if (strcasecmp(sprop, "rj-slave") == 0) {
424 mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
425 mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
426 mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
427 } else if (strcasecmp(sprop, "rj-master") == 0) {
428 mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
429 mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
430 mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
431 } else if (strcasecmp(sprop, "ac97-slave") == 0) {
432 mdata->dai_format = SND_SOC_DAIFMT_AC97;
433 mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
434 mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
435 } else if (strcasecmp(sprop, "ac97-master") == 0) {
436 mdata->dai_format = SND_SOC_DAIFMT_AC97;
437 mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
438 mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
439 } else {
440 dev_err(&pdev->dev,
441 "unrecognized fsl,mode property '%s'\n", sprop);
442 ret = -EINVAL;
443 goto error;
444 }
445
446 if (!mdata->clk_frequency) {
447 dev_err(&pdev->dev, "unknown clock frequency\n");
448 ret = -EINVAL;
449 goto error;
450 }
451
452 /* Find the playback DMA channel to use. */
453 mdata->dai[0].platform_name = mdata->platform_name[0];
454 ret = get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
455 &mdata->dma_channel_id[0],
456 &mdata->dma_id[0]);
457 if (ret) {
458 dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");
459 goto error;
460 }
461
462 /* Find the capture DMA channel to use. */
463 mdata->dai[1].platform_name = mdata->platform_name[1];
464 ret = get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
465 &mdata->dma_channel_id[1],
466 &mdata->dma_id[1]);
467 if (ret) {
468 dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");
469 goto error;
470 }
471
472 /* Initialize our DAI data structure. */
473 mdata->dai[0].stream_name = "playback";
474 mdata->dai[1].stream_name = "capture";
475 mdata->dai[0].name = mdata->dai[0].stream_name;
476 mdata->dai[1].name = mdata->dai[1].stream_name;
477
478 mdata->card.probe = p1022_ds_machine_probe;
479 mdata->card.remove = p1022_ds_machine_remove;
480 mdata->card.name = pdev->name; /* The platform driver name */
481 mdata->card.num_links = 2;
482 mdata->card.dai_link = mdata->dai;
483
484 /* Allocate a new audio platform device structure */
485 sound_device = platform_device_alloc("soc-audio", -1);
486 if (!sound_device) {
487 dev_err(&pdev->dev, "platform device alloc failed\n");
488 ret = -ENOMEM;
489 goto error;
490 }
491
492 /* Associate the card data with the sound device */
493 platform_set_drvdata(sound_device, &mdata->card);
494
495 /* Register with ASoC */
496 ret = platform_device_add(sound_device);
497 if (ret) {
498 dev_err(&pdev->dev, "platform device add failed\n");
499 goto error;
500 }
501
502 of_node_put(codec_np);
503
504 return 0;
505
506error:
507 if (sound_device)
508 platform_device_unregister(sound_device);
509
510 kfree(mdata);
511error_put:
512 of_node_put(codec_np);
513 return ret;
514}
515
516/**
517 * p1022_ds_remove: remove the platform device
518 *
519 * This function is called when the platform device is removed.
520 */
521static int __devexit p1022_ds_remove(struct platform_device *pdev)
522{
523 struct platform_device *sound_device = dev_get_drvdata(&pdev->dev);
524 struct snd_soc_card *card = platform_get_drvdata(sound_device);
525 struct machine_data *mdata =
526 container_of(card, struct machine_data, card);
527
528 platform_device_unregister(sound_device);
529
530 kfree(mdata);
531 sound_device->dev.platform_data = NULL;
532
533 dev_set_drvdata(&pdev->dev, NULL);
534
535 return 0;
536}
537
538static struct platform_driver p1022_ds_driver = {
539 .probe = p1022_ds_probe,
540 .remove = __devexit_p(p1022_ds_remove),
541 .driver = {
542 /* The name must match the 'model' property in the device tree,
543 * in lowercase letters, but only the part after that last
544 * comma. This is because some model properties have a "fsl,"
545 * prefix.
546 */
547 .name = "snd-soc-p1022",
548 .owner = THIS_MODULE,
549 },
550};
551
552/**
553 * p1022_ds_init: machine driver initialization.
554 *
555 * This function is called when this module is loaded.
556 */
557static int __init p1022_ds_init(void)
558{
559 struct device_node *guts_np;
560 struct resource res;
561
562 pr_info("Freescale P1022 DS ALSA SoC machine driver\n");
563
564 /* Get the physical address of the global utilities registers */
565 guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
566 if (of_address_to_resource(guts_np, 0, &res)) {
567 pr_err("p1022-ds: missing/invalid global utilities node\n");
568 return -EINVAL;
569 }
570 guts_phys = res.start;
571 of_node_put(guts_np);
572
573 return platform_driver_register(&p1022_ds_driver);
574}
575
576/**
577 * p1022_ds_exit: machine driver exit
578 *
579 * This function is called when this driver is unloaded.
580 */
581static void __exit p1022_ds_exit(void)
582{
583 platform_driver_unregister(&p1022_ds_driver);
584}
585
586module_init(p1022_ds_init);
587module_exit(p1022_ds_exit);
588
589MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
590MODULE_DESCRIPTION("Freescale P1022 DS ALSA SoC machine driver");
591MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
index 6644cba7cbf2..fe15bb26e484 100644
--- a/sound/soc/fsl/pcm030-audio-fabric.c
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -32,21 +32,24 @@
32 32
33#define DRV_NAME "pcm030-audio-fabric" 33#define DRV_NAME "pcm030-audio-fabric"
34 34
35static struct snd_soc_device device;
36static struct snd_soc_card card; 35static struct snd_soc_card card;
37 36
38static struct snd_soc_dai_link pcm030_fabric_dai[] = { 37static struct snd_soc_dai_link pcm030_fabric_dai[] = {
39{ 38{
40 .name = "AC97", 39 .name = "AC97",
41 .stream_name = "AC97 Analog", 40 .stream_name = "AC97 Analog",
42 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 41 .codec_dai_name = "wm9712-hifi",
43 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], 42 .cpu_dai_name = "mpc5200-psc-ac97.0",
43 .platform_name = "mpc5200-pcm-audio",
44 .codec_name = "wm9712-codec",
44}, 45},
45{ 46{
46 .name = "AC97", 47 .name = "AC97",
47 .stream_name = "AC97 IEC958", 48 .stream_name = "AC97 IEC958",
48 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 49 .codec_dai_name = "wm9712-aux",
49 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], 50 .cpu_dai_name = "mpc5200-psc-ac97.1",
51 .platform_name = "mpc5200-pcm-audio",
52 ..codec_name = "wm9712-codec",
50}, 53},
51}; 54};
52 55
@@ -58,22 +61,18 @@ static __init int pcm030_fabric_init(void)
58 if (!of_machine_is_compatible("phytec,pcm030")) 61 if (!of_machine_is_compatible("phytec,pcm030"))
59 return -ENODEV; 62 return -ENODEV;
60 63
61 card.platform = &mpc5200_audio_dma_platform; 64
62 card.name = "pcm030"; 65 card.name = "pcm030";
63 card.dai_link = pcm030_fabric_dai; 66 card.dai_link = pcm030_fabric_dai;
64 card.num_links = ARRAY_SIZE(pcm030_fabric_dai); 67 card.num_links = ARRAY_SIZE(pcm030_fabric_dai);
65 68
66 device.card = &card;
67 device.codec_dev = &soc_codec_dev_wm9712;
68
69 pdev = platform_device_alloc("soc-audio", 1); 69 pdev = platform_device_alloc("soc-audio", 1);
70 if (!pdev) { 70 if (!pdev) {
71 pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); 71 pr_err("pcm030_fabric_init: platform_device_alloc() failed\n");
72 return -ENODEV; 72 return -ENODEV;
73 } 73 }
74 74
75 platform_set_drvdata(pdev, &device); 75 platform_set_drvdata(pdev, &card);
76 device.dev = &pdev->dev;
77 76
78 rc = platform_device_add(pdev); 77 rc = platform_device_add(pdev);
79 if (rc) { 78 if (rc) {
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
deleted file mode 100644
index 3bc13fd89096..000000000000
--- a/sound/soc/fsl/soc-of-simple.c
+++ /dev/null
@@ -1,172 +0,0 @@
1/*
2 * OF helpers for ALSA SoC Layer
3 *
4 * Copyright (C) 2008, Secret Lab Technologies Ltd.
5 */
6
7#include <linux/module.h>
8#include <linux/moduleparam.h>
9#include <linux/init.h>
10#include <linux/delay.h>
11#include <linux/pm.h>
12#include <linux/bitops.h>
13#include <linux/platform_device.h>
14#include <linux/of.h>
15#include <linux/slab.h>
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/soc.h>
20#include <sound/soc-of-simple.h>
21#include <sound/initval.h>
22
23MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
24MODULE_LICENSE("GPL");
25MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings");
26
27static DEFINE_MUTEX(of_snd_soc_mutex);
28static LIST_HEAD(of_snd_soc_device_list);
29static int of_snd_soc_next_index;
30
31struct of_snd_soc_device {
32 int id;
33 struct list_head list;
34 struct snd_soc_device device;
35 struct snd_soc_card card;
36 struct snd_soc_dai_link dai_link;
37 struct platform_device *pdev;
38 struct device_node *platform_node;
39 struct device_node *codec_node;
40};
41
42static struct snd_soc_ops of_snd_soc_ops = {
43};
44
45static struct of_snd_soc_device *
46of_snd_soc_get_device(struct device_node *codec_node)
47{
48 struct of_snd_soc_device *of_soc;
49
50 list_for_each_entry(of_soc, &of_snd_soc_device_list, list) {
51 if (of_soc->codec_node == codec_node)
52 return of_soc;
53 }
54
55 of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL);
56 if (!of_soc)
57 return NULL;
58
59 /* Initialize the structure and add it to the global list */
60 of_soc->codec_node = codec_node;
61 of_soc->id = of_snd_soc_next_index++;
62 of_soc->card.dai_link = &of_soc->dai_link;
63 of_soc->card.num_links = 1;
64 of_soc->device.card = &of_soc->card;
65 of_soc->dai_link.ops = &of_snd_soc_ops;
66 list_add(&of_soc->list, &of_snd_soc_device_list);
67
68 return of_soc;
69}
70
71static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc)
72{
73 struct platform_device *pdev;
74 int rc;
75
76 /* Only register the device if both the codec and platform have
77 * been registered */
78 if ((!of_soc->device.codec_data) || (!of_soc->platform_node))
79 return;
80
81 pr_info("platform<-->codec match achieved; registering machine\n");
82
83 pdev = platform_device_alloc("soc-audio", of_soc->id);
84 if (!pdev) {
85 pr_err("of_soc: platform_device_alloc() failed\n");
86 return;
87 }
88
89 pdev->dev.platform_data = of_soc;
90 platform_set_drvdata(pdev, &of_soc->device);
91 of_soc->device.dev = &pdev->dev;
92
93 /* The ASoC device is complete; register it */
94 rc = platform_device_add(pdev);
95 if (rc) {
96 pr_err("of_soc: platform_device_add() failed\n");
97 return;
98 }
99
100}
101
102int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
103 void *codec_data, struct snd_soc_dai *dai,
104 struct device_node *node)
105{
106 struct of_snd_soc_device *of_soc;
107 int rc = 0;
108
109 pr_info("registering ASoC codec driver: %s\n", node->full_name);
110
111 mutex_lock(&of_snd_soc_mutex);
112 of_soc = of_snd_soc_get_device(node);
113 if (!of_soc) {
114 rc = -ENOMEM;
115 goto out;
116 }
117
118 /* Store the codec data */
119 of_soc->device.codec_data = codec_data;
120 of_soc->device.codec_dev = codec_dev;
121 of_soc->dai_link.name = (char *)node->name;
122 of_soc->dai_link.stream_name = (char *)node->name;
123 of_soc->dai_link.codec_dai = dai;
124
125 /* Now try to register the SoC device */
126 of_snd_soc_register_device(of_soc);
127
128 out:
129 mutex_unlock(&of_snd_soc_mutex);
130 return rc;
131}
132EXPORT_SYMBOL_GPL(of_snd_soc_register_codec);
133
134int of_snd_soc_register_platform(struct snd_soc_platform *platform,
135 struct device_node *node,
136 struct snd_soc_dai *cpu_dai)
137{
138 struct of_snd_soc_device *of_soc;
139 struct device_node *codec_node;
140 const phandle *handle;
141 int len, rc = 0;
142
143 pr_info("registering ASoC platform driver: %s\n", node->full_name);
144
145 handle = of_get_property(node, "codec-handle", &len);
146 if (!handle || len < sizeof(handle))
147 return -ENODEV;
148 codec_node = of_find_node_by_phandle(*handle);
149 if (!codec_node)
150 return -ENODEV;
151 pr_info("looking for codec: %s\n", codec_node->full_name);
152
153 mutex_lock(&of_snd_soc_mutex);
154 of_soc = of_snd_soc_get_device(codec_node);
155 if (!of_soc) {
156 rc = -ENOMEM;
157 goto out;
158 }
159
160 of_soc->platform_node = node;
161 of_soc->dai_link.cpu_dai = cpu_dai;
162 of_soc->card.platform = platform;
163 of_soc->card.name = of_soc->dai_link.cpu_dai->name;
164
165 /* Now try to register the SoC device */
166 of_snd_soc_register_device(of_soc);
167
168 out:
169 mutex_unlock(&of_snd_soc_mutex);
170 return rc;
171}
172EXPORT_SYMBOL_GPL(of_snd_soc_register_platform);