ASoC: atmel-ssc-dai: register dai and pcm directly

change the method for register dai and pcm
  - let the atmel-ssc-dai no longer as a standalone platform device
  - remap ssc and then register dai directly
  - register pcm from dai directly
  - modify the code which related with this change

Signed-off-by: Bo Shen <voice.shen@atmel.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
Bo Shen 2012-11-14 18:09:09 +08:00 committed by Mark Brown
parent 099343c64e
commit be681a8275
4 changed files with 50 additions and 136 deletions

View file

@ -473,28 +473,17 @@ static struct snd_soc_platform_driver atmel_soc_platform = {
.resume = atmel_pcm_resume, .resume = atmel_pcm_resume,
}; };
static int __devinit atmel_soc_platform_probe(struct platform_device *pdev) int atmel_pcm_platform_register(struct device *dev)
{ {
return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform); return snd_soc_register_platform(dev, &atmel_soc_platform);
} }
EXPORT_SYMBOL(atmel_pcm_platform_register);
static int __devexit atmel_soc_platform_remove(struct platform_device *pdev) void atmel_pcm_platform_unregister(struct device *dev)
{ {
snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_platform(dev);
return 0;
} }
EXPORT_SYMBOL(atmel_pcm_platform_unregister);
static struct platform_driver atmel_pcm_driver = {
.driver = {
.name = "atmel-pcm-audio",
.owner = THIS_MODULE,
},
.probe = atmel_soc_platform_probe,
.remove = __devexit_p(atmel_soc_platform_remove),
};
module_platform_driver(atmel_pcm_driver);
MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
MODULE_DESCRIPTION("Atmel PCM module"); MODULE_DESCRIPTION("Atmel PCM module");

View file

@ -80,4 +80,7 @@ struct atmel_pcm_dma_params {
#define ssc_readx(base, reg) (__raw_readl((base) + (reg))) #define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg)) #define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
int atmel_pcm_platform_register(struct device *dev);
void atmel_pcm_platform_unregister(struct device *dev);
#endif /* _ATMEL_PCM_H */ #endif /* _ATMEL_PCM_H */

View file

@ -48,11 +48,7 @@
#include "atmel_ssc_dai.h" #include "atmel_ssc_dai.h"
#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
#define NUM_SSC_DEVICES 1
#else
#define NUM_SSC_DEVICES 3 #define NUM_SSC_DEVICES 3
#endif
/* /*
* SSC PDC registers required by the PCM DMA engine. * SSC PDC registers required by the PCM DMA engine.
@ -107,7 +103,6 @@ static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
.pdc = &pdc_rx_reg, .pdc = &pdc_rx_reg,
.mask = &ssc_rx_mask, .mask = &ssc_rx_mask,
} }, } },
#if NUM_SSC_DEVICES == 3
{{ {{
.name = "SSC1 PCM out", .name = "SSC1 PCM out",
.pdc = &pdc_tx_reg, .pdc = &pdc_tx_reg,
@ -128,7 +123,6 @@ static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
.pdc = &pdc_rx_reg, .pdc = &pdc_rx_reg,
.mask = &ssc_rx_mask, .mask = &ssc_rx_mask,
} }, } },
#endif
}; };
@ -139,7 +133,6 @@ static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
.dir_mask = SSC_DIR_MASK_UNUSED, .dir_mask = SSC_DIR_MASK_UNUSED,
.initialized = 0, .initialized = 0,
}, },
#if NUM_SSC_DEVICES == 3
{ {
.name = "ssc1", .name = "ssc1",
.lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock), .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
@ -152,7 +145,6 @@ static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
.dir_mask = SSC_DIR_MASK_UNUSED, .dir_mask = SSC_DIR_MASK_UNUSED,
.initialized = 0, .initialized = 0,
}, },
#endif
}; };
@ -690,27 +682,9 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
static int atmel_ssc_probe(struct snd_soc_dai *dai) static int atmel_ssc_probe(struct snd_soc_dai *dai)
{ {
struct atmel_ssc_info *ssc_p = &ssc_info[dai->id]; struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
int ret = 0;
snd_soc_dai_set_drvdata(dai, ssc_p); snd_soc_dai_set_drvdata(dai, ssc_p);
/*
* Request SSC device
*/
ssc_p->ssc = ssc_request(dai->id);
if (IS_ERR(ssc_p->ssc)) {
printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id);
ret = PTR_ERR(ssc_p->ssc);
}
return ret;
}
static int atmel_ssc_remove(struct snd_soc_dai *dai)
{
struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai);
ssc_free(ssc_p->ssc);
return 0; return 0;
} }
@ -728,11 +702,8 @@ static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
.set_clkdiv = atmel_ssc_set_dai_clkdiv, .set_clkdiv = atmel_ssc_set_dai_clkdiv,
}; };
static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = { static struct snd_soc_dai_driver atmel_ssc_dai = {
{
.name = "atmel-ssc-dai.0",
.probe = atmel_ssc_probe, .probe = atmel_ssc_probe,
.remove = atmel_ssc_remove,
.suspend = atmel_ssc_suspend, .suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume, .resume = atmel_ssc_resume,
.playback = { .playback = {
@ -746,69 +717,37 @@ static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
.rates = ATMEL_SSC_RATES, .rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,}, .formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops, .ops = &atmel_ssc_dai_ops,
},
#if NUM_SSC_DEVICES == 3
{
.name = "atmel-ssc-dai.1",
.probe = atmel_ssc_probe,
.remove = atmel_ssc_remove,
.suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume,
.playback = {
.channels_min = 1,
.channels_max = 2,
.rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,},
.capture = {
.channels_min = 1,
.channels_max = 2,
.rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops,
},
{
.name = "atmel-ssc-dai.2",
.probe = atmel_ssc_probe,
.remove = atmel_ssc_remove,
.suspend = atmel_ssc_suspend,
.resume = atmel_ssc_resume,
.playback = {
.channels_min = 1,
.channels_max = 2,
.rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,},
.capture = {
.channels_min = 1,
.channels_max = 2,
.rates = ATMEL_SSC_RATES,
.formats = ATMEL_SSC_FORMATS,},
.ops = &atmel_ssc_dai_ops,
},
#endif
}; };
static __devinit int asoc_ssc_probe(struct platform_device *pdev) static int asoc_ssc_init(struct device *dev)
{ {
BUG_ON(pdev->id < 0); int ret;
BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai));
return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]); ret = snd_soc_register_dai(dev, &atmel_ssc_dai);
} if (ret) {
dev_err(dev, "Could not register DAI: %d\n", ret);
goto err;
}
ret = atmel_pcm_platform_register(dev);
if (ret) {
dev_err(dev, "Could not register PCM: %d\n", ret);
goto err_unregister_dai;
};
static int __devexit asoc_ssc_remove(struct platform_device *pdev)
{
snd_soc_unregister_dai(&pdev->dev);
return 0; return 0;
err_unregister_dai:
snd_soc_unregister_dai(dev);
err:
return ret;
} }
static struct platform_driver asoc_ssc_driver = { static void asoc_ssc_exit(struct device *dev)
.driver = { {
.name = "atmel-ssc-dai", atmel_pcm_platform_unregister(dev);
.owner = THIS_MODULE, snd_soc_unregister_dai(dev);
}, }
.probe = asoc_ssc_probe,
.remove = __devexit_p(asoc_ssc_remove),
};
/** /**
* atmel_ssc_set_audio - Allocate the specified SSC for audio use. * atmel_ssc_set_audio - Allocate the specified SSC for audio use.
@ -816,50 +755,32 @@ static struct platform_driver asoc_ssc_driver = {
int atmel_ssc_set_audio(int ssc_id) int atmel_ssc_set_audio(int ssc_id)
{ {
struct ssc_device *ssc; struct ssc_device *ssc;
static struct platform_device *dma_pdev;
struct platform_device *ssc_pdev;
int ret; int ret;
if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai))
return -EINVAL;
/* Allocate a dummy device for DMA if we don't have one already */
if (!dma_pdev) {
dma_pdev = platform_device_alloc("atmel-pcm-audio", -1);
if (!dma_pdev)
return -ENOMEM;
ret = platform_device_add(dma_pdev);
if (ret < 0) {
platform_device_put(dma_pdev);
dma_pdev = NULL;
return ret;
}
}
ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id);
if (!ssc_pdev)
return -ENOMEM;
/* If we can grab the SSC briefly to parent the DAI device off it */ /* If we can grab the SSC briefly to parent the DAI device off it */
ssc = ssc_request(ssc_id); ssc = ssc_request(ssc_id);
if (IS_ERR(ssc)) if (IS_ERR(ssc)) {
pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n", pr_err("Unable to parent ASoC SSC DAI on SSC: %ld\n",
PTR_ERR(ssc)); PTR_ERR(ssc));
else { return PTR_ERR(ssc);
ssc_pdev->dev.parent = &(ssc->pdev->dev); } else {
ssc_free(ssc); ssc_info[ssc_id].ssc = ssc;
} }
ret = platform_device_add(ssc_pdev); ret = asoc_ssc_init(&ssc->pdev->dev);
if (ret < 0)
platform_device_put(ssc_pdev);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(atmel_ssc_set_audio); EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
module_platform_driver(asoc_ssc_driver); void atmel_ssc_put_audio(int ssc_id)
{
struct ssc_device *ssc = ssc_info[ssc_id].ssc;
ssc_free(ssc);
asoc_ssc_exit(&ssc->pdev->dev);
}
EXPORT_SYMBOL_GPL(atmel_ssc_put_audio);
/* Module information */ /* Module information */
MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");

View file

@ -117,6 +117,7 @@ struct atmel_ssc_info {
struct atmel_ssc_state ssc_state; struct atmel_ssc_state ssc_state;
}; };
int atmel_ssc_set_audio(int ssc); int atmel_ssc_set_audio(int ssc_id);
void atmel_ssc_put_audio(int ssc_id);
#endif /* _AT91_SSC_DAI_H */ #endif /* _AT91_SSC_DAI_H */