aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2015-07-15 03:17:36 -0400
committerMark Brown <broonie@kernel.org>2015-07-17 14:26:06 -0400
commit70fb10529f61c31c26397a02091177bedd23217d (patch)
tree73cf4ee3132165250814949798b481237b25dff4
parent9269e3c3cfac277a49b485e27ac6850f9a11a259 (diff)
ASoC: rsnd: add MIX (Mixer) support
This patch adds MIX (Mixer) initial support for rsnd driver. It is assuming that this MIX is used via DPCM. This is sample code for playback. CPU0 : [MEM] -> [SRC1] -> [CTU02] -+ | +-> [MIX0] -> [DVC0] -> [SSI0] | CPU1 : [MEM] -> [SRC2] -> [CTU03] -+ sound { compatible = "renesas,rsrc-card"; ... cpu@0 { sound-dai = <&rcar_sound 0>; }; cpu@1 { sound-dai = <&rcar_sound 1>; }; codec { ... }; }; rcar_sound { ... rcar_sound,dai { dai0 { playback = <&src1 &ctu02 &mix0 &dvc0 &ssi0>; }; dai1 { playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>; }; }; }; Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Keita Kobayashi <keita.kobayashi.ym@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.txt8
-rw-r--r--include/sound/rcar_snd.h7
-rw-r--r--sound/soc/sh/rcar/Makefile2
-rw-r--r--sound/soc/sh/rcar/core.c85
-rw-r--r--sound/soc/sh/rcar/dma.c5
-rw-r--r--sound/soc/sh/rcar/gen.c10
-rw-r--r--sound/soc/sh/rcar/mix.c200
-rw-r--r--sound/soc/sh/rcar/rsnd.h29
8 files changed, 333 insertions, 13 deletions
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
index 278607de05de..1173395b5e5c 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt
@@ -21,6 +21,9 @@ Required properties:
21- rcar_sound,ctu : Should contain CTU feature. 21- rcar_sound,ctu : Should contain CTU feature.
22 The number of CTU subnode should be same as HW. 22 The number of CTU subnode should be same as HW.
23 see below for detail. 23 see below for detail.
24- rcar_sound,mix : Should contain MIX feature.
25 The number of MIX subnode should be same as HW.
26 see below for detail.
24- rcar_sound,dvc : Should contain DVC feature. 27- rcar_sound,dvc : Should contain DVC feature.
25 The number of DVC subnode should be same as HW. 28 The number of DVC subnode should be same as HW.
26 see below for detail. 29 see below for detail.
@@ -93,6 +96,11 @@ rcar_sound: sound@ec500000 {
93 }; 96 };
94 }; 97 };
95 98
99 rcar_sound,mix {
100 mix0: mix@0 { };
101 mix1: mix@1 { };
102 };
103
96 rcar_sound,ctu { 104 rcar_sound,ctu {
97 ctu00: ctu@0 { }; 105 ctu00: ctu@0 { };
98 ctu01: ctu@1 { }; 106 ctu01: ctu@1 { };
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h
index 8f9303093ab9..bb7b2ebfee7b 100644
--- a/include/sound/rcar_snd.h
+++ b/include/sound/rcar_snd.h
@@ -65,6 +65,10 @@ struct rsnd_ctu_platform_info {
65 u32 flags; 65 u32 flags;
66}; 66};
67 67
68struct rsnd_mix_platform_info {
69 u32 flags;
70};
71
68struct rsnd_dvc_platform_info { 72struct rsnd_dvc_platform_info {
69 u32 flags; 73 u32 flags;
70}; 74};
@@ -73,6 +77,7 @@ struct rsnd_dai_path_info {
73 struct rsnd_ssi_platform_info *ssi; 77 struct rsnd_ssi_platform_info *ssi;
74 struct rsnd_src_platform_info *src; 78 struct rsnd_src_platform_info *src;
75 struct rsnd_ctu_platform_info *ctu; 79 struct rsnd_ctu_platform_info *ctu;
80 struct rsnd_mix_platform_info *mix;
76 struct rsnd_dvc_platform_info *dvc; 81 struct rsnd_dvc_platform_info *dvc;
77}; 82};
78 83
@@ -100,6 +105,8 @@ struct rcar_snd_info {
100 int src_info_nr; 105 int src_info_nr;
101 struct rsnd_ctu_platform_info *ctu_info; 106 struct rsnd_ctu_platform_info *ctu_info;
102 int ctu_info_nr; 107 int ctu_info_nr;
108 struct rsnd_mix_platform_info *mix_info;
109 int mix_info_nr;
103 struct rsnd_dvc_platform_info *dvc_info; 110 struct rsnd_dvc_platform_info *dvc_info;
104 int dvc_info_nr; 111 int dvc_info_nr;
105 struct rsnd_dai_platform_info *dai_info; 112 struct rsnd_dai_platform_info *dai_info;
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile
index 7c4730a81c4a..8b258501aa35 100644
--- a/sound/soc/sh/rcar/Makefile
+++ b/sound/soc/sh/rcar/Makefile
@@ -1,4 +1,4 @@
1snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o dvc.o 1snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o
2obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o 2obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
3 3
4snd-soc-rsrc-card-objs := rsrc-card.o 4snd-soc-rsrc-card-objs := rsrc-card.o
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 63ae7bbfd1dc..927a7b02123b 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -605,23 +605,74 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
605void rsnd_path_parse(struct rsnd_priv *priv, 605void rsnd_path_parse(struct rsnd_priv *priv,
606 struct rsnd_dai_stream *io) 606 struct rsnd_dai_stream *io)
607{ 607{
608 struct rsnd_mod *src = rsnd_io_to_mod_src(io);
609 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); 608 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
610 int src_id = rsnd_mod_id(src); 609 struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
611 u32 path[] = { 610 struct rsnd_mod *src = rsnd_io_to_mod_src(io);
612 [0] = 0x30000, 611 struct rsnd_mod *cmd;
613 [1] = 0x30001, 612 struct device *dev = rsnd_priv_to_dev(priv);
614 [2] = 0x40000, 613 u32 data;
615 [3] = 0x10000,
616 [4] = 0x20000,
617 [5] = 0x40100
618 };
619 614
620 /* Gen1 is not supported */ 615 /* Gen1 is not supported */
621 if (rsnd_is_gen1(priv)) 616 if (rsnd_is_gen1(priv))
622 return; 617 return;
623 618
624 rsnd_mod_write(dvc, CMD_ROUTE_SLCT, path[src_id]); 619 if (!mix && !dvc)
620 return;
621
622 if (mix) {
623 struct rsnd_dai *rdai;
624 int i;
625 u32 path[] = {
626 [0] = 0,
627 [1] = 1 << 0,
628 [2] = 0,
629 [3] = 0,
630 [4] = 0,
631 [5] = 1 << 8
632 };
633
634 /*
635 * it is assuming that integrater is well understanding about
636 * data path. Here doesn't check impossible connection,
637 * like src2 + src5
638 */
639 data = 0;
640 for_each_rsnd_dai(rdai, priv, i) {
641 io = &rdai->playback;
642 if (mix == rsnd_io_to_mod_mix(io))
643 data |= path[rsnd_mod_id(src)];
644
645 io = &rdai->capture;
646 if (mix == rsnd_io_to_mod_mix(io))
647 data |= path[rsnd_mod_id(src)];
648 }
649
650 /*
651 * We can't use ctu = rsnd_io_ctu() here.
652 * Since, ID of dvc/mix are 0 or 1 (= same as CMD number)
653 * but ctu IDs are 0 - 7 (= CTU00 - CTU13)
654 */
655 cmd = mix;
656 } else {
657 u32 path[] = {
658 [0] = 0x30000,
659 [1] = 0x30001,
660 [2] = 0x40000,
661 [3] = 0x10000,
662 [4] = 0x20000,
663 [5] = 0x40100
664 };
665
666 data = path[rsnd_mod_id(src)];
667
668 cmd = dvc;
669 }
670
671 dev_dbg(dev, "ctu/mix path = 0x%08x", data);
672
673 rsnd_mod_write(cmd, CMD_ROUTE_SLCT, data);
674
675 rsnd_mod_write(cmd, CMD_CTRL, 0x10);
625} 676}
626 677
627static int rsnd_path_init(struct rsnd_priv *priv, 678static int rsnd_path_init(struct rsnd_priv *priv,
@@ -656,6 +707,11 @@ static int rsnd_path_init(struct rsnd_priv *priv,
656 if (ret < 0) 707 if (ret < 0)
657 return ret; 708 return ret;
658 709
710 /* MIX */
711 ret = rsnd_path_add(priv, io, mix);
712 if (ret < 0)
713 return ret;
714
659 /* DVC */ 715 /* DVC */
660 ret = rsnd_path_add(priv, io, dvc); 716 ret = rsnd_path_add(priv, io, dvc);
661 if (ret < 0) 717 if (ret < 0)
@@ -672,13 +728,14 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
672 struct device_node *ssi_node, *ssi_np; 728 struct device_node *ssi_node, *ssi_np;
673 struct device_node *src_node, *src_np; 729 struct device_node *src_node, *src_np;
674 struct device_node *ctu_node, *ctu_np; 730 struct device_node *ctu_node, *ctu_np;
731 struct device_node *mix_node, *mix_np;
675 struct device_node *dvc_node, *dvc_np; 732 struct device_node *dvc_node, *dvc_np;
676 struct device_node *playback, *capture; 733 struct device_node *playback, *capture;
677 struct rsnd_dai_platform_info *dai_info; 734 struct rsnd_dai_platform_info *dai_info;
678 struct rcar_snd_info *info = rsnd_priv_to_info(priv); 735 struct rcar_snd_info *info = rsnd_priv_to_info(priv);
679 struct device *dev = &pdev->dev; 736 struct device *dev = &pdev->dev;
680 int nr, i; 737 int nr, i;
681 int dai_i, ssi_i, src_i, ctu_i, dvc_i; 738 int dai_i, ssi_i, src_i, ctu_i, mix_i, dvc_i;
682 739
683 if (!of_data) 740 if (!of_data)
684 return; 741 return;
@@ -705,6 +762,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
705 ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); 762 ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
706 src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); 763 src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src");
707 ctu_node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu"); 764 ctu_node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu");
765 mix_node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
708 dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc"); 766 dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");
709 767
710#define mod_parse(name) \ 768#define mod_parse(name) \
@@ -742,6 +800,7 @@ if (name##_node) { \
742 mod_parse(ssi); 800 mod_parse(ssi);
743 mod_parse(src); 801 mod_parse(src);
744 mod_parse(ctu); 802 mod_parse(ctu);
803 mod_parse(mix);
745 mod_parse(dvc); 804 mod_parse(dvc);
746 805
747 of_node_put(playback); 806 of_node_put(playback);
@@ -1155,6 +1214,7 @@ static int rsnd_probe(struct platform_device *pdev)
1155 rsnd_ssi_probe, 1214 rsnd_ssi_probe,
1156 rsnd_src_probe, 1215 rsnd_src_probe,
1157 rsnd_ctu_probe, 1216 rsnd_ctu_probe,
1217 rsnd_mix_probe,
1158 rsnd_dvc_probe, 1218 rsnd_dvc_probe,
1159 rsnd_adg_probe, 1219 rsnd_adg_probe,
1160 rsnd_dai_probe, 1220 rsnd_dai_probe,
@@ -1251,6 +1311,7 @@ static int rsnd_remove(struct platform_device *pdev)
1251 rsnd_ssi_remove, 1311 rsnd_ssi_remove,
1252 rsnd_src_remove, 1312 rsnd_src_remove,
1253 rsnd_ctu_remove, 1313 rsnd_ctu_remove,
1314 rsnd_mix_remove,
1254 rsnd_dvc_remove, 1315 rsnd_dvc_remove,
1255 }; 1316 };
1256 int ret = 0, i; 1317 int ret = 0, i;
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 229b68d2cf70..305b12929853 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -427,6 +427,7 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
427 int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); 427 int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod);
428 int use_src = !!rsnd_io_to_mod_src(io); 428 int use_src = !!rsnd_io_to_mod_src(io);
429 int use_cmd = !!rsnd_io_to_mod_dvc(io) || 429 int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
430 !!rsnd_io_to_mod_mix(io) ||
430 !!rsnd_io_to_mod_ctu(io); 431 !!rsnd_io_to_mod_ctu(io);
431 int id = rsnd_mod_id(mod); 432 int id = rsnd_mod_id(mod);
432 struct dma_addr { 433 struct dma_addr {
@@ -506,6 +507,7 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
506 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); 507 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
507 struct rsnd_mod *src = rsnd_io_to_mod_src(io); 508 struct rsnd_mod *src = rsnd_io_to_mod_src(io);
508 struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io); 509 struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io);
510 struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
509 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); 511 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
510 struct rsnd_mod *mod[MOD_MAX]; 512 struct rsnd_mod *mod[MOD_MAX];
511 struct rsnd_mod *mod_start, *mod_end; 513 struct rsnd_mod *mod_start, *mod_end;
@@ -548,6 +550,9 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
548 } else if (ctu) { 550 } else if (ctu) {
549 mod[i] = ctu; 551 mod[i] = ctu;
550 ctu = NULL; 552 ctu = NULL;
553 } else if (mix) {
554 mod[i] = mix;
555 mix = NULL;
551 } else if (dvc) { 556 } else if (dvc) {
552 mod[i] = dvc; 557 mod[i] = dvc;
553 dvc = NULL; 558 dvc = NULL;
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 41b75cd4e09b..f04d17bc6e3d 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -242,6 +242,16 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
242 RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), 242 RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
243 RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100), 243 RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
244 RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100), 244 RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
245 RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40),
246 RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40),
247 RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40),
248 RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40),
249 RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40),
250 RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40),
251 RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40),
252 RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40),
253 RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40),
254 RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40),
245 RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), 255 RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
246 RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), 256 RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
247 RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), 257 RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c
new file mode 100644
index 000000000000..0d5c102db6f5
--- /dev/null
+++ b/sound/soc/sh/rcar/mix.c
@@ -0,0 +1,200 @@
1/*
2 * mix.c
3 *
4 * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include "rsnd.h"
11
12#define MIX_NAME_SIZE 16
13#define MIX_NAME "mix"
14
15struct rsnd_mix {
16 struct rsnd_mix_platform_info *info; /* rcar_snd.h */
17 struct rsnd_mod mod;
18};
19
20#define rsnd_mix_nr(priv) ((priv)->mix_nr)
21#define for_each_rsnd_mix(pos, priv, i) \
22 for ((i) = 0; \
23 ((i) < rsnd_mix_nr(priv)) && \
24 ((pos) = (struct rsnd_mix *)(priv)->mix + i); \
25 i++)
26
27
28static void rsnd_mix_soft_reset(struct rsnd_mod *mod)
29{
30 rsnd_mod_write(mod, MIX_SWRSR, 0);
31 rsnd_mod_write(mod, MIX_SWRSR, 1);
32}
33
34#define rsnd_mix_initialize_lock(mod) __rsnd_mix_initialize_lock(mod, 1)
35#define rsnd_mix_initialize_unlock(mod) __rsnd_mix_initialize_lock(mod, 0)
36static void __rsnd_mix_initialize_lock(struct rsnd_mod *mod, u32 enable)
37{
38 rsnd_mod_write(mod, MIX_MIXIR, enable);
39}
40
41static void rsnd_mix_volume_update(struct rsnd_dai_stream *io,
42 struct rsnd_mod *mod)
43{
44
45 /* Disable MIX dB setting */
46 rsnd_mod_write(mod, MIX_MDBER, 0);
47
48 rsnd_mod_write(mod, MIX_MDBAR, 0);
49 rsnd_mod_write(mod, MIX_MDBBR, 0);
50 rsnd_mod_write(mod, MIX_MDBCR, 0);
51 rsnd_mod_write(mod, MIX_MDBDR, 0);
52
53 /* Enable MIX dB setting */
54 rsnd_mod_write(mod, MIX_MDBER, 1);
55}
56
57static int rsnd_mix_init(struct rsnd_mod *mod,
58 struct rsnd_dai_stream *io,
59 struct rsnd_priv *priv)
60{
61 rsnd_mod_hw_start(mod);
62
63 rsnd_mix_soft_reset(mod);
64
65 rsnd_mix_initialize_lock(mod);
66
67 rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io));
68
69 rsnd_path_parse(priv, io);
70
71 /* volume step */
72 rsnd_mod_write(mod, MIX_MIXMR, 0);
73 rsnd_mod_write(mod, MIX_MVPDR, 0);
74
75 rsnd_mix_volume_update(io, mod);
76
77 rsnd_mix_initialize_unlock(mod);
78
79 return 0;
80}
81
82static int rsnd_mix_quit(struct rsnd_mod *mod,
83 struct rsnd_dai_stream *io,
84 struct rsnd_priv *priv)
85{
86 rsnd_mod_hw_stop(mod);
87
88 return 0;
89}
90
91static struct rsnd_mod_ops rsnd_mix_ops = {
92 .name = MIX_NAME,
93 .init = rsnd_mix_init,
94 .quit = rsnd_mix_quit,
95};
96
97struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
98{
99 if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
100 id = 0;
101
102 return &((struct rsnd_mix *)(priv->mix) + id)->mod;
103}
104
105static void rsnd_of_parse_mix(struct platform_device *pdev,
106 const struct rsnd_of_data *of_data,
107 struct rsnd_priv *priv)
108{
109 struct device_node *node;
110 struct rsnd_mix_platform_info *mix_info;
111 struct rcar_snd_info *info = rsnd_priv_to_info(priv);
112 struct device *dev = &pdev->dev;
113 int nr;
114
115 if (!of_data)
116 return;
117
118 node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
119 if (!node)
120 return;
121
122 nr = of_get_child_count(node);
123 if (!nr)
124 goto rsnd_of_parse_mix_end;
125
126 mix_info = devm_kzalloc(dev,
127 sizeof(struct rsnd_mix_platform_info) * nr,
128 GFP_KERNEL);
129 if (!mix_info) {
130 dev_err(dev, "mix info allocation error\n");
131 goto rsnd_of_parse_mix_end;
132 }
133
134 info->mix_info = mix_info;
135 info->mix_info_nr = nr;
136
137rsnd_of_parse_mix_end:
138 of_node_put(node);
139
140}
141
142int rsnd_mix_probe(struct platform_device *pdev,
143 const struct rsnd_of_data *of_data,
144 struct rsnd_priv *priv)
145{
146 struct rcar_snd_info *info = rsnd_priv_to_info(priv);
147 struct device *dev = rsnd_priv_to_dev(priv);
148 struct rsnd_mix *mix;
149 struct clk *clk;
150 char name[MIX_NAME_SIZE];
151 int i, nr, ret;
152
153 /* This driver doesn't support Gen1 at this point */
154 if (rsnd_is_gen1(priv)) {
155 dev_warn(dev, "MIX is not supported on Gen1\n");
156 return -EINVAL;
157 }
158
159 rsnd_of_parse_mix(pdev, of_data, priv);
160
161 nr = info->mix_info_nr;
162 if (!nr)
163 return 0;
164
165 mix = devm_kzalloc(dev, sizeof(*mix) * nr, GFP_KERNEL);
166 if (!mix)
167 return -ENOMEM;
168
169 priv->mix_nr = nr;
170 priv->mix = mix;
171
172 for_each_rsnd_mix(mix, priv, i) {
173 snprintf(name, MIX_NAME_SIZE, "%s.%d",
174 MIX_NAME, i);
175
176 clk = devm_clk_get(dev, name);
177 if (IS_ERR(clk))
178 return PTR_ERR(clk);
179
180 mix->info = &info->mix_info[i];
181
182 ret = rsnd_mod_init(priv, &mix->mod, &rsnd_mix_ops,
183 clk, RSND_MOD_MIX, i);
184 if (ret)
185 return ret;
186 }
187
188 return 0;
189}
190
191void rsnd_mix_remove(struct platform_device *pdev,
192 struct rsnd_priv *priv)
193{
194 struct rsnd_mix *mix;
195 int i;
196
197 for_each_rsnd_mix(mix, priv, i) {
198 rsnd_mod_quit(&mix->mod);
199 }
200}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index f2128a7cf259..7a0e52b4640a 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -49,6 +49,16 @@ enum rsnd_reg {
49 RSND_REG_CMD_ROUTE_SLCT, 49 RSND_REG_CMD_ROUTE_SLCT,
50 RSND_REG_CTU_CTUIR, 50 RSND_REG_CTU_CTUIR,
51 RSND_REG_CTU_ADINR, 51 RSND_REG_CTU_ADINR,
52 RSND_REG_MIX_SWRSR,
53 RSND_REG_MIX_MIXIR,
54 RSND_REG_MIX_ADINR,
55 RSND_REG_MIX_MIXMR,
56 RSND_REG_MIX_MVPDR,
57 RSND_REG_MIX_MDBAR,
58 RSND_REG_MIX_MDBBR,
59 RSND_REG_MIX_MDBCR,
60 RSND_REG_MIX_MDBDR,
61 RSND_REG_MIX_MDBER,
52 RSND_REG_DVC_SWRSR, 62 RSND_REG_DVC_SWRSR,
53 RSND_REG_DVC_DVUIR, 63 RSND_REG_DVC_DVUIR,
54 RSND_REG_DVC_ADINR, 64 RSND_REG_DVC_ADINR,
@@ -222,6 +232,7 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
222 */ 232 */
223enum rsnd_mod_type { 233enum rsnd_mod_type {
224 RSND_MOD_DVC = 0, 234 RSND_MOD_DVC = 0,
235 RSND_MOD_MIX,
225 RSND_MOD_CTU, 236 RSND_MOD_CTU,
226 RSND_MOD_SRC, 237 RSND_MOD_SRC,
227 RSND_MOD_SSI, 238 RSND_MOD_SSI,
@@ -355,6 +366,7 @@ struct rsnd_dai_stream {
355#define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI) 366#define rsnd_io_to_mod_ssi(io) rsnd_io_to_mod((io), RSND_MOD_SSI)
356#define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC) 367#define rsnd_io_to_mod_src(io) rsnd_io_to_mod((io), RSND_MOD_SRC)
357#define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU) 368#define rsnd_io_to_mod_ctu(io) rsnd_io_to_mod((io), RSND_MOD_CTU)
369#define rsnd_io_to_mod_mix(io) rsnd_io_to_mod((io), RSND_MOD_MIX)
358#define rsnd_io_to_mod_dvc(io) rsnd_io_to_mod((io), RSND_MOD_DVC) 370#define rsnd_io_to_mod_dvc(io) rsnd_io_to_mod((io), RSND_MOD_DVC)
359#define rsnd_io_to_rdai(io) ((io)->rdai) 371#define rsnd_io_to_rdai(io) ((io)->rdai)
360#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io))) 372#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io)))
@@ -473,6 +485,12 @@ struct rsnd_priv {
473 int ctu_nr; 485 int ctu_nr;
474 486
475 /* 487 /*
488 * below value will be filled on rsnd_mix_probe()
489 */
490 void *mix;
491 int mix_nr;
492
493 /*
476 * below value will be filled on rsnd_dvc_probe() 494 * below value will be filled on rsnd_dvc_probe()
477 */ 495 */
478 void *dvc; 496 void *dvc;
@@ -589,6 +607,17 @@ void rsnd_ctu_remove(struct platform_device *pdev,
589struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id); 607struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
590 608
591/* 609/*
610 * R-Car MIX
611 */
612int rsnd_mix_probe(struct platform_device *pdev,
613 const struct rsnd_of_data *of_data,
614 struct rsnd_priv *priv);
615
616void rsnd_mix_remove(struct platform_device *pdev,
617 struct rsnd_priv *priv);
618struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
619
620/*
592 * R-Car DVC 621 * R-Car DVC
593 */ 622 */
594int rsnd_dvc_probe(struct platform_device *pdev, 623int rsnd_dvc_probe(struct platform_device *pdev,