Skip to content

Commit 9269e3c

Browse files
morimotobroonie
authored andcommitted
ASoC: rsnd: add CTU (Channel Transfer Unit) prototype support
This patch adds CTU (Channel Transfer Unit) support for rsnd driver. But, it does nothing to data at this point, but is required for MIX support. CTU design is a little different from other IPs (CTU0 is including CTU00 - CTU03, and CTU1 is including CTU10 - CTU13, these have different register mapping) We need to care about it on this driver. Signed-off-by: Kuninori Morimoto <[email protected]> Tested-by: Keita Kobayashi <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 7dfb491 commit 9269e3c

File tree

8 files changed

+236
-6
lines changed

8 files changed

+236
-6
lines changed

Documentation/devicetree/bindings/sound/renesas,rsnd.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Required properties:
1818
- rcar_sound,src : Should contain SRC feature.
1919
The number of SRC subnode should be same as HW.
2020
see below for detail.
21+
- rcar_sound,ctu : Should contain CTU feature.
22+
The number of CTU subnode should be same as HW.
23+
see below for detail.
2124
- rcar_sound,dvc : Should contain DVC feature.
2225
The number of DVC subnode should be same as HW.
2326
see below for detail.
@@ -90,6 +93,17 @@ rcar_sound: sound@ec500000 {
9093
};
9194
};
9295

96+
rcar_sound,ctu {
97+
ctu00: ctu@0 { };
98+
ctu01: ctu@1 { };
99+
ctu02: ctu@2 { };
100+
ctu03: ctu@3 { };
101+
ctu10: ctu@4 { };
102+
ctu11: ctu@5 { };
103+
ctu12: ctu@6 { };
104+
ctu13: ctu@7 { };
105+
};
106+
93107
rcar_sound,src {
94108
src0: src@0 {
95109
interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>;

include/sound/rcar_snd.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,18 @@ struct rsnd_src_platform_info {
6161
/*
6262
* flags
6363
*/
64+
struct rsnd_ctu_platform_info {
65+
u32 flags;
66+
};
67+
6468
struct rsnd_dvc_platform_info {
6569
u32 flags;
6670
};
6771

6872
struct rsnd_dai_path_info {
6973
struct rsnd_ssi_platform_info *ssi;
7074
struct rsnd_src_platform_info *src;
75+
struct rsnd_ctu_platform_info *ctu;
7176
struct rsnd_dvc_platform_info *dvc;
7277
};
7378

@@ -93,6 +98,8 @@ struct rcar_snd_info {
9398
int ssi_info_nr;
9499
struct rsnd_src_platform_info *src_info;
95100
int src_info_nr;
101+
struct rsnd_ctu_platform_info *ctu_info;
102+
int ctu_info_nr;
96103
struct rsnd_dvc_platform_info *dvc_info;
97104
int dvc_info_nr;
98105
struct rsnd_dai_platform_info *dai_info;

sound/soc/sh/rcar/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o dvc.o
1+
snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o src.o ctu.o dvc.o
22
obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o
33

44
snd-soc-rsrc-card-objs := rsrc-card.o

sound/soc/sh/rcar/core.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,11 @@ static int rsnd_path_init(struct rsnd_priv *priv,
651651
if (ret < 0)
652652
return ret;
653653

654+
/* CTU */
655+
ret = rsnd_path_add(priv, io, ctu);
656+
if (ret < 0)
657+
return ret;
658+
654659
/* DVC */
655660
ret = rsnd_path_add(priv, io, dvc);
656661
if (ret < 0)
@@ -666,13 +671,14 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
666671
struct device_node *dai_node, *dai_np;
667672
struct device_node *ssi_node, *ssi_np;
668673
struct device_node *src_node, *src_np;
674+
struct device_node *ctu_node, *ctu_np;
669675
struct device_node *dvc_node, *dvc_np;
670676
struct device_node *playback, *capture;
671677
struct rsnd_dai_platform_info *dai_info;
672678
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
673679
struct device *dev = &pdev->dev;
674680
int nr, i;
675-
int dai_i, ssi_i, src_i, dvc_i;
681+
int dai_i, ssi_i, src_i, ctu_i, dvc_i;
676682

677683
if (!of_data)
678684
return;
@@ -698,6 +704,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
698704

699705
ssi_node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
700706
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");
701708
dvc_node = of_get_child_by_name(dev->of_node, "rcar_sound,dvc");
702709

703710
#define mod_parse(name) \
@@ -734,6 +741,7 @@ if (name##_node) { \
734741

735742
mod_parse(ssi);
736743
mod_parse(src);
744+
mod_parse(ctu);
737745
mod_parse(dvc);
738746

739747
of_node_put(playback);
@@ -1146,6 +1154,7 @@ static int rsnd_probe(struct platform_device *pdev)
11461154
rsnd_dma_probe,
11471155
rsnd_ssi_probe,
11481156
rsnd_src_probe,
1157+
rsnd_ctu_probe,
11491158
rsnd_dvc_probe,
11501159
rsnd_adg_probe,
11511160
rsnd_dai_probe,
@@ -1241,6 +1250,7 @@ static int rsnd_remove(struct platform_device *pdev)
12411250
struct rsnd_priv *priv) = {
12421251
rsnd_ssi_remove,
12431252
rsnd_src_remove,
1253+
rsnd_ctu_remove,
12441254
rsnd_dvc_remove,
12451255
};
12461256
int ret = 0, i;

sound/soc/sh/rcar/ctu.c

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* ctu.c
3+
*
4+
* Copyright (c) 2015 Kuninori Morimoto <[email protected]>
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 CTU_NAME_SIZE 16
13+
#define CTU_NAME "ctu"
14+
15+
struct rsnd_ctu {
16+
struct rsnd_ctu_platform_info *info; /* rcar_snd.h */
17+
struct rsnd_mod mod;
18+
};
19+
20+
#define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
21+
#define for_each_rsnd_ctu(pos, priv, i) \
22+
for ((i) = 0; \
23+
((i) < rsnd_ctu_nr(priv)) && \
24+
((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \
25+
i++)
26+
27+
#define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1)
28+
#define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0)
29+
static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable)
30+
{
31+
rsnd_mod_write(mod, CTU_CTUIR, enable);
32+
}
33+
34+
static int rsnd_ctu_init(struct rsnd_mod *mod,
35+
struct rsnd_dai_stream *io,
36+
struct rsnd_priv *priv)
37+
{
38+
rsnd_mod_hw_start(mod);
39+
40+
rsnd_ctu_initialize_lock(mod);
41+
42+
rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io));
43+
44+
rsnd_ctu_initialize_unlock(mod);
45+
46+
return 0;
47+
}
48+
49+
static int rsnd_ctu_quit(struct rsnd_mod *mod,
50+
struct rsnd_dai_stream *io,
51+
struct rsnd_priv *priv)
52+
{
53+
rsnd_mod_hw_stop(mod);
54+
55+
return 0;
56+
}
57+
58+
static struct rsnd_mod_ops rsnd_ctu_ops = {
59+
.name = CTU_NAME,
60+
.init = rsnd_ctu_init,
61+
.quit = rsnd_ctu_quit,
62+
};
63+
64+
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
65+
{
66+
if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
67+
id = 0;
68+
69+
return &((struct rsnd_ctu *)(priv->ctu) + id)->mod;
70+
}
71+
72+
void rsnd_of_parse_ctu(struct platform_device *pdev,
73+
const struct rsnd_of_data *of_data,
74+
struct rsnd_priv *priv)
75+
{
76+
struct device_node *node;
77+
struct rsnd_ctu_platform_info *ctu_info;
78+
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
79+
struct device *dev = &pdev->dev;
80+
int nr;
81+
82+
if (!of_data)
83+
return;
84+
85+
node = of_get_child_by_name(dev->of_node, "rcar_sound,ctu");
86+
if (!node)
87+
return;
88+
89+
nr = of_get_child_count(node);
90+
if (!nr)
91+
goto rsnd_of_parse_ctu_end;
92+
93+
ctu_info = devm_kzalloc(dev,
94+
sizeof(struct rsnd_ctu_platform_info) * nr,
95+
GFP_KERNEL);
96+
if (!ctu_info) {
97+
dev_err(dev, "ctu info allocation error\n");
98+
goto rsnd_of_parse_ctu_end;
99+
}
100+
101+
info->ctu_info = ctu_info;
102+
info->ctu_info_nr = nr;
103+
104+
rsnd_of_parse_ctu_end:
105+
of_node_put(node);
106+
107+
}
108+
109+
int rsnd_ctu_probe(struct platform_device *pdev,
110+
const struct rsnd_of_data *of_data,
111+
struct rsnd_priv *priv)
112+
{
113+
struct rcar_snd_info *info = rsnd_priv_to_info(priv);
114+
struct device *dev = rsnd_priv_to_dev(priv);
115+
struct rsnd_ctu *ctu;
116+
struct clk *clk;
117+
char name[CTU_NAME_SIZE];
118+
int i, nr, ret;
119+
120+
/* This driver doesn't support Gen1 at this point */
121+
if (rsnd_is_gen1(priv)) {
122+
dev_warn(dev, "CTU is not supported on Gen1\n");
123+
return -EINVAL;
124+
}
125+
126+
rsnd_of_parse_ctu(pdev, of_data, priv);
127+
128+
nr = info->ctu_info_nr;
129+
if (!nr)
130+
return 0;
131+
132+
ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL);
133+
if (!ctu)
134+
return -ENOMEM;
135+
136+
priv->ctu_nr = nr;
137+
priv->ctu = ctu;
138+
139+
for_each_rsnd_ctu(ctu, priv, i) {
140+
/*
141+
* CTU00, CTU01, CTU02, CTU03 => CTU0
142+
* CTU10, CTU11, CTU12, CTU13 => CTU1
143+
*/
144+
snprintf(name, CTU_NAME_SIZE, "%s.%d",
145+
CTU_NAME, i / 4);
146+
147+
clk = devm_clk_get(dev, name);
148+
if (IS_ERR(clk))
149+
return PTR_ERR(clk);
150+
151+
ctu->info = &info->ctu_info[i];
152+
153+
ret = rsnd_mod_init(priv, &ctu->mod, &rsnd_ctu_ops,
154+
clk, RSND_MOD_CTU, i);
155+
if (ret)
156+
return ret;
157+
}
158+
159+
return 0;
160+
}
161+
162+
void rsnd_ctu_remove(struct platform_device *pdev,
163+
struct rsnd_priv *priv)
164+
{
165+
struct rsnd_ctu *ctu;
166+
int i;
167+
168+
for_each_rsnd_ctu(ctu, priv, i) {
169+
rsnd_mod_quit(&ctu->mod);
170+
}
171+
}

sound/soc/sh/rcar/dma.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,8 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
426426
phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU);
427427
int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod);
428428
int use_src = !!rsnd_io_to_mod_src(io);
429-
int use_dvc = !!rsnd_io_to_mod_dvc(io);
429+
int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
430+
!!rsnd_io_to_mod_ctu(io);
430431
int id = rsnd_mod_id(mod);
431432
struct dma_addr {
432433
dma_addr_t out_addr;
@@ -464,16 +465,16 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
464465
};
465466

466467
/* it shouldn't happen */
467-
if (use_dvc && !use_src)
468+
if (use_cmd && !use_src)
468469
dev_err(dev, "DVC is selected without SRC\n");
469470

470471
/* use SSIU or SSI ? */
471472
if (is_ssi && rsnd_ssi_use_busif(io, mod))
472473
is_ssi++;
473474

474475
return (is_from) ?
475-
dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr :
476-
dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr;
476+
dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr :
477+
dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
477478
}
478479

479480
static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
@@ -504,6 +505,7 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
504505
struct rsnd_mod *this = rsnd_dma_to_mod(dma);
505506
struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
506507
struct rsnd_mod *src = rsnd_io_to_mod_src(io);
508+
struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io);
507509
struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
508510
struct rsnd_mod *mod[MOD_MAX];
509511
struct rsnd_mod *mod_start, *mod_end;
@@ -543,6 +545,9 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma,
543545
if (src) {
544546
mod[i] = src;
545547
src = NULL;
548+
} else if (ctu) {
549+
mod[i] = ctu;
550+
ctu = NULL;
546551
} else if (dvc) {
547552
mod[i] = dvc;
548553
dvc = NULL;

sound/soc/sh/rcar/gen.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
240240
RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
241241
RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40),
242242
RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
243+
RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
244+
RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
243245
RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
244246
RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
245247
RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),

0 commit comments

Comments
 (0)