Commit ffc4fdbb authored by Manuel Lauss's avatar Manuel Lauss Committed by Mark Brown

ASoC: fix au1x platform

This patch fixes up the au1x audio platform after the multi-component
merge:
- compile fixes and updates to get DB1200 platform audio working again,
- removal of global variables in AC97/I2S/DMA(PCM) modules.

The AC97 part is limited to one instance only for now due to issues
with getting at driver data in the soc_ac97_ops.
Signed-off-by: default avatarManuel Lauss <manuel.lauss@googlemail.com>
Acked-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 0bb5f267
...@@ -429,6 +429,11 @@ static struct platform_device db1200_audio_dev = { ...@@ -429,6 +429,11 @@ static struct platform_device db1200_audio_dev = {
.resource = au1200_psc1_res, .resource = au1200_psc1_res,
}; };
static struct platform_device db1200_stac_dev = {
.name = "ac97-codec",
.id = 1, /* on PSC1 */
};
static struct platform_device *db1200_devs[] __initdata = { static struct platform_device *db1200_devs[] __initdata = {
NULL, /* PSC0, selected by S6.8 */ NULL, /* PSC0, selected by S6.8 */
&db1200_ide_dev, &db1200_ide_dev,
...@@ -436,6 +441,7 @@ static struct platform_device *db1200_devs[] __initdata = { ...@@ -436,6 +441,7 @@ static struct platform_device *db1200_devs[] __initdata = {
&db1200_rtc_dev, &db1200_rtc_dev,
&db1200_nand_dev, &db1200_nand_dev,
&db1200_audio_dev, &db1200_audio_dev,
&db1200_stac_dev,
}; };
static int __init db1200_dev_init(void) static int __init db1200_dev_init(void)
......
...@@ -27,10 +27,10 @@ ...@@ -27,10 +27,10 @@
static struct snd_soc_dai_link db1200_ac97_dai = { static struct snd_soc_dai_link db1200_ac97_dai = {
.name = "AC97", .name = "AC97",
.stream_name = "AC97 HiFi", .stream_name = "AC97 HiFi",
.cpu_dai_name = "au1xpsc-ac97",
.codec_dai_name = "ac97-hifi", .codec_dai_name = "ac97-hifi",
.platform_name = "au1xpsc-pcm-audio", .cpu_dai_name = "au1xpsc_ac97.1",
.codec_name = "ac97-codec", .platform_name = "au1xpsc-pcm.1",
.codec_name = "ac97-codec.1",
}; };
static struct snd_soc_card db1200_ac97_machine = { static struct snd_soc_card db1200_ac97_machine = {
...@@ -75,10 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = { ...@@ -75,10 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = {
static struct snd_soc_dai_link db1200_i2s_dai = { static struct snd_soc_dai_link db1200_i2s_dai = {
.name = "WM8731", .name = "WM8731",
.stream_name = "WM8731 PCM", .stream_name = "WM8731 PCM",
.cpu_dai_name = "au1xpsc", .codec_dai_name = "wm8731-hifi",
.codec_dai_name = "wm8731-hifi" .cpu_dai_name = "au1xpsc_i2s.1",
.platform_name = "au1xpsc-pcm-audio", .platform_name = "au1xpsc-pcm.1",
.codec_name = "wm8731-codec.0-001a", .codec_name = "wm8731-codec.0-001b",
.ops = &db1200_i2s_wm8731_ops, .ops = &db1200_i2s_wm8731_ops,
}; };
...@@ -97,7 +97,7 @@ static int __init db1200_audio_load(void) ...@@ -97,7 +97,7 @@ static int __init db1200_audio_load(void)
int ret; int ret;
ret = -ENOMEM; ret = -ENOMEM;
db1200_asoc_dev = platform_device_alloc("soc-audio", -1); db1200_asoc_dev = platform_device_alloc("soc-audio", 1); /* PSC1 */
if (!db1200_asoc_dev) if (!db1200_asoc_dev)
goto out; goto out;
......
...@@ -10,9 +10,6 @@ ...@@ -10,9 +10,6 @@
* *
* DMA glue for Au1x-PSC audio. * DMA glue for Au1x-PSC audio.
* *
* NOTE: all of these drivers can only work with a SINGLE instance
* of a PSC. Multiple independent audio devices are impossible
* with ASoC v1.
*/ */
...@@ -61,9 +58,6 @@ struct au1xpsc_audio_dmadata { ...@@ -61,9 +58,6 @@ struct au1xpsc_audio_dmadata {
int msbits; int msbits;
}; };
/* instance data. There can be only one, MacLeod!!!! */
static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2];
/* /*
* These settings are somewhat okay, at least on my machine audio plays * These settings are somewhat okay, at least on my machine audio plays
* almost skip-free. Especially the 64kB buffer seems to help a LOT. * almost skip-free. Especially the 64kB buffer seems to help a LOT.
...@@ -199,6 +193,14 @@ static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd, ...@@ -199,6 +193,14 @@ static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd,
return 0; return 0;
} }
static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss)
{
struct snd_soc_pcm_runtime *rtd = ss->private_data;
struct au1xpsc_audio_dmadata *pcd =
snd_soc_platform_get_drvdata(rtd->platform);
return &pcd[SUBSTREAM_TYPE(ss)];
}
static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
...@@ -211,7 +213,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, ...@@ -211,7 +213,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
goto out; goto out;
stype = SUBSTREAM_TYPE(substream); stype = SUBSTREAM_TYPE(substream);
pcd = au1xpsc_audio_pcmdma[stype]; pcd = to_dmadata(substream);
DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
"runtime->min_align %d\n", "runtime->min_align %d\n",
...@@ -249,8 +251,7 @@ static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream) ...@@ -249,8 +251,7 @@ static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream)
static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
{ {
struct au1xpsc_audio_dmadata *pcd = struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream);
au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)];
au1xxx_dbdma_reset(pcd->ddma_chan); au1xxx_dbdma_reset(pcd->ddma_chan);
...@@ -267,7 +268,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) ...@@ -267,7 +268,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{ {
u32 c = au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->ddma_chan; u32 c = to_dmadata(substream)->ddma_chan;
switch (cmd) { switch (cmd) {
case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_START:
...@@ -287,8 +288,7 @@ static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ...@@ -287,8 +288,7 @@ static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static snd_pcm_uframes_t static snd_pcm_uframes_t
au1xpsc_pcm_pointer(struct snd_pcm_substream *substream) au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
{ {
return bytes_to_frames(substream->runtime, return bytes_to_frames(substream->runtime, to_dmadata(substream)->pos);
au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->pos);
} }
static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
...@@ -299,7 +299,7 @@ static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) ...@@ -299,7 +299,7 @@ static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) static int au1xpsc_pcm_close(struct snd_pcm_substream *substream)
{ {
au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]); au1x_pcm_dbdma_free(to_dmadata(substream));
return 0; return 0;
} }
...@@ -329,35 +329,21 @@ static int au1xpsc_pcm_new(struct snd_card *card, ...@@ -329,35 +329,21 @@ static int au1xpsc_pcm_new(struct snd_card *card,
return 0; return 0;
} }
static int au1xpsc_pcm_probe(struct snd_soc_platform *platform)
{
if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
return -ENODEV;
return 0;
}
/* au1xpsc audio platform */ /* au1xpsc audio platform */
struct snd_soc_platform_driver au1xpsc_soc_platform = { struct snd_soc_platform_driver au1xpsc_soc_platform = {
.probe = au1xpsc_pcm_probe,
.ops = &au1xpsc_pcm_ops, .ops = &au1xpsc_pcm_ops,
.pcm_new = au1xpsc_pcm_new, .pcm_new = au1xpsc_pcm_new,
.pcm_free = au1xpsc_pcm_free_dma_buffers, .pcm_free = au1xpsc_pcm_free_dma_buffers,
}; };
EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
{ {
struct au1xpsc_audio_dmadata *dmadata;
struct resource *r; struct resource *r;
int ret; int ret;
if (au1xpsc_audio_pcmdma[PCM_TX] || au1xpsc_audio_pcmdma[PCM_RX]) dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
return -EBUSY; if (!dmadata)
/* TX DMA */
au1xpsc_audio_pcmdma[PCM_TX]
= kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
if (!au1xpsc_audio_pcmdma[PCM_TX])
return -ENOMEM; return -ENOMEM;
r = platform_get_resource(pdev, IORESOURCE_DMA, 0); r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
...@@ -365,54 +351,40 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) ...@@ -365,54 +351,40 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
ret = -ENODEV; ret = -ENODEV;
goto out1; goto out1;
} }
(au1xpsc_audio_pcmdma[PCM_TX])->ddma_id = r->start; dmadata[PCM_TX].ddma_id = r->start;
/* RX DMA */ /* RX DMA */
au1xpsc_audio_pcmdma[PCM_RX]
= kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
if (!au1xpsc_audio_pcmdma[PCM_RX])
return -ENOMEM;
r = platform_get_resource(pdev, IORESOURCE_DMA, 1); r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (!r) { if (!r) {
ret = -ENODEV; ret = -ENODEV;
goto out2; goto out1;
} }
(au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; dmadata[PCM_RX].ddma_id = r->start;
platform_set_drvdata(pdev, dmadata);
ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
if (!ret) if (!ret)
return ret; return ret;
out2:
kfree(au1xpsc_audio_pcmdma[PCM_RX]);
au1xpsc_audio_pcmdma[PCM_RX] = NULL;
out1: out1:
kfree(au1xpsc_audio_pcmdma[PCM_TX]); kfree(dmadata);
au1xpsc_audio_pcmdma[PCM_TX] = NULL;
return ret; return ret;
} }
static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
{ {
int i; struct au1xpsc_audio_dmadata *dmadata = platform_get_drvdata(pdev);
snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_platform(&pdev->dev);
kfree(dmadata);
for (i = 0; i < 2; i++) {
if (au1xpsc_audio_pcmdma[i]) {
au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
kfree(au1xpsc_audio_pcmdma[i]);
au1xpsc_audio_pcmdma[i] = NULL;
}
}
return 0; return 0;
} }
static struct platform_driver au1xpsc_pcm_driver = { static struct platform_driver au1xpsc_pcm_driver = {
.driver = { .driver = {
.name = "au1xpsc-pcm-audio", .name = "au1xpsc-pcm",
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = au1xpsc_pcm_drvprobe, .probe = au1xpsc_pcm_drvprobe,
...@@ -421,8 +393,6 @@ static struct platform_driver au1xpsc_pcm_driver = { ...@@ -421,8 +393,6 @@ static struct platform_driver au1xpsc_pcm_driver = {
static int __init au1xpsc_audio_dbdma_load(void) static int __init au1xpsc_audio_dbdma_load(void)
{ {
au1xpsc_audio_pcmdma[PCM_TX] = NULL;
au1xpsc_audio_pcmdma[PCM_RX] = NULL;
return platform_driver_register(&au1xpsc_pcm_driver); return platform_driver_register(&au1xpsc_pcm_driver);
} }
...@@ -460,7 +430,7 @@ struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev) ...@@ -460,7 +430,7 @@ struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
res[1].start = res[1].end = id[1]; res[1].start = res[1].end = id[1];
res[0].flags = res[1].flags = IORESOURCE_DMA; res[0].flags = res[1].flags = IORESOURCE_DMA;
pd = platform_device_alloc("au1xpsc-pcm", -1); pd = platform_device_alloc("au1xpsc-pcm", pdev->id);
if (!pd) if (!pd)
goto out; goto out;
......
...@@ -10,9 +10,6 @@ ...@@ -10,9 +10,6 @@
* *
* Au1xxx-PSC AC97 glue. * Au1xxx-PSC AC97 glue.
* *
* NOTE: all of these drivers can only work with a SINGLE instance
* of a PSC. Multiple independent audio devices are impossible
* with ASoC v1.
*/ */
#include <linux/init.h> #include <linux/init.h>
...@@ -56,12 +53,29 @@ ...@@ -56,12 +53,29 @@
/* instance data. There can be only one, MacLeod!!!! */ /* instance data. There can be only one, MacLeod!!!! */
static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
#if 0
/* this could theoretically work, but ac97->bus->card->private_data can be NULL
* when snd_ac97_mixer() is called; I don't know if the rest further down the
* chain are always valid either.
*/
static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x)
{
struct snd_soc_card *c = x->bus->card->private_data;
return snd_soc_dai_get_drvdata(c->rtd->cpu_dai);
}
#else
#define ac97_to_pscdata(x) au1xpsc_ac97_workdata
#endif
/* AC97 controller reads codec register */ /* AC97 controller reads codec register */
static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
unsigned short reg) unsigned short reg)
{ {
/* FIXME */ struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
unsigned short retry, tmo; unsigned short retry, tmo;
unsigned long data; unsigned long data;
...@@ -102,8 +116,7 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, ...@@ -102,8 +116,7 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
unsigned short val) unsigned short val)
{ {
/* FIXME */ struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
unsigned int tmo, retry; unsigned int tmo, retry;
au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
...@@ -134,8 +147,7 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, ...@@ -134,8 +147,7 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
/* AC97 controller asserts a warm reset */ /* AC97 controller asserts a warm reset */
static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
{ {
/* FIXME */ struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata)); au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
au_sync(); au_sync();
...@@ -146,8 +158,7 @@ static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) ...@@ -146,8 +158,7 @@ static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
{ {
/* FIXME */ struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
int i; int i;
/* disable PSC during cold reset */ /* disable PSC during cold reset */
...@@ -202,8 +213,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, ...@@ -202,8 +213,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
/* FIXME */ struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
unsigned long r, ro, stat; unsigned long r, ro, stat;
int chans, t, stype = SUBSTREAM_TYPE(substream); int chans, t, stype = SUBSTREAM_TYPE(substream);
...@@ -283,8 +293,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, ...@@ -283,8 +293,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai) int cmd, struct snd_soc_dai *dai)
{ {
/* FIXME */ struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
int ret, stype = SUBSTREAM_TYPE(substream); int ret, stype = SUBSTREAM_TYPE(substream);
ret = 0; ret = 0;
...@@ -325,7 +334,7 @@ static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { ...@@ -325,7 +334,7 @@ static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
.hw_params = au1xpsc_ac97_hw_params, .hw_params = au1xpsc_ac97_hw_params,
}; };
struct snd_soc_dai_driver au1xpsc_ac97_dai = { static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
.ac97_control = 1, .ac97_control = 1,
.probe = au1xpsc_ac97_probe, .probe = au1xpsc_ac97_probe,
.playback = { .playback = {
...@@ -342,7 +351,6 @@ struct snd_soc_dai_driver au1xpsc_ac97_dai = { ...@@ -342,7 +351,6 @@ struct snd_soc_dai_driver au1xpsc_ac97_dai = {
}, },
.ops = &au1xpsc_ac97_dai_ops, .ops = &au1xpsc_ac97_dai_ops,
}; };
EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
{ {
...@@ -351,9 +359,6 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) ...@@ -351,9 +359,6 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
unsigned long sel; unsigned long sel;
struct au1xpsc_audio_data *wd; struct au1xpsc_audio_data *wd;
if (au1xpsc_ac97_workdata)
return -EBUSY;
wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
if (!wd) if (!wd)
return -ENOMEM; return -ENOMEM;
...@@ -387,14 +392,20 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) ...@@ -387,14 +392,20 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
au_sync(); au_sync();
ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_ac97_dai); /* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */
memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template,
sizeof(struct snd_soc_dai_driver));
wd->dai_drv.name = dev_name(&pdev->dev);
platform_set_drvdata(pdev, wd);
ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
if (ret) if (ret)
goto out1; goto out1;
wd->dmapd = au1xpsc_pcm_add(pdev); wd->dmapd = au1xpsc_pcm_add(pdev);
if (wd->dmapd) { if (wd->dmapd) {
platform_set_drvdata(pdev, wd); au1xpsc_ac97_workdata = wd;
au1xpsc_ac97_workdata = wd; /* MDEV */
return 0; return 0;
} }
...@@ -477,7 +488,7 @@ static struct dev_pm_ops au1xpscac97_pmops = { ...@@ -477,7 +488,7 @@ static struct dev_pm_ops au1xpscac97_pmops = {
static struct platform_driver au1xpsc_ac97_driver = { static struct platform_driver au1xpsc_ac97_driver = {
.driver = { .driver = {
.name = "au1xpsc-ac97", .name = "au1xpsc_ac97",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = AU1XPSCAC97_PMOPS, .pm = AU1XPSCAC97_PMOPS,
}, },
......
...@@ -10,9 +10,6 @@ ...@@ -10,9 +10,6 @@
* *
* Au1xxx-PSC I2S glue. * Au1xxx-PSC I2S glue.
* *
* NOTE: all of these drivers can only work with a SINGLE instance
* of a PSC. Multiple independent audio devices are impossible
* with ASoC v1.
* NOTE: so far only PSC slave mode (bit- and frameclock) is supported. * NOTE: so far only PSC slave mode (bit- and frameclock) is supported.
*/ */
...@@ -54,13 +51,10 @@ ...@@ -54,13 +51,10 @@
((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC) ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
/* instance data. There can be only one, MacLeod!!!! */
static struct au1xpsc_audio_data *au1xpsc_i2s_workdata;
static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt) unsigned int fmt)
{ {
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(cpu_dai);
unsigned long ct; unsigned long ct;
int ret; int ret;
...@@ -120,7 +114,7 @@ static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream, ...@@ -120,7 +114,7 @@ static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
int cfgbits; int cfgbits;
unsigned long stat; unsigned long stat;
...@@ -245,7 +239,7 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype) ...@@ -245,7 +239,7 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
int ret, stype = SUBSTREAM_TYPE(substream); int ret, stype = SUBSTREAM_TYPE(substream);
switch (cmd) { switch (cmd) {
...@@ -263,19 +257,13 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -263,19 +257,13 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret; return ret;
} }
static int au1xpsc_i2s_probe(struct snd_soc_dai *dai)
{
return au1xpsc_i2s_workdata ? 0 : -ENODEV;
}
static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
.trigger = au1xpsc_i2s_trigger, .trigger = au1xpsc_i2s_trigger,
.hw_params = au1xpsc_i2s_hw_params, .hw_params = au1xpsc_i2s_hw_params,
.set_fmt = au1xpsc_i2s_set_fmt, .set_fmt = au1xpsc_i2s_set_fmt,
}; };
static struct snd_soc_dai_driver au1xpsc_i2s_dai = { static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
.probe = au1xpsc_i2s_probe,
.playback = { .playback = {
.rates = AU1XPSC_I2S_RATES, .rates = AU1XPSC_I2S_RATES,
.formats = AU1XPSC_I2S_FMTS, .formats = AU1XPSC_I2S_FMTS,
...@@ -298,9 +286,6 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) ...@@ -298,9 +286,6 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
int ret; int ret;
struct au1xpsc_audio_data *wd; struct au1xpsc_audio_data *wd;
if (au1xpsc_i2s_workdata)
return -EBUSY;
wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
if (!wd) if (!wd)
return -ENOMEM; return -ENOMEM;
...@@ -337,17 +322,21 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) ...@@ -337,17 +322,21 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
* time out. * time out.
*/ */
ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_i2s_dai); /* name the DAI like this device instance ("au1xpsc-i2s.PSCINDEX") */
memcpy(&wd->dai_drv, &au1xpsc_i2s_dai_template,
sizeof(struct snd_soc_dai_driver));
wd->dai_drv.name = dev_name(&pdev->dev);
platform_set_drvdata(pdev, wd);
ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
if (ret) if (ret)
goto out1; goto out1;
/* finally add the DMA device for this PSC */ /* finally add the DMA device for this PSC */
wd->dmapd = au1xpsc_pcm_add(pdev); wd->dmapd = au1xpsc_pcm_add(pdev);
if (wd->dmapd) { if (wd->dmapd)
platform_set_drvdata(pdev, wd);
au1xpsc_i2s_workdata = wd;
return 0; return 0;
}
snd_soc_unregister_dai(&pdev->dev); snd_soc_unregister_dai(&pdev->dev);
out1: out1:
...@@ -376,8 +365,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) ...@@ -376,8 +365,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
release_mem_region(r->start, resource_size(r)); release_mem_region(r->start, resource_size(r));
kfree(wd); kfree(wd);
au1xpsc_i2s_workdata = NULL; /* MDEV */
return 0; return 0;
} }
...@@ -427,7 +414,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = { ...@@ -427,7 +414,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = {
static struct platform_driver au1xpsc_i2s_driver = { static struct platform_driver au1xpsc_i2s_driver = {
.driver = { .driver = {
.name = "au1xpsc", .name = "au1xpsc_i2s",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = AU1XPSCI2S_PMOPS, .pm = AU1XPSCI2S_PMOPS,
}, },
...@@ -437,7 +424,6 @@ static struct platform_driver au1xpsc_i2s_driver = { ...@@ -437,7 +424,6 @@ static struct platform_driver au1xpsc_i2s_driver = {
static int __init au1xpsc_i2s_load(void) static int __init au1xpsc_i2s_load(void)
{ {
au1xpsc_i2s_workdata = NULL;
return platform_driver_register(&au1xpsc_i2s_driver); return platform_driver_register(&au1xpsc_i2s_driver);
} }
......
...@@ -8,16 +8,11 @@ ...@@ -8,16 +8,11 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
* *
* NOTE: all of these drivers can only work with a SINGLE instance
* of a PSC. Multiple independent audio devices are impossible
* with ASoC v1.
*/ */
#ifndef _AU1X_PCM_H #ifndef _AU1X_PCM_H
#define _AU1X_PCM_H #define _AU1X_PCM_H
extern struct snd_ac97_bus_ops soc_ac97_ops;
/* DBDMA helpers */ /* DBDMA helpers */
extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev); extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev);
extern void au1xpsc_pcm_destroy(struct platform_device *dmapd); extern void au1xpsc_pcm_destroy(struct platform_device *dmapd);
...@@ -28,6 +23,8 @@ struct au1xpsc_audio_data { ...@@ -28,6 +23,8 @@ struct au1xpsc_audio_data {
unsigned long cfg; unsigned long cfg;
unsigned long rate; unsigned long rate;
struct snd_soc_dai_driver dai_drv;
unsigned long pm[2]; unsigned long pm[2];
struct mutex lock; struct mutex lock;
struct platform_device *dmapd; struct platform_device *dmapd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment