aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/txx9
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@slimlogic.co.uk>2010-03-17 16:15:21 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-08-12 09:00:00 -0400
commitf0fba2ad1b6b53d5360125c41953b7afcd6deff0 (patch)
treef6ad50905f8daa616593c978d7ae992e73241180 /sound/soc/txx9
parentbda7d2a862e6b788bca2d02d38a07966a9c92e48 (diff)
ASoC: multi-component - ASoC Multi-Component Support
This patch extends the ASoC API to allow sound cards to have more than one CODEC and more than one platform DMA controller. This is achieved by dividing some current ASoC structures that contain both driver data and device data into structures that only either contain device data or driver data. i.e. struct snd_soc_codec ---> struct snd_soc_codec (device data) +-> struct snd_soc_codec_driver (driver data) struct snd_soc_platform ---> struct snd_soc_platform (device data) +-> struct snd_soc_platform_driver (driver data) struct snd_soc_dai ---> struct snd_soc_dai (device data) +-> struct snd_soc_dai_driver (driver data) struct snd_soc_device ---> deleted This now allows ASoC to be more tightly aligned with the Linux driver model and also means that every ASoC codec, platform and (platform) DAI is a kernel device. ASoC component private data is now stored as device private data. The ASoC sound card struct snd_soc_card has also been updated to store lists of it's components rather than a pointer to a codec and platform. The PCM runtime struct soc_pcm_runtime now has pointers to all its components. This patch adds DAPM support for ASoC multi-component and removes struct snd_soc_socdev from DAPM core. All DAPM calls are now made on a card, codec or runtime PCM level basis rather than using snd_soc_socdev. Other notable multi-component changes:- * Stream operations now de-reference less structures. * close_delayed work() now runs on a DAI basis rather than looping all DAIs in a card. * PM suspend()/resume() operations can now handle N CODECs and Platforms per sound card. * Added soc_bind_dai_link() to bind the component devices to the sound card. * Added soc_dai_link_probe() and soc_dai_link_remove() to probe and remove DAI link components. * sysfs entries can now be registered per component per card. * snd_soc_new_pcms() functionailty rolled into dai_link_probe(). * snd_soc_register_codec() now does all the codec list and mutex init. This patch changes the probe() and remove() of the CODEC drivers as follows:- o Make CODEC driver a platform driver o Moved all struct snd_soc_codec list, mutex, etc initialiasation to core. o Removed all static codec pointers (drivers now support > 1 codec dev) o snd_soc_register_pcms() now done by core. o snd_soc_register_dai() folded into snd_soc_register_codec(). CS4270 portions: Acked-by: Timur Tabi <timur@freescale.com> Some TLV320aic23 and Cirrus platform fixes. Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> TI CODEC and OMAP fixes Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> Samsung platform and misc fixes :- Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Jassi Brar <jassi.brar@samsung.com> Signed-off-by: Seungwhan Youn <sw.youn@samsung.com> MPC8610 and PPC fixes. Signed-off-by: Timur Tabi <timur@freescale.com> i.MX fixes and some core fixes. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> J4740 platform fixes:- Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> CC: Tony Lindgren <tony@atomide.com> CC: Nicolas Ferre <nicolas.ferre@atmel.com> CC: Kevin Hilman <khilman@deeprootsystems.com> CC: Sascha Hauer <s.hauer@pengutronix.de> CC: Atsushi Nemoto <anemo@mba.ocn.ne.jp> CC: Kuninori Morimoto <morimoto.kuninori@renesas.com> CC: Daniel Gloeckner <dg@emlix.com> CC: Manuel Lauss <mano@roarinelk.homelinux.net> CC: Mike Frysinger <vapier.adi@gmail.com> CC: Arnaud Patard <apatard@mandriva.com> CC: Wan ZongShun <mcuos.com@gmail.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/txx9')
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c55
-rw-r--r--sound/soc/txx9/txx9aclc-generic.c24
-rw-r--r--sound/soc/txx9/txx9aclc.c141
-rw-r--r--sound/soc/txx9/txx9aclc.h13
4 files changed, 109 insertions, 124 deletions
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index 0ec20b68e8cb..743d07b82c06 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -36,13 +36,11 @@
36 36
37static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq); 37static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq);
38 38
39/* REVISIT: How to find txx9aclc_soc_device from snd_ac97? */ 39/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
40static struct txx9aclc_soc_device *txx9aclc_soc_dev; 40static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
41 41
42static int txx9aclc_regready(struct txx9aclc_soc_device *dev) 42static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata)
43{ 43{
44 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
45
46 return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY; 44 return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;
47} 45}
48 46
@@ -50,8 +48,7 @@ static int txx9aclc_regready(struct txx9aclc_soc_device *dev)
50static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, 48static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
51 unsigned short reg) 49 unsigned short reg)
52{ 50{
53 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; 51 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
54 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
55 void __iomem *base = drvdata->base; 52 void __iomem *base = drvdata->base;
56 u32 dat; 53 u32 dat;
57 54
@@ -61,15 +58,15 @@ static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
61 dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ; 58 dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;
62 __raw_writel(dat, base + ACREGACC); 59 __raw_writel(dat, base + ACREGACC);
63 __raw_writel(ACINT_REGACCRDY, base + ACINTEN); 60 __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
64 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { 61 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
65 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); 62 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
66 dev_err(dev->soc_dev.dev, "ac97 read timeout (reg %#x)\n", reg); 63 printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg);
67 dat = 0xffff; 64 dat = 0xffff;
68 goto done; 65 goto done;
69 } 66 }
70 dat = __raw_readl(base + ACREGACC); 67 dat = __raw_readl(base + ACREGACC);
71 if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) { 68 if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) {
72 dev_err(dev->soc_dev.dev, "reg mismatch %x with %x\n", 69 printk(KERN_ERR "reg mismatch %x with %x\n",
73 dat, reg); 70 dat, reg);
74 dat = 0xffff; 71 dat = 0xffff;
75 goto done; 72 goto done;
@@ -84,16 +81,15 @@ done:
84static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, 81static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
85 unsigned short val) 82 unsigned short val)
86{ 83{
87 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; 84 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
88 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
89 void __iomem *base = drvdata->base; 85 void __iomem *base = drvdata->base;
90 86
91 __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) | 87 __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |
92 (val << ACREGACC_DAT_SHIFT), 88 (val << ACREGACC_DAT_SHIFT),
93 base + ACREGACC); 89 base + ACREGACC);
94 __raw_writel(ACINT_REGACCRDY, base + ACINTEN); 90 __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
95 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { 91 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
96 dev_err(dev->soc_dev.dev, 92 printk(KERN_ERR
97 "ac97 write timeout (reg %#x)\n", reg); 93 "ac97 write timeout (reg %#x)\n", reg);
98 } 94 }
99 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); 95 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
@@ -101,8 +97,7 @@ static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
101 97
102static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) 98static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)
103{ 99{
104 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; 100 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
105 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
106 void __iomem *base = drvdata->base; 101 void __iomem *base = drvdata->base;
107 u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY; 102 u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY;
108 103
@@ -141,31 +136,23 @@ static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)
141 return IRQ_HANDLED; 136 return IRQ_HANDLED;
142} 137}
143 138
144static int txx9aclc_ac97_probe(struct platform_device *pdev, 139static int txx9aclc_ac97_probe(struct snd_soc_dai *dai)
145 struct snd_soc_dai *dai)
146{ 140{
147 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 141 txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai);
148 struct txx9aclc_soc_device *dev =
149 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
150
151 dev->aclc_pdev = to_platform_device(dai->dev);
152 txx9aclc_soc_dev = dev;
153 return 0; 142 return 0;
154} 143}
155 144
156static void txx9aclc_ac97_remove(struct platform_device *pdev, 145static int txx9aclc_ac97_remove(struct snd_soc_dai *dai)
157 struct snd_soc_dai *dai)
158{ 146{
159 struct platform_device *aclc_pdev = to_platform_device(dai->dev); 147 struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai);
160 struct txx9aclc_plat_drvdata *drvdata = platform_get_drvdata(aclc_pdev);
161 148
162 /* disable AC-link */ 149 /* disable AC-link */
163 __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS); 150 __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS);
164 txx9aclc_soc_dev = NULL; 151 txx9aclc_drvdata = NULL;
152 return 0;
165} 153}
166 154
167struct snd_soc_dai txx9aclc_ac97_dai = { 155static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
168 .name = "txx9aclc_ac97",
169 .ac97_control = 1, 156 .ac97_control = 1,
170 .probe = txx9aclc_ac97_probe, 157 .probe = txx9aclc_ac97_probe,
171 .remove = txx9aclc_ac97_remove, 158 .remove = txx9aclc_ac97_remove,
@@ -182,7 +169,6 @@ struct snd_soc_dai txx9aclc_ac97_dai = {
182 .channels_max = 2, 169 .channels_max = 2,
183 }, 170 },
184}; 171};
185EXPORT_SYMBOL_GPL(txx9aclc_ac97_dai);
186 172
187static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev) 173static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
188{ 174{
@@ -219,13 +205,12 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
219 if (err < 0) 205 if (err < 0)
220 return err; 206 return err;
221 207
222 txx9aclc_ac97_dai.dev = &pdev->dev; 208 return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai);
223 return snd_soc_register_dai(&txx9aclc_ac97_dai);
224} 209}
225 210
226static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev) 211static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
227{ 212{
228 snd_soc_unregister_dai(&txx9aclc_ac97_dai); 213 snd_soc_unregister_dai(&pdev->dev);
229 return 0; 214 return 0;
230} 215}
231 216
diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c
index 95b17f731aec..6770e7166be4 100644
--- a/sound/soc/txx9/txx9aclc-generic.c
+++ b/sound/soc/txx9/txx9aclc-generic.c
@@ -19,54 +19,44 @@
19#include <sound/core.h> 19#include <sound/core.h>
20#include <sound/pcm.h> 20#include <sound/pcm.h>
21#include <sound/soc.h> 21#include <sound/soc.h>
22#include "../codecs/ac97.h"
23#include "txx9aclc.h" 22#include "txx9aclc.h"
24 23
25static struct snd_soc_dai_link txx9aclc_generic_dai = { 24static struct snd_soc_dai_link txx9aclc_generic_dai = {
26 .name = "AC97", 25 .name = "AC97",
27 .stream_name = "AC97 HiFi", 26 .stream_name = "AC97 HiFi",
28 .cpu_dai = &txx9aclc_ac97_dai, 27 .cpu_dai_name = "txx9aclc-ac97",
29 .codec_dai = &ac97_dai, 28 .codec_dai_name = "ac97-hifi",
29 .platform_name = "txx9aclc-pcm-audio",
30 .codec_name = "ac97-codec",
30}; 31};
31 32
32static struct snd_soc_card txx9aclc_generic_card = { 33static struct snd_soc_card txx9aclc_generic_card = {
33 .name = "Generic TXx9 ACLC Audio", 34 .name = "Generic TXx9 ACLC Audio",
34 .platform = &txx9aclc_soc_platform,
35 .dai_link = &txx9aclc_generic_dai, 35 .dai_link = &txx9aclc_generic_dai,
36 .num_links = 1, 36 .num_links = 1,
37}; 37};
38 38
39static struct txx9aclc_soc_device txx9aclc_generic_soc_device = { 39static struct platform_device *soc_pdev;
40 .soc_dev = {
41 .card = &txx9aclc_generic_card,
42 .codec_dev = &soc_codec_dev_ac97,
43 },
44};
45 40
46static int __init txx9aclc_generic_probe(struct platform_device *pdev) 41static int __init txx9aclc_generic_probe(struct platform_device *pdev)
47{ 42{
48 struct txx9aclc_soc_device *dev = &txx9aclc_generic_soc_device;
49 struct platform_device *soc_pdev;
50 int ret; 43 int ret;
51 44
52 soc_pdev = platform_device_alloc("soc-audio", -1); 45 soc_pdev = platform_device_alloc("soc-audio", -1);
53 if (!soc_pdev) 46 if (!soc_pdev)
54 return -ENOMEM; 47 return -ENOMEM;
55 platform_set_drvdata(soc_pdev, &dev->soc_dev); 48 platform_set_drvdata(soc_pdev, &txx9aclc_generic_card);
56 dev->soc_dev.dev = &soc_pdev->dev;
57 ret = platform_device_add(soc_pdev); 49 ret = platform_device_add(soc_pdev);
58 if (ret) { 50 if (ret) {
59 platform_device_put(soc_pdev); 51 platform_device_put(soc_pdev);
60 return ret; 52 return ret;
61 } 53 }
62 platform_set_drvdata(pdev, soc_pdev); 54
63 return 0; 55 return 0;
64} 56}
65 57
66static int __exit txx9aclc_generic_remove(struct platform_device *pdev) 58static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
67{ 59{
68 struct platform_device *soc_pdev = platform_get_drvdata(pdev);
69
70 platform_device_unregister(soc_pdev); 60 platform_device_unregister(soc_pdev);
71 return 0; 61 return 0;
72} 62}
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index 0e3452303ea6..f4aa4e03c888 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -22,6 +22,16 @@
22#include <sound/soc.h> 22#include <sound/soc.h>
23#include "txx9aclc.h" 23#include "txx9aclc.h"
24 24
25static struct txx9aclc_soc_device {
26 struct txx9aclc_dmadata dmadata[2];
27} txx9aclc_soc_device;
28
29/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
30static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
31
32static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
33 struct txx9aclc_dmadata *dmadata);
34
25static const struct snd_pcm_hardware txx9aclc_pcm_hardware = { 35static const struct snd_pcm_hardware txx9aclc_pcm_hardware = {
26 /* 36 /*
27 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID 37 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
@@ -46,7 +56,6 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,
46 struct snd_pcm_hw_params *params) 56 struct snd_pcm_hw_params *params)
47{ 57{
48 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 58 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
49 struct snd_soc_device *socdev = rtd->socdev;
50 struct snd_pcm_runtime *runtime = substream->runtime; 59 struct snd_pcm_runtime *runtime = substream->runtime;
51 struct txx9aclc_dmadata *dmadata = runtime->private_data; 60 struct txx9aclc_dmadata *dmadata = runtime->private_data;
52 int ret; 61 int ret;
@@ -55,13 +64,13 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,
55 if (ret < 0) 64 if (ret < 0)
56 return ret; 65 return ret;
57 66
58 dev_dbg(socdev->dev, 67 dev_dbg(rtd->platform->dev,
59 "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd " 68 "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
60 "runtime->min_align %ld\n", 69 "runtime->min_align %ld\n",
61 (unsigned long)runtime->dma_area, 70 (unsigned long)runtime->dma_area,
62 (unsigned long)runtime->dma_addr, runtime->dma_bytes, 71 (unsigned long)runtime->dma_addr, runtime->dma_bytes,
63 runtime->min_align); 72 runtime->min_align);
64 dev_dbg(socdev->dev, 73 dev_dbg(rtd->platform->dev,
65 "periods %d period_bytes %d stream %d\n", 74 "periods %d period_bytes %d stream %d\n",
66 params_periods(params), params_period_bytes(params), 75 params_periods(params), params_period_bytes(params),
67 substream->stream); 76 substream->stream);
@@ -152,11 +161,7 @@ static void txx9aclc_dma_tasklet(unsigned long data)
152 161
153 spin_lock_irqsave(&dmadata->dma_lock, flags); 162 spin_lock_irqsave(&dmadata->dma_lock, flags);
154 if (dmadata->frag_count < 0) { 163 if (dmadata->frag_count < 0) {
155 struct txx9aclc_soc_device *dev = 164 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
156 container_of(dmadata, struct txx9aclc_soc_device,
157 dmadata[substream->stream]);
158 struct txx9aclc_plat_drvdata *drvdata =
159 txx9aclc_get_plat_drvdata(dev);
160 void __iomem *base = drvdata->base; 165 void __iomem *base = drvdata->base;
161 166
162 spin_unlock_irqrestore(&dmadata->dma_lock, flags); 167 spin_unlock_irqrestore(&dmadata->dma_lock, flags);
@@ -202,10 +207,7 @@ static void txx9aclc_dma_tasklet(unsigned long data)
202static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 207static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
203{ 208{
204 struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; 209 struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
205 struct snd_soc_pcm_runtime *rtd = substream->private_data; 210 struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata;
206 struct txx9aclc_soc_device *dev =
207 container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev);
208 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
209 void __iomem *base = drvdata->base; 211 void __iomem *base = drvdata->base;
210 unsigned long flags; 212 unsigned long flags;
211 int ret = 0; 213 int ret = 0;
@@ -244,9 +246,7 @@ txx9aclc_pcm_pointer(struct snd_pcm_substream *substream)
244 246
245static int txx9aclc_pcm_open(struct snd_pcm_substream *substream) 247static int txx9aclc_pcm_open(struct snd_pcm_substream *substream)
246{ 248{
247 struct snd_soc_pcm_runtime *rtd = substream->private_data; 249 struct txx9aclc_soc_device *dev = &txx9aclc_soc_device;
248 struct txx9aclc_soc_device *dev =
249 container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev);
250 struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream]; 250 struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream];
251 int ret; 251 int ret;
252 252
@@ -291,8 +291,38 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)
291static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, 291static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
292 struct snd_pcm *pcm) 292 struct snd_pcm *pcm)
293{ 293{
294 struct platform_device *pdev = to_platform_device(dai->platform->dev);
295 struct txx9aclc_soc_device *dev;
296 struct resource *r;
297 int i;
298 int ret;
299
300 /* at this point onwards the AC97 component has probed and this will be valid */
301 dev = snd_soc_dai_get_drvdata(dai);
302
303 dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
304 dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
305 for (i = 0; i < 2; i++) {
306 r = platform_get_resource(pdev, IORESOURCE_DMA, i);
307 if (!r) {
308 ret = -EBUSY;
309 goto exit;
310 }
311 dev->dmadata[i].dma_res = r;
312 ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
313 if (ret)
314 goto exit;
315 }
294 return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 316 return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
295 card->dev, 64 * 1024, 4 * 1024 * 1024); 317 card->dev, 64 * 1024, 4 * 1024 * 1024);
318
319exit:
320 for (i = 0; i < 2; i++) {
321 if (dev->dmadata[i].dma_chan)
322 dma_release_channel(dev->dmadata[i].dma_chan);
323 dev->dmadata[i].dma_chan = NULL;
324 }
325 return ret;
296} 326}
297 327
298static bool filter(struct dma_chan *chan, void *param) 328static bool filter(struct dma_chan *chan, void *param)
@@ -314,7 +344,7 @@ static bool filter(struct dma_chan *chan, void *param)
314static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, 344static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
315 struct txx9aclc_dmadata *dmadata) 345 struct txx9aclc_dmadata *dmadata)
316{ 346{
317 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); 347 struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata;
318 struct txx9dmac_slave *ds = &dmadata->dma_slave; 348 struct txx9dmac_slave *ds = &dmadata->dma_slave;
319 dma_cap_mask_t mask; 349 dma_cap_mask_t mask;
320 350
@@ -334,7 +364,7 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
334 dma_cap_set(DMA_SLAVE, mask); 364 dma_cap_set(DMA_SLAVE, mask);
335 dmadata->dma_chan = dma_request_channel(mask, filter, dmadata); 365 dmadata->dma_chan = dma_request_channel(mask, filter, dmadata);
336 if (!dmadata->dma_chan) { 366 if (!dmadata->dma_chan) {
337 dev_err(dev->soc_dev.dev, 367 printk(KERN_ERR
338 "DMA channel for %s is not available\n", 368 "DMA channel for %s is not available\n",
339 dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ? 369 dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ?
340 "playback" : "capture"); 370 "playback" : "capture");
@@ -345,45 +375,16 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
345 return 0; 375 return 0;
346} 376}
347 377
348static int txx9aclc_pcm_probe(struct platform_device *pdev) 378static int txx9aclc_pcm_probe(struct snd_soc_platform *platform)
349{ 379{
350 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 380 snd_soc_platform_set_drvdata(platform, &txx9aclc_soc_device);
351 struct txx9aclc_soc_device *dev =
352 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
353 struct resource *r;
354 int i;
355 int ret;
356
357 dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
358 dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
359 for (i = 0; i < 2; i++) {
360 r = platform_get_resource(dev->aclc_pdev, IORESOURCE_DMA, i);
361 if (!r) {
362 ret = -EBUSY;
363 goto exit;
364 }
365 dev->dmadata[i].dma_res = r;
366 ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
367 if (ret)
368 goto exit;
369 }
370 return 0; 381 return 0;
371
372exit:
373 for (i = 0; i < 2; i++) {
374 if (dev->dmadata[i].dma_chan)
375 dma_release_channel(dev->dmadata[i].dma_chan);
376 dev->dmadata[i].dma_chan = NULL;
377 }
378 return ret;
379} 382}
380 383
381static int txx9aclc_pcm_remove(struct platform_device *pdev) 384static int txx9aclc_pcm_remove(struct snd_soc_platform *platform)
382{ 385{
383 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 386 struct txx9aclc_soc_device *dev = snd_soc_platform_get_drvdata(platform);
384 struct txx9aclc_soc_device *dev = 387 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
385 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
386 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
387 void __iomem *base = drvdata->base; 388 void __iomem *base = drvdata->base;
388 int i; 389 int i;
389 390
@@ -406,28 +407,46 @@ static int txx9aclc_pcm_remove(struct platform_device *pdev)
406 return 0; 407 return 0;
407} 408}
408 409
409struct snd_soc_platform txx9aclc_soc_platform = { 410static struct snd_soc_platform_driver txx9aclc_soc_platform = {
410 .name = "txx9aclc-audio",
411 .probe = txx9aclc_pcm_probe, 411 .probe = txx9aclc_pcm_probe,
412 .remove = txx9aclc_pcm_remove, 412 .remove = txx9aclc_pcm_remove,
413 .pcm_ops = &txx9aclc_pcm_ops, 413 .ops = &txx9aclc_pcm_ops,
414 .pcm_new = txx9aclc_pcm_new, 414 .pcm_new = txx9aclc_pcm_new,
415 .pcm_free = txx9aclc_pcm_free_dma_buffers, 415 .pcm_free = txx9aclc_pcm_free_dma_buffers,
416}; 416};
417EXPORT_SYMBOL_GPL(txx9aclc_soc_platform);
418 417
419static int __init txx9aclc_soc_platform_init(void) 418static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev)
420{ 419{
421 return snd_soc_register_platform(&txx9aclc_soc_platform); 420 return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform);
422} 421}
423 422
424static void __exit txx9aclc_soc_platform_exit(void) 423static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev)
425{ 424{
426 snd_soc_unregister_platform(&txx9aclc_soc_platform); 425 snd_soc_unregister_platform(&pdev->dev);
426 return 0;
427} 427}
428 428
429module_init(txx9aclc_soc_platform_init); 429static struct platform_driver txx9aclc_pcm_driver = {
430module_exit(txx9aclc_soc_platform_exit); 430 .driver = {
431 .name = "txx9aclc-pcm-audio",
432 .owner = THIS_MODULE,
433 },
434
435 .probe = txx9aclc_soc_platform_probe,
436 .remove = __devexit_p(txx9aclc_soc_platform_remove),
437};
438
439static int __init snd_txx9aclc_pcm_init(void)
440{
441 return platform_driver_register(&txx9aclc_pcm_driver);
442}
443module_init(snd_txx9aclc_pcm_init);
444
445static void __exit snd_txx9aclc_pcm_exit(void)
446{
447 platform_driver_unregister(&txx9aclc_pcm_driver);
448}
449module_exit(snd_txx9aclc_pcm_exit);
431 450
432MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); 451MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
433MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver"); 452MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h
index 6769aab41b33..9c2de84fec3b 100644
--- a/sound/soc/txx9/txx9aclc.h
+++ b/sound/soc/txx9/txx9aclc.h
@@ -65,19 +65,10 @@ struct txx9aclc_plat_drvdata {
65 u64 physbase; 65 u64 physbase;
66}; 66};
67 67
68struct txx9aclc_soc_device {
69 struct snd_soc_device soc_dev;
70 struct platform_device *aclc_pdev; /* for ioresources, drvdata */
71 struct txx9aclc_dmadata dmadata[2];
72};
73
74static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata( 68static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata(
75 struct txx9aclc_soc_device *sdev) 69 struct snd_soc_dai *dai)
76{ 70{
77 return platform_get_drvdata(sdev->aclc_pdev); 71 return dev_get_drvdata(dai->dev);
78} 72}
79 73
80extern struct snd_soc_platform txx9aclc_soc_platform;
81extern struct snd_soc_dai txx9aclc_ac97_dai;
82
83#endif /* __TXX9ACLC_H */ 74#endif /* __TXX9ACLC_H */