aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh/rcar
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2014-03-17 22:29:55 -0400
committerMark Brown <broonie@linaro.org>2014-03-21 14:14:56 -0400
commit90e8e50fce3585d6f9902701de08389b027dadc6 (patch)
tree67971cdae1de6d546e530d05ba3964f553cf9c24 /sound/soc/sh/rcar
parentba9c949f797aa3af56303445812a452144c61c35 (diff)
ASoC: rsnd: add DeviceTree support
Support for loading the Renesas R-Car sound driver via DeviceTree. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/sh/rcar')
-rw-r--r--sound/soc/sh/rcar/adg.c1
-rw-r--r--sound/soc/sh/rcar/core.c122
-rw-r--r--sound/soc/sh/rcar/gen.c15
-rw-r--r--sound/soc/sh/rcar/rsnd.h11
-rw-r--r--sound/soc/sh/rcar/src.c36
-rw-r--r--sound/soc/sh/rcar/ssi.c56
6 files changed, 238 insertions, 3 deletions
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 953f1cce982d..69c44269ebdb 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -392,6 +392,7 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
392} 392}
393 393
394int rsnd_adg_probe(struct platform_device *pdev, 394int rsnd_adg_probe(struct platform_device *pdev,
395 const struct rsnd_of_data *of_data,
395 struct rsnd_priv *priv) 396 struct rsnd_priv *priv)
396{ 397{
397 struct rsnd_adg *adg; 398 struct rsnd_adg *adg;
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 6a1b45df8101..e77f7716f1d7 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -100,6 +100,21 @@
100#define RSND_RATES SNDRV_PCM_RATE_8000_96000 100#define RSND_RATES SNDRV_PCM_RATE_8000_96000
101#define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) 101#define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
102 102
103static struct rsnd_of_data rsnd_of_data_gen1 = {
104 .flags = RSND_GEN1,
105};
106
107static struct rsnd_of_data rsnd_of_data_gen2 = {
108 .flags = RSND_GEN2,
109};
110
111static struct of_device_id rsnd_of_match[] = {
112 { .compatible = "renesas,rcar_sound-gen1", .data = &rsnd_of_data_gen1 },
113 { .compatible = "renesas,rcar_sound-gen2", .data = &rsnd_of_data_gen2 },
114 {},
115};
116MODULE_DEVICE_TABLE(of, rsnd_of_match);
117
103/* 118/*
104 * rsnd_platform functions 119 * rsnd_platform functions
105 */ 120 */
@@ -620,7 +635,92 @@ static int rsnd_path_init(struct rsnd_priv *priv,
620 return ret; 635 return ret;
621} 636}
622 637
638static void rsnd_of_parse_dai(struct platform_device *pdev,
639 const struct rsnd_of_data *of_data,
640 struct rsnd_priv *priv)
641{
642 struct device_node *dai_node, *dai_np;
643 struct device_node *ssi_node, *ssi_np;
644 struct device_node *src_node, *src_np;
645 struct device_node *playback, *capture;
646 struct rsnd_dai_platform_info *dai_info;
647 struct rcar_snd_info *info = rsnd_priv_to_info(priv);
648 struct device *dev = &pdev->dev;
649 int nr, i;
650 int dai_i, ssi_i, src_i;
651
652 if (!of_data)
653 return;
654
655 dai_node = of_get_child_by_name(dev->of_node, "rcar_sound,dai");
656 if (!dai_node)
657 return;
658
659 nr = of_get_child_count(dai_node);
660 if (!nr)
661 return;
662
663 dai_info = devm_kzalloc(dev,
664 sizeof(struct rsnd_dai_platform_info) * nr,
665 GFP_KERNEL);
666 if (!dai_info) {
667 dev_err(dev, "dai info allocation error\n");
668 return;
669 }
670
671 info->dai_info_nr = nr;
672 info->dai_info = dai_info;
673
674 ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
675 src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src");
676
677#define mod_parse(name) \
678if (name##_node) { \
679 struct rsnd_##name##_platform_info *name##_info; \
680 \
681 name##_i = 0; \
682 for_each_child_of_node(name##_node, name##_np) { \
683 name##_info = info->name##_info + name##_i; \
684 \
685 if (name##_np == playback) \
686 dai_info->playback.name = name##_info; \
687 if (name##_np == capture) \
688 dai_info->capture.name = name##_info; \
689 \
690 name##_i++; \
691 } \
692}
693
694 /*
695 * parse all dai
696 */
697 dai_i = 0;
698 for_each_child_of_node(dai_node, dai_np) {
699 dai_info = info->dai_info + dai_i;
700
701 for (i = 0;; i++) {
702
703 playback = of_parse_phandle(dai_np, "playback", i);
704 capture = of_parse_phandle(dai_np, "capture", i);
705
706 if (!playback && !capture)
707 break;
708
709 mod_parse(ssi);
710 mod_parse(src);
711
712 if (playback)
713 of_node_put(playback);
714 if (capture)
715 of_node_put(capture);
716 }
717
718 dai_i++;
719 }
720}
721
623static int rsnd_dai_probe(struct platform_device *pdev, 722static int rsnd_dai_probe(struct platform_device *pdev,
723 const struct rsnd_of_data *of_data,
624 struct rsnd_priv *priv) 724 struct rsnd_priv *priv)
625{ 725{
626 struct snd_soc_dai_driver *drv; 726 struct snd_soc_dai_driver *drv;
@@ -628,13 +728,16 @@ static int rsnd_dai_probe(struct platform_device *pdev,
628 struct rsnd_dai *rdai; 728 struct rsnd_dai *rdai;
629 struct rsnd_mod *pmod, *cmod; 729 struct rsnd_mod *pmod, *cmod;
630 struct device *dev = rsnd_priv_to_dev(priv); 730 struct device *dev = rsnd_priv_to_dev(priv);
631 int dai_nr = info->dai_info_nr; 731 int dai_nr;
632 int i; 732 int i;
633 733
734 rsnd_of_parse_dai(pdev, of_data, priv);
735
634 /* 736 /*
635 * dai_nr should be set via dai_info_nr, 737 * dai_nr should be set via dai_info_nr,
636 * but allow it to keeping compatible 738 * but allow it to keeping compatible
637 */ 739 */
740 dai_nr = info->dai_info_nr;
638 if (!dai_nr) { 741 if (!dai_nr) {
639 /* get max dai nr */ 742 /* get max dai nr */
640 for (dai_nr = 0; dai_nr < 32; dai_nr++) { 743 for (dai_nr = 0; dai_nr < 32; dai_nr++) {
@@ -802,7 +905,10 @@ static int rsnd_probe(struct platform_device *pdev)
802 struct rsnd_priv *priv; 905 struct rsnd_priv *priv;
803 struct device *dev = &pdev->dev; 906 struct device *dev = &pdev->dev;
804 struct rsnd_dai *rdai; 907 struct rsnd_dai *rdai;
908 const struct of_device_id *of_id = of_match_device(rsnd_of_match, dev);
909 const struct rsnd_of_data *of_data;
805 int (*probe_func[])(struct platform_device *pdev, 910 int (*probe_func[])(struct platform_device *pdev,
911 const struct rsnd_of_data *of_data,
806 struct rsnd_priv *priv) = { 912 struct rsnd_priv *priv) = {
807 rsnd_gen_probe, 913 rsnd_gen_probe,
808 rsnd_ssi_probe, 914 rsnd_ssi_probe,
@@ -812,7 +918,16 @@ static int rsnd_probe(struct platform_device *pdev)
812 }; 918 };
813 int ret, i; 919 int ret, i;
814 920
815 info = pdev->dev.platform_data; 921 info = NULL;
922 of_data = NULL;
923 if (of_id) {
924 info = devm_kzalloc(&pdev->dev,
925 sizeof(struct rcar_snd_info), GFP_KERNEL);
926 of_data = of_id->data;
927 } else {
928 info = pdev->dev.platform_data;
929 }
930
816 if (!info) { 931 if (!info) {
817 dev_err(dev, "driver needs R-Car sound information\n"); 932 dev_err(dev, "driver needs R-Car sound information\n");
818 return -ENODEV; 933 return -ENODEV;
@@ -835,7 +950,7 @@ static int rsnd_probe(struct platform_device *pdev)
835 * init each module 950 * init each module
836 */ 951 */
837 for (i = 0; i < ARRAY_SIZE(probe_func); i++) { 952 for (i = 0; i < ARRAY_SIZE(probe_func); i++) {
838 ret = probe_func[i](pdev, priv); 953 ret = probe_func[i](pdev, of_data, priv);
839 if (ret) 954 if (ret)
840 return ret; 955 return ret;
841 } 956 }
@@ -903,6 +1018,7 @@ static int rsnd_remove(struct platform_device *pdev)
903static struct platform_driver rsnd_driver = { 1018static struct platform_driver rsnd_driver = {
904 .driver = { 1019 .driver = {
905 .name = "rcar_sound", 1020 .name = "rcar_sound",
1021 .of_match_table = rsnd_of_match,
906 }, 1022 },
907 .probe = rsnd_probe, 1023 .probe = rsnd_probe,
908 .remove = rsnd_remove, 1024 .remove = rsnd_remove,
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 9094970dbdfb..50a1ef3eb1c6 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -359,13 +359,28 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
359/* 359/*
360 * Gen 360 * Gen
361 */ 361 */
362static void rsnd_of_parse_gen(struct platform_device *pdev,
363 const struct rsnd_of_data *of_data,
364 struct rsnd_priv *priv)
365{
366 struct rcar_snd_info *info = priv->info;
367
368 if (!of_data)
369 return;
370
371 info->flags = of_data->flags;
372}
373
362int rsnd_gen_probe(struct platform_device *pdev, 374int rsnd_gen_probe(struct platform_device *pdev,
375 const struct rsnd_of_data *of_data,
363 struct rsnd_priv *priv) 376 struct rsnd_priv *priv)
364{ 377{
365 struct device *dev = rsnd_priv_to_dev(priv); 378 struct device *dev = rsnd_priv_to_dev(priv);
366 struct rsnd_gen *gen; 379 struct rsnd_gen *gen;
367 int ret; 380 int ret;
368 381
382 rsnd_of_parse_gen(pdev, of_data, priv);
383
369 gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); 384 gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
370 if (!gen) { 385 if (!gen) {
371 dev_err(dev, "GEN allocate failed\n"); 386 dev_err(dev, "GEN allocate failed\n");
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index c46e0afa54ae..619d198c7d2e 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -17,6 +17,8 @@
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/list.h> 18#include <linux/list.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/of_device.h>
21#include <linux/of_irq.h>
20#include <linux/sh_dma.h> 22#include <linux/sh_dma.h>
21#include <linux/workqueue.h> 23#include <linux/workqueue.h>
22#include <sound/rcar_snd.h> 24#include <sound/rcar_snd.h>
@@ -113,6 +115,7 @@ enum rsnd_reg {
113#define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 115#define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18
114#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 116#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
115 117
118struct rsnd_of_data;
116struct rsnd_priv; 119struct rsnd_priv;
117struct rsnd_mod; 120struct rsnd_mod;
118struct rsnd_dai; 121struct rsnd_dai;
@@ -260,6 +263,7 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
260 * R-Car Gen1/Gen2 263 * R-Car Gen1/Gen2
261 */ 264 */
262int rsnd_gen_probe(struct platform_device *pdev, 265int rsnd_gen_probe(struct platform_device *pdev,
266 const struct rsnd_of_data *of_data,
263 struct rsnd_priv *priv); 267 struct rsnd_priv *priv);
264void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, 268void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
265 struct rsnd_mod *mod, 269 struct rsnd_mod *mod,
@@ -273,6 +277,7 @@ void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
273int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); 277int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod);
274int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); 278int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate);
275int rsnd_adg_probe(struct platform_device *pdev, 279int rsnd_adg_probe(struct platform_device *pdev,
280 const struct rsnd_of_data *of_data,
276 struct rsnd_priv *priv); 281 struct rsnd_priv *priv);
277int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, 282int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
278 struct rsnd_mod *mod, 283 struct rsnd_mod *mod,
@@ -290,6 +295,10 @@ int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod,
290/* 295/*
291 * R-Car sound priv 296 * R-Car sound priv
292 */ 297 */
298struct rsnd_of_data {
299 u32 flags;
300};
301
293struct rsnd_priv { 302struct rsnd_priv {
294 303
295 struct device *dev; 304 struct device *dev;
@@ -348,6 +357,7 @@ struct rsnd_priv {
348 * R-Car SRC 357 * R-Car SRC
349 */ 358 */
350int rsnd_src_probe(struct platform_device *pdev, 359int rsnd_src_probe(struct platform_device *pdev,
360 const struct rsnd_of_data *of_data,
351 struct rsnd_priv *priv); 361 struct rsnd_priv *priv);
352struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); 362struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
353unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, 363unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
@@ -366,6 +376,7 @@ int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod,
366 * R-Car SSI 376 * R-Car SSI
367 */ 377 */
368int rsnd_ssi_probe(struct platform_device *pdev, 378int rsnd_ssi_probe(struct platform_device *pdev,
379 const struct rsnd_of_data *of_data,
369 struct rsnd_priv *priv); 380 struct rsnd_priv *priv);
370struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); 381struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
371struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, 382struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index ea6a214985d0..eee75ebf961c 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -628,7 +628,41 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id)
628 return &((struct rsnd_src *)(priv->src) + id)->mod; 628 return &((struct rsnd_src *)(priv->src) + id)->mod;
629} 629}
630 630
631static void rsnd_of_parse_src(struct platform_device *pdev,
632 const struct rsnd_of_data *of_data,
633 struct rsnd_priv *priv)
634{
635 struct device_node *src_node;
636 struct rcar_snd_info *info = rsnd_priv_to_info(priv);
637 struct rsnd_src_platform_info *src_info;
638 struct device *dev = &pdev->dev;
639 int nr;
640
641 if (!of_data)
642 return;
643
644 src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src");
645 if (!src_node)
646 return;
647
648 nr = of_get_child_count(src_node);
649 if (!nr)
650 return;
651
652 src_info = devm_kzalloc(dev,
653 sizeof(struct rsnd_src_platform_info) * nr,
654 GFP_KERNEL);
655 if (!src_info) {
656 dev_err(dev, "src info allocation error\n");
657 return;
658 }
659
660 info->src_info = src_info;
661 info->src_info_nr = nr;
662}
663
631int rsnd_src_probe(struct platform_device *pdev, 664int rsnd_src_probe(struct platform_device *pdev,
665 const struct rsnd_of_data *of_data,
632 struct rsnd_priv *priv) 666 struct rsnd_priv *priv)
633{ 667{
634 struct rcar_snd_info *info = rsnd_priv_to_info(priv); 668 struct rcar_snd_info *info = rsnd_priv_to_info(priv);
@@ -639,6 +673,8 @@ int rsnd_src_probe(struct platform_device *pdev,
639 char name[RSND_SRC_NAME_SIZE]; 673 char name[RSND_SRC_NAME_SIZE];
640 int i, nr; 674 int i, nr;
641 675
676 rsnd_of_parse_src(pdev, of_data, priv);
677
642 /* 678 /*
643 * init SRC 679 * init SRC
644 */ 680 */
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 633b23d209b9..4b7e20603dd7 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -588,7 +588,61 @@ static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *s
588 } 588 }
589} 589}
590 590
591
592static void rsnd_of_parse_ssi(struct platform_device *pdev,
593 const struct rsnd_of_data *of_data,
594 struct rsnd_priv *priv)
595{
596 struct device_node *node;
597 struct device_node *np;
598 struct rsnd_ssi_platform_info *ssi_info;
599 struct rcar_snd_info *info = rsnd_priv_to_info(priv);
600 struct device *dev = &pdev->dev;
601 int nr, i;
602
603 if (!of_data)
604 return;
605
606 node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
607 if (!node)
608 return;
609
610 nr = of_get_child_count(node);
611 if (!nr)
612 return;
613
614 ssi_info = devm_kzalloc(dev,
615 sizeof(struct rsnd_ssi_platform_info) * nr,
616 GFP_KERNEL);
617 if (!ssi_info) {
618 dev_err(dev, "ssi info allocation error\n");
619 return;
620 }
621
622 info->ssi_info = ssi_info;
623 info->ssi_info_nr = nr;
624
625 i = -1;
626 for_each_child_of_node(node, np) {
627 i++;
628
629 ssi_info = info->ssi_info + i;
630
631 /*
632 * pin settings
633 */
634 if (of_get_property(np, "shared-pin", NULL))
635 ssi_info->flags |= RSND_SSI_CLK_PIN_SHARE;
636
637 /*
638 * irq
639 */
640 ssi_info->pio_irq = irq_of_parse_and_map(np, 0);
641 }
642}
643
591int rsnd_ssi_probe(struct platform_device *pdev, 644int rsnd_ssi_probe(struct platform_device *pdev,
645 const struct rsnd_of_data *of_data,
592 struct rsnd_priv *priv) 646 struct rsnd_priv *priv)
593{ 647{
594 struct rcar_snd_info *info = rsnd_priv_to_info(priv); 648 struct rcar_snd_info *info = rsnd_priv_to_info(priv);
@@ -600,6 +654,8 @@ int rsnd_ssi_probe(struct platform_device *pdev,
600 char name[RSND_SSI_NAME_SIZE]; 654 char name[RSND_SSI_NAME_SIZE];
601 int i, nr; 655 int i, nr;
602 656
657 rsnd_of_parse_ssi(pdev, of_data, priv);
658
603 /* 659 /*
604 * init SSI 660 * init SSI
605 */ 661 */