diff options
| author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2014-03-17 22:29:55 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2014-03-21 14:14:56 -0400 |
| commit | 90e8e50fce3585d6f9902701de08389b027dadc6 (patch) | |
| tree | 67971cdae1de6d546e530d05ba3964f553cf9c24 | |
| parent | ba9c949f797aa3af56303445812a452144c61c35 (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>
| -rw-r--r-- | Documentation/devicetree/bindings/sound/renesas,rsnd.txt | 96 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/adg.c | 1 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/core.c | 122 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/gen.c | 15 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 11 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/src.c | 36 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/ssi.c | 56 |
7 files changed, 334 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt new file mode 100644 index 000000000000..7c6d33f29796 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | Renesas R-Car sound | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : "renesas,rcar_sound-gen1" if generation1 | ||
| 5 | "renesas,rcar_sound-gen2" if generation2 | ||
| 6 | - reg : Should contain the register physical address. | ||
| 7 | required register is | ||
| 8 | SRU/ADG/SSI if generation1 | ||
| 9 | SRU/ADG/SSIU/SSI if generation2 | ||
| 10 | - rcar_sound,ssi : SSI subnode | ||
| 11 | - rcar_sound,scu : SCU subnode | ||
| 12 | - rcar_sound,dai : DAI subnode | ||
| 13 | |||
| 14 | SSI subnode properties: | ||
| 15 | - interrupts : Should contain SSI interrupt for PIO transfer | ||
| 16 | - shared-pin : if shared clock pin | ||
| 17 | |||
| 18 | DAI subnode properties: | ||
| 19 | - playback : list of playback modules | ||
| 20 | - capture : list of capture modules | ||
| 21 | |||
| 22 | Example: | ||
| 23 | |||
| 24 | rcar_sound: rcar_sound@0xffd90000 { | ||
| 25 | #sound-dai-cells = <1>; | ||
| 26 | compatible = "renesas,rcar_sound-gen2"; | ||
| 27 | reg = <0 0xec500000 0 0x1000>, /* SCU */ | ||
| 28 | <0 0xec5a0000 0 0x100>, /* ADG */ | ||
| 29 | <0 0xec540000 0 0x1000>, /* SSIU */ | ||
| 30 | <0 0xec541000 0 0x1280>; /* SSI */ | ||
| 31 | |||
| 32 | rcar_sound,src { | ||
| 33 | src0: src@0 { }; | ||
| 34 | src1: src@1 { }; | ||
| 35 | src2: src@2 { }; | ||
| 36 | src3: src@3 { }; | ||
| 37 | src4: src@4 { }; | ||
| 38 | src5: src@5 { }; | ||
| 39 | src6: src@6 { }; | ||
| 40 | src7: src@7 { }; | ||
| 41 | src8: src@8 { }; | ||
| 42 | src9: src@9 { }; | ||
| 43 | }; | ||
| 44 | |||
| 45 | rcar_sound,ssi { | ||
| 46 | ssi0: ssi@0 { | ||
| 47 | interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; | ||
| 48 | }; | ||
| 49 | ssi1: ssi@1 { | ||
| 50 | interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; | ||
| 51 | }; | ||
| 52 | ssi2: ssi@2 { | ||
| 53 | interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; | ||
| 54 | }; | ||
| 55 | ssi3: ssi@3 { | ||
| 56 | interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; | ||
| 57 | }; | ||
| 58 | ssi4: ssi@4 { | ||
| 59 | interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; | ||
| 60 | }; | ||
| 61 | ssi5: ssi@5 { | ||
| 62 | interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; | ||
| 63 | }; | ||
| 64 | ssi6: ssi@6 { | ||
| 65 | interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; | ||
| 66 | }; | ||
| 67 | ssi7: ssi@7 { | ||
| 68 | interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; | ||
| 69 | }; | ||
| 70 | ssi8: ssi@8 { | ||
| 71 | interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; | ||
| 72 | }; | ||
| 73 | ssi9: ssi@9 { | ||
| 74 | interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; | ||
| 75 | }; | ||
| 76 | }; | ||
| 77 | |||
| 78 | rcar_sound,dai { | ||
| 79 | dai0 { | ||
| 80 | playback = <&ssi5 &src5>; | ||
| 81 | capture = <&ssi6>; | ||
| 82 | }; | ||
| 83 | dai1 { | ||
| 84 | playback = <&ssi3>; | ||
| 85 | }; | ||
| 86 | dai2 { | ||
| 87 | capture = <&ssi4>; | ||
| 88 | }; | ||
| 89 | dai3 { | ||
| 90 | playback = <&ssi7>; | ||
| 91 | }; | ||
| 92 | dai4 { | ||
| 93 | capture = <&ssi8>; | ||
| 94 | }; | ||
| 95 | }; | ||
| 96 | }; | ||
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 | ||
| 394 | int rsnd_adg_probe(struct platform_device *pdev, | 394 | int 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 | ||
| 103 | static struct rsnd_of_data rsnd_of_data_gen1 = { | ||
| 104 | .flags = RSND_GEN1, | ||
| 105 | }; | ||
| 106 | |||
| 107 | static struct rsnd_of_data rsnd_of_data_gen2 = { | ||
| 108 | .flags = RSND_GEN2, | ||
| 109 | }; | ||
| 110 | |||
| 111 | static 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 | }; | ||
| 116 | MODULE_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 | ||
| 638 | static 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) \ | ||
| 678 | if (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 | |||
| 623 | static int rsnd_dai_probe(struct platform_device *pdev, | 722 | static 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) | |||
| 903 | static struct platform_driver rsnd_driver = { | 1018 | static 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 | */ |
| 362 | static 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 | |||
| 362 | int rsnd_gen_probe(struct platform_device *pdev, | 374 | int 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 | ||
| 118 | struct rsnd_of_data; | ||
| 116 | struct rsnd_priv; | 119 | struct rsnd_priv; |
| 117 | struct rsnd_mod; | 120 | struct rsnd_mod; |
| 118 | struct rsnd_dai; | 121 | struct 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 | */ |
| 262 | int rsnd_gen_probe(struct platform_device *pdev, | 265 | int 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); |
| 264 | void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, | 268 | void __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, | |||
| 273 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); | 277 | int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); |
| 274 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); | 278 | int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); |
| 275 | int rsnd_adg_probe(struct platform_device *pdev, | 279 | int 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); |
| 277 | int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, | 282 | int 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 | */ |
| 298 | struct rsnd_of_data { | ||
| 299 | u32 flags; | ||
| 300 | }; | ||
| 301 | |||
| 293 | struct rsnd_priv { | 302 | struct 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 | */ |
| 350 | int rsnd_src_probe(struct platform_device *pdev, | 359 | int 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); |
| 352 | struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); | 362 | struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); |
| 353 | unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, | 363 | unsigned 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 | */ |
| 368 | int rsnd_ssi_probe(struct platform_device *pdev, | 378 | int 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); |
| 370 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | 381 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); |
| 371 | struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv, | 382 | struct 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 | ||
| 631 | static 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 | |||
| 631 | int rsnd_src_probe(struct platform_device *pdev, | 664 | int 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 | |||
| 592 | static 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 | |||
| 591 | int rsnd_ssi_probe(struct platform_device *pdev, | 644 | int 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 | */ |
