.id = 1, /* on PSC1 */
};
+static struct platform_device db1200_audiodma_dev = {
+ .name = "au1xpsc-pcm",
+ .id = 1, /* PSC ID */
+};
+
static struct platform_device *db1200_devs[] __initdata = {
NULL, /* PSC0, selected by S6.8 */
&db1200_ide_dev,
&db1200_eth_dev,
&db1200_rtc_dev,
&db1200_nand_dev,
+ &db1200_audiodma_dev,
&db1200_audio_dev,
&db1200_stac_dev,
};
static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
{
+ struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int stype = SUBSTREAM_TYPE(substream), *dmaids;
+
+ dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ if (!dmaids)
+ return -ENODEV; /* whoa, has ordering changed? */
+
+ pcd->ddma_id = dmaids[stype];
+
snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware);
return 0;
}
static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
{
struct au1xpsc_audio_dmadata *dmadata;
- struct resource *r;
int ret;
dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
if (!dmadata)
return -ENOMEM;
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!r) {
- ret = -ENODEV;
- goto out1;
- }
- dmadata[PCM_TX].ddma_id = r->start;
-
- /* RX DMA */
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!r) {
- ret = -ENODEV;
- goto out1;
- }
- dmadata[PCM_RX].ddma_id = r->start;
-
platform_set_drvdata(pdev, dmadata);
ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
- if (!ret)
- return ret;
+ if (ret)
+ kfree(dmadata);
-out1:
- kfree(dmadata);
return ret;
}
module_init(au1xpsc_audio_dbdma_load);
module_exit(au1xpsc_audio_dbdma_unload);
-
-struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
-{
- struct resource *res, *r;
- struct platform_device *pd;
- int id[2];
- int ret;
-
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!r)
- return NULL;
- id[0] = r->start;
-
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!r)
- return NULL;
- id[1] = r->start;
-
- res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
- if (!res)
- return NULL;
-
- res[0].start = res[0].end = id[0];
- res[1].start = res[1].end = id[1];
- res[0].flags = res[1].flags = IORESOURCE_DMA;
-
- pd = platform_device_alloc("au1xpsc-pcm", pdev->id);
- if (!pd)
- goto out;
-
- pd->resource = res;
- pd->num_resources = 2;
-
- ret = platform_device_add(pd);
- if (!ret)
- return pd;
-
- platform_device_put(pd);
-out:
- kfree(res);
- return NULL;
-}
-EXPORT_SYMBOL_GPL(au1xpsc_pcm_add);
-
-void au1xpsc_pcm_destroy(struct platform_device *dmapd)
-{
- if (dmapd)
- platform_device_unregister(dmapd);
-}
-EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
MODULE_AUTHOR("Manuel Lauss");
return ret;
}
+static int au1xpsc_ac97_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
+ snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
+ return 0;
+}
+
static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
{
return au1xpsc_ac97_workdata ? 0 : -ENODEV;
}
static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
+ .startup = au1xpsc_ac97_startup,
.trigger = au1xpsc_ac97_trigger,
.hw_params = au1xpsc_ac97_hw_params,
};
if (!wd->mmio)
goto out1;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!r)
+ goto out2;
+ wd->dmaids[PCM_TX] = r->start;
+
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!r)
+ goto out2;
+ wd->dmaids[PCM_RX] = r->start;
+
/* configuration: max dma trigger threshold, enable ac97 */
wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
PSC_AC97CFG_DE_ENABLE;
ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
if (ret)
- goto out1;
+ goto out2;
- wd->dmapd = au1xpsc_pcm_add(pdev);
- if (wd->dmapd) {
- au1xpsc_ac97_workdata = wd;
- return 0;
- }
+ au1xpsc_ac97_workdata = wd;
+ return 0;
- snd_soc_unregister_dai(&pdev->dev);
+out2:
+ iounmap(wd->mmio);
out1:
release_mem_region(r->start, resource_size(r));
out0:
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (wd->dmapd)
- au1xpsc_pcm_destroy(wd->dmapd);
-
snd_soc_unregister_dai(&pdev->dev);
/* disable PSC completely */
return ret;
}
+static int au1xpsc_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
+ snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
+ return 0;
+}
+
static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
+ .startup = au1xpsc_i2s_startup,
.trigger = au1xpsc_i2s_trigger,
.hw_params = au1xpsc_i2s_hw_params,
.set_fmt = au1xpsc_i2s_set_fmt,
if (!wd->mmio)
goto out1;
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!r)
+ goto out2;
+ wd->dmaids[PCM_TX] = r->start;
+
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!r)
+ goto out2;
+ wd->dmaids[PCM_RX] = r->start;
+
/* preserve PSC clock source set up by platform (dev.platform_data
* is already occupied by soc layer)
*/
platform_set_drvdata(pdev, wd);
ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
- if (ret)
- goto out1;
-
- /* finally add the DMA device for this PSC */
- wd->dmapd = au1xpsc_pcm_add(pdev);
- if (wd->dmapd)
+ if (!ret)
return 0;
- snd_soc_unregister_dai(&pdev->dev);
+out2:
+ iounmap(wd->mmio);
out1:
release_mem_region(r->start, resource_size(r));
out0:
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (wd->dmapd)
- au1xpsc_pcm_destroy(wd->dmapd);
-
snd_soc_unregister_dai(&pdev->dev);
au_writel(0, I2S_CFG(wd));
#define SUBSTREAM_TYPE(substream) \
((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK ? PCM_TX : PCM_RX)
-/* PSC/DBDMA helpers */
-extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev);
-extern void au1xpsc_pcm_destroy(struct platform_device *dmapd);
-
struct au1xpsc_audio_data {
void __iomem *mmio;
unsigned long pm[2];
struct mutex lock;
int dmaids[2];
- struct platform_device *dmapd;
};
/* easy access macros */