diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-04-24 16:33:10 +0100 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-04-24 17:39:38 +0100 |
commit | 172fd9e26200668ebaf3e1d6d09b36d5d531bfa6 (patch) | |
tree | 882a34484549fc258e0eca25dbf7588bcfb4fd13 /sound/soc/s3c24xx/s3c64xx-i2s.c | |
parent | 7629ad24f2b3df95c8b4cd8869e3c04e1df6c442 (diff) | |
download | blackbird-op-linux-172fd9e26200668ebaf3e1d6d09b36d5d531bfa6.tar.gz blackbird-op-linux-172fd9e26200668ebaf3e1d6d09b36d5d531bfa6.zip |
ASoC: Fix S3C64xx IIS device registration and support both ports
The S3C64xx IIS code had a number of problems with device registration.
The hardware has two IIS ports of which the driver supported only one
at once via a single exported DAI, attempting to identify the DAI to
use based on the dev->id of the ASoC platform device. As well as
limiting the driver to only supporting one IIS port at once this also
meant that the ID of the soc-audio device (or in future the card device)
had to match the IIS ID.
Fix both problems by converting the driver to register the DAIs based on
probing of platform devices registered by the arch/arm code, using those
platform devices to interact with the clock API.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/s3c24xx/s3c64xx-i2s.c')
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s.c | 146 |
1 files changed, 97 insertions, 49 deletions
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 33c5de7e255f..a84c4bec56b9 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c @@ -120,36 +120,8 @@ EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate); static int s3c64xx_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - struct device *dev = &pdev->dev; - struct s3c_i2sv2_info *i2s; - int ret; - - dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id); - - if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) { - dev_err(dev, "id %d out of range\n", pdev->id); - return -EINVAL; - } - - i2s = &s3c64xx_i2s[pdev->id]; - - ret = s3c_i2sv2_probe(pdev, dai, i2s, - pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0); - if (ret) - return ret; - - i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; - i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; - - i2s->iis_cclk = clk_get(dev, "audio-bus"); - if (IS_ERR(i2s->iis_cclk)) { - dev_err(dev, "failed to get audio-bus"); - iounmap(i2s->regs); - return -ENODEV; - } - /* configure GPIO for i2s port */ - switch (pdev->id) { + switch (dai->id) { case 0: s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); @@ -181,35 +153,114 @@ static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { .set_sysclk = s3c64xx_i2s_set_sysclk, }; -struct snd_soc_dai s3c64xx_i2s_dai = { - .name = "s3c64xx-i2s", - .id = 0, - .probe = s3c64xx_i2s_probe, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = S3C64XX_I2S_RATES, - .formats = S3C64XX_I2S_FMTS, +struct snd_soc_dai s3c64xx_i2s_dai[] = { + { + .name = "s3c64xx-i2s", + .id = 0, + .probe = s3c64xx_i2s_probe, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS, + }, + .ops = &s3c64xx_i2s_dai_ops, }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = S3C64XX_I2S_RATES, - .formats = S3C64XX_I2S_FMTS, + { + .name = "s3c64xx-i2s", + .id = 1, + .probe = s3c64xx_i2s_probe, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS, + }, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = S3C64XX_I2S_RATES, + .formats = S3C64XX_I2S_FMTS, + }, + .ops = &s3c64xx_i2s_dai_ops, }, - .ops = &s3c64xx_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); +static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) +{ + struct s3c_i2sv2_info *i2s; + struct snd_soc_dai *dai; + int ret; + + if (pdev->id >= ARRAY_SIZE(s3c64xx_i2s)) { + dev_err(&pdev->dev, "id %d out of range\n", pdev->id); + return -EINVAL; + } + + i2s = &s3c64xx_i2s[pdev->id]; + dai = &s3c64xx_i2s_dai[pdev->id]; + dai->dev = &pdev->dev; + + i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; + i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; + + i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); + if (IS_ERR(i2s->iis_cclk)) { + dev_err(&pdev->dev, "failed to get audio-bus"); + ret = PTR_ERR(i2s->iis_cclk); + goto err; + } + + ret = s3c_i2sv2_probe(pdev, dai, i2s, + dai->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0); + if (ret) + goto err_clk; + + ret = snd_soc_register_dai(dai); + if (ret != 0) + goto err_i2sv2; + + return 0; + +err_i2sv2: + /* Not implemented for I2Sv2 core yet */ +err_clk: + clk_put(i2s->iis_cclk); +err: + return ret; +} + +static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev) +{ + dev_err(&pdev->dev, "Device removal not yet supported\n"); + return 0; +} + +static struct platform_driver s3c64xx_iis_driver = { + .probe = s3c64xx_iis_dev_probe, + .remove = s3c64xx_iis_dev_remove, + .driver = { + .name = "s3c64xx-iis", + .owner = THIS_MODULE, + }, +}; + static int __init s3c64xx_i2s_init(void) { - return s3c_i2sv2_register_dai(&s3c64xx_i2s_dai); + return platform_driver_register(&s3c64xx_iis_driver); } module_init(s3c64xx_i2s_init); static void __exit s3c64xx_i2s_exit(void) { - snd_soc_unregister_dai(&s3c64xx_i2s_dai); + platform_driver_unregister(&s3c64xx_iis_driver); } module_exit(s3c64xx_i2s_exit); @@ -217,6 +268,3 @@ module_exit(s3c64xx_i2s_exit); MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); MODULE_LICENSE("GPL"); - - - |