diff options
Diffstat (limited to 'sound/soc/mxs')
-rw-r--r-- | sound/soc/mxs/mxs-pcm.c | 24 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-pcm.h | 3 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-saif.c | 92 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-saif.h | 1 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-sgtl5000.c | 50 |
5 files changed, 116 insertions, 54 deletions
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index e373fbb..373dec9 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -220,28 +220,16 @@ static struct snd_soc_platform_driver mxs_soc_platform = { .pcm_free = mxs_pcm_free, }; -static int __devinit mxs_soc_platform_probe(struct platform_device *pdev) +int __devinit mxs_pcm_platform_register(struct device *dev) { - return snd_soc_register_platform(&pdev->dev, &mxs_soc_platform); + return snd_soc_register_platform(dev, &mxs_soc_platform); } +EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); -static int __devexit mxs_soc_platform_remove(struct platform_device *pdev) +void __devexit mxs_pcm_platform_unregister(struct device *dev) { - snd_soc_unregister_platform(&pdev->dev); - - return 0; + snd_soc_unregister_platform(dev); } - -static struct platform_driver mxs_pcm_driver = { - .driver = { - .name = "mxs-pcm-audio", - .owner = THIS_MODULE, - }, - .probe = mxs_soc_platform_probe, - .remove = __devexit_p(mxs_soc_platform_remove), -}; - -module_platform_driver(mxs_pcm_driver); +EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:mxs-pcm-audio"); diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h index 5f01a91..35ba2ca 100644 --- a/sound/soc/mxs/mxs-pcm.h +++ b/sound/soc/mxs/mxs-pcm.h @@ -24,4 +24,7 @@ struct mxs_pcm_dma_params { int chan_num; }; +int mxs_pcm_platform_register(struct device *dev); +void mxs_pcm_platform_unregister(struct device *dev); + #endif diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 7fd224b..aba71bf 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -18,6 +18,8 @@ #include <linux/module.h> #include <linux/init.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/dma-mapping.h> @@ -621,37 +623,57 @@ static irqreturn_t mxs_saif_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int mxs_saif_probe(struct platform_device *pdev) +static int __devinit mxs_saif_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct resource *iores, *dmares; struct mxs_saif *saif; struct mxs_saif_platform_data *pdata; struct pinctrl *pinctrl; int ret = 0; - if (pdev->id >= ARRAY_SIZE(mxs_saif)) + + if (!np && pdev->id >= ARRAY_SIZE(mxs_saif)) return -EINVAL; saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL); if (!saif) return -ENOMEM; - mxs_saif[pdev->id] = saif; - saif->id = pdev->id; - - pdata = pdev->dev.platform_data; - if (pdata && !pdata->master_mode) { - saif->master_id = pdata->master_id; - if (saif->master_id < 0 || - saif->master_id >= ARRAY_SIZE(mxs_saif) || - saif->master_id == saif->id) { - dev_err(&pdev->dev, "get wrong master id\n"); - return -EINVAL; + if (np) { + struct device_node *master; + saif->id = of_alias_get_id(np, "saif"); + if (saif->id < 0) + return saif->id; + /* + * If there is no "fsl,saif-master" phandle, it's a saif + * master. Otherwise, it's a slave and its phandle points + * to the master. + */ + master = of_parse_phandle(np, "fsl,saif-master", 0); + if (!master) { + saif->master_id = saif->id; + } else { + saif->master_id = of_alias_get_id(master, "saif"); + if (saif->master_id < 0) + return saif->master_id; } } else { - saif->master_id = saif->id; + saif->id = pdev->id; + pdata = pdev->dev.platform_data; + if (pdata && !pdata->master_mode) + saif->master_id = pdata->master_id; + else + saif->master_id = saif->id; + } + + if (saif->master_id < 0 || saif->master_id >= ARRAY_SIZE(mxs_saif)) { + dev_err(&pdev->dev, "get wrong master id\n"); + return -EINVAL; } + mxs_saif[saif->id] = saif; + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(pinctrl)) { ret = PTR_ERR(pinctrl); @@ -677,12 +699,19 @@ static int mxs_saif_probe(struct platform_device *pdev) dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!dmares) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to get dma resource: %d\n", - ret); - goto failed_get_resource; + /* + * TODO: This is a temporary solution and should be changed + * to use generic DMA binding later when the helplers get in. + */ + ret = of_property_read_u32(np, "fsl,saif-dma-channel", + &saif->dma_param.chan_num); + if (ret) { + dev_err(&pdev->dev, "failed to get dma channel\n"); + goto failed_get_resource; + } + } else { + saif->dma_param.chan_num = dmares->start; } - saif->dma_param.chan_num = dmares->start; saif->irq = platform_get_irq(pdev, 0); if (saif->irq < 0) { @@ -716,24 +745,14 @@ static int mxs_saif_probe(struct platform_device *pdev) goto failed_get_resource; } - saif->soc_platform_pdev = platform_device_alloc( - "mxs-pcm-audio", pdev->id); - if (!saif->soc_platform_pdev) { - ret = -ENOMEM; - goto failed_pdev_alloc; - } - - platform_set_drvdata(saif->soc_platform_pdev, saif); - ret = platform_device_add(saif->soc_platform_pdev); + ret = mxs_pcm_platform_register(&pdev->dev); if (ret) { - dev_err(&pdev->dev, "failed to add soc platform device\n"); - goto failed_pdev_add; + dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + goto failed_pdev_alloc; } return 0; -failed_pdev_add: - platform_device_put(saif->soc_platform_pdev); failed_pdev_alloc: snd_soc_unregister_dai(&pdev->dev); failed_get_resource: @@ -746,13 +765,19 @@ static int __devexit mxs_saif_remove(struct platform_device *pdev) { struct mxs_saif *saif = platform_get_drvdata(pdev); - platform_device_unregister(saif->soc_platform_pdev); + mxs_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_dai(&pdev->dev); clk_put(saif->clk); return 0; } +static const struct of_device_id mxs_saif_dt_ids[] = { + { .compatible = "fsl,imx28-saif", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_saif_dt_ids); + static struct platform_driver mxs_saif_driver = { .probe = mxs_saif_probe, .remove = __devexit_p(mxs_saif_remove), @@ -760,6 +785,7 @@ static struct platform_driver mxs_saif_driver = { .driver = { .name = "mxs-saif", .owner = THIS_MODULE, + .of_match_table = mxs_saif_dt_ids, }, }; diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h index 12c91e4..3cb342e 100644 --- a/sound/soc/mxs/mxs-saif.h +++ b/sound/soc/mxs/mxs-saif.h @@ -123,7 +123,6 @@ struct mxs_saif { unsigned int cur_rate; unsigned int ongoing; - struct platform_device *soc_platform_pdev; u32 fifo_underrun; u32 fifo_overrun; }; diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 60f052b..3e6e876 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -18,6 +18,8 @@ #include <linux/module.h> #include <linux/device.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> @@ -90,7 +92,7 @@ static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { .codec_dai_name = "sgtl5000", .codec_name = "sgtl5000.0-000a", .cpu_dai_name = "mxs-saif.0", - .platform_name = "mxs-pcm-audio.0", + .platform_name = "mxs-saif.0", .ops = &mxs_sgtl5000_hifi_ops, }, { .name = "HiFi Rx", @@ -98,7 +100,7 @@ static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { .codec_dai_name = "sgtl5000", .codec_name = "sgtl5000.0-000a", .cpu_dai_name = "mxs-saif.1", - .platform_name = "mxs-pcm-audio.1", + .platform_name = "mxs-saif.1", .ops = &mxs_sgtl5000_hifi_ops, }, }; @@ -110,11 +112,48 @@ static struct snd_soc_card mxs_sgtl5000 = { .num_links = ARRAY_SIZE(mxs_sgtl5000_dai), }; +static int __devinit mxs_sgtl5000_probe_dt(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *saif_np[2], *codec_np; + int i, ret = 0; + + if (!np) + return 1; /* no device tree */ + + saif_np[0] = of_parse_phandle(np, "saif-controllers", 0); + saif_np[1] = of_parse_phandle(np, "saif-controllers", 1); + codec_np = of_parse_phandle(np, "audio-codec", 0); + if (!saif_np[0] || !saif_np[1] || !codec_np) { + dev_err(&pdev->dev, "phandle missing or invalid\n"); + return -EINVAL; + } + + for (i = 0; i < 2; i++) { + mxs_sgtl5000_dai[i].codec_name = NULL; + mxs_sgtl5000_dai[i].codec_of_node = codec_np; + mxs_sgtl5000_dai[i].cpu_dai_name = NULL; + mxs_sgtl5000_dai[i].cpu_dai_of_node = saif_np[i]; + mxs_sgtl5000_dai[i].platform_name = NULL; + mxs_sgtl5000_dai[i].platform_of_node = saif_np[i]; + } + + of_node_put(codec_np); + of_node_put(saif_np[0]); + of_node_put(saif_np[1]); + + return ret; +} + static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev) { struct snd_soc_card *card = &mxs_sgtl5000; int ret; + ret = mxs_sgtl5000_probe_dt(pdev); + if (ret < 0) + return ret; + /* * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w). * The Sgtl5000 sysclk is derived from saif0 mclk and it's range @@ -148,10 +187,17 @@ static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id mxs_sgtl5000_dt_ids[] = { + { .compatible = "fsl,mxs-audio-sgtl5000", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_sgtl5000_dt_ids); + static struct platform_driver mxs_sgtl5000_audio_driver = { .driver = { .name = "mxs-sgtl5000", .owner = THIS_MODULE, + .of_match_table = mxs_sgtl5000_dt_ids, }, .probe = mxs_sgtl5000_probe, .remove = __devexit_p(mxs_sgtl5000_remove), |