Skip to content

Commit ef19ecf

Browse files
John Madieubroonie
authored andcommitted
ASoC: rsnd: Add system suspend/resume support
Add system suspend/resume support for the ASoC rsnd driver, required for RZ/G3E platforms. Distribute the per-module suspend/resume work across the relevant files (adg.c, ssi.c, ssiu.c, src.c, ctu.c, mix.c, dvc.c, dma.c) rather than centralising it in core.c. Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com> Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://patch.msgid.link/20260525110230.4014435-19-john.madieu.xa@bp.renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent ec1b5eb commit ef19ecf

10 files changed

Lines changed: 241 additions & 2 deletions

File tree

sound/soc/renesas/rcar/adg.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,3 +953,29 @@ void rsnd_adg_remove(struct rsnd_priv *priv)
953953
/* It should be called after rsnd_adg_clk_disable() */
954954
rsnd_adg_null_clk_clean(priv);
955955
}
956+
957+
static struct rsnd_mod *rsnd_adg_mod_get(struct rsnd_priv *priv)
958+
{
959+
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
960+
961+
if (!adg)
962+
return NULL;
963+
964+
return rsnd_mod_get(adg);
965+
}
966+
967+
void rsnd_adg_suspend(struct rsnd_priv *priv)
968+
{
969+
struct rsnd_mod *mod = rsnd_adg_mod_get(priv);
970+
971+
if (mod)
972+
rsnd_suspend_clk_reset(mod->clk, mod->rstc);
973+
}
974+
975+
void rsnd_adg_resume(struct rsnd_priv *priv)
976+
{
977+
struct rsnd_mod *mod = rsnd_adg_mod_get(priv);
978+
979+
if (mod)
980+
rsnd_resume_clk_reset(mod->clk, mod->rstc);
981+
}

sound/soc/renesas/rcar/core.c

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,8 @@ static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
962962
static const struct snd_pcm_hardware rsnd_pcm_hardware = {
963963
.info = SNDRV_PCM_INFO_INTERLEAVED |
964964
SNDRV_PCM_INFO_MMAP |
965-
SNDRV_PCM_INFO_MMAP_VALID,
965+
SNDRV_PCM_INFO_MMAP_VALID |
966+
SNDRV_PCM_INFO_RESUME,
966967
.buffer_bytes_max = 64 * 1024,
967968
.period_bytes_min = 32,
968969
.period_bytes_max = 8192,
@@ -2159,11 +2160,35 @@ static void rsnd_remove(struct platform_device *pdev)
21592160
remove_func[i](priv);
21602161
}
21612162

2163+
void rsnd_suspend_clk_reset(struct clk *clk, struct reset_control *rstc)
2164+
{
2165+
clk_unprepare(clk);
2166+
reset_control_assert(rstc);
2167+
}
2168+
2169+
void rsnd_resume_clk_reset(struct clk *clk, struct reset_control *rstc)
2170+
{
2171+
reset_control_deassert(rstc);
2172+
clk_prepare(clk);
2173+
}
2174+
21622175
static int rsnd_suspend(struct device *dev)
21632176
{
21642177
struct rsnd_priv *priv = dev_get_drvdata(dev);
21652178

2179+
/*
2180+
* Reverse order of probe:
2181+
* ADG -> DVC -> MIX -> CTU -> SRC -> SSIU -> SSI -> DMA
2182+
*/
21662183
rsnd_adg_clk_disable(priv);
2184+
rsnd_adg_suspend(priv);
2185+
rsnd_dvc_suspend(priv);
2186+
rsnd_mix_suspend(priv);
2187+
rsnd_ctu_suspend(priv);
2188+
rsnd_src_suspend(priv);
2189+
rsnd_ssiu_suspend(priv);
2190+
rsnd_ssi_suspend(priv);
2191+
rsnd_dma_suspend(priv);
21672192

21682193
return 0;
21692194
}
@@ -2172,7 +2197,21 @@ static int rsnd_resume(struct device *dev)
21722197
{
21732198
struct rsnd_priv *priv = dev_get_drvdata(dev);
21742199

2175-
return rsnd_adg_clk_enable(priv);
2200+
/*
2201+
* Same order as probe:
2202+
* DMA -> SSI -> SSIU -> SRC -> CTU -> MIX -> DVC -> ADG
2203+
*/
2204+
rsnd_dma_resume(priv);
2205+
rsnd_ssi_resume(priv);
2206+
rsnd_ssiu_resume(priv);
2207+
rsnd_src_resume(priv);
2208+
rsnd_ctu_resume(priv);
2209+
rsnd_mix_resume(priv);
2210+
rsnd_dvc_resume(priv);
2211+
rsnd_adg_resume(priv);
2212+
rsnd_adg_clk_enable(priv);
2213+
2214+
return 0;
21762215
}
21772216

21782217
static const struct dev_pm_ops rsnd_pm_ops = {

sound/soc/renesas/rcar/ctu.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,3 +378,23 @@ void rsnd_ctu_remove(struct rsnd_priv *priv)
378378
rsnd_mod_quit(rsnd_mod_get(ctu));
379379
}
380380
}
381+
382+
void rsnd_ctu_suspend(struct rsnd_priv *priv)
383+
{
384+
struct rsnd_ctu *ctu;
385+
int i;
386+
387+
for_each_rsnd_ctu(ctu, priv, i)
388+
rsnd_suspend_clk_reset(rsnd_mod_get(ctu)->clk,
389+
rsnd_mod_get(ctu)->rstc);
390+
}
391+
392+
void rsnd_ctu_resume(struct rsnd_priv *priv)
393+
{
394+
struct rsnd_ctu *ctu;
395+
int i;
396+
397+
for_each_rsnd_ctu(ctu, priv, i)
398+
rsnd_resume_clk_reset(rsnd_mod_get(ctu)->clk,
399+
rsnd_mod_get(ctu)->rstc);
400+
}

sound/soc/renesas/rcar/dma.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,3 +1035,25 @@ int rsnd_dma_probe(struct rsnd_priv *priv)
10351035
/* dummy mem mod for debug */
10361036
return rsnd_mod_init(NULL, &mem, &mem_ops, NULL, NULL, 0, 0);
10371037
}
1038+
1039+
void rsnd_dma_suspend(struct rsnd_priv *priv)
1040+
{
1041+
struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
1042+
1043+
if (dmac) {
1044+
/* Mirror probe (which enables clk before deasserting reset) */
1045+
rsnd_suspend_clk_reset(NULL, dmac->audmapp_rstc);
1046+
clk_disable_unprepare(dmac->audmapp_clk);
1047+
}
1048+
}
1049+
1050+
void rsnd_dma_resume(struct rsnd_priv *priv)
1051+
{
1052+
struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
1053+
1054+
if (dmac) {
1055+
/* Clock must be stable before reset is deasserted */
1056+
clk_prepare_enable(dmac->audmapp_clk);
1057+
rsnd_resume_clk_reset(NULL, dmac->audmapp_rstc);
1058+
}
1059+
}

sound/soc/renesas/rcar/dvc.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,23 @@ void rsnd_dvc_remove(struct rsnd_priv *priv)
381381
rsnd_mod_quit(rsnd_mod_get(dvc));
382382
}
383383
}
384+
385+
void rsnd_dvc_suspend(struct rsnd_priv *priv)
386+
{
387+
struct rsnd_dvc *dvc;
388+
int i;
389+
390+
for_each_rsnd_dvc(dvc, priv, i)
391+
rsnd_suspend_clk_reset(rsnd_mod_get(dvc)->clk,
392+
rsnd_mod_get(dvc)->rstc);
393+
}
394+
395+
void rsnd_dvc_resume(struct rsnd_priv *priv)
396+
{
397+
struct rsnd_dvc *dvc;
398+
int i;
399+
400+
for_each_rsnd_dvc(dvc, priv, i)
401+
rsnd_resume_clk_reset(rsnd_mod_get(dvc)->clk,
402+
rsnd_mod_get(dvc)->rstc);
403+
}

sound/soc/renesas/rcar/mix.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,23 @@ void rsnd_mix_remove(struct rsnd_priv *priv)
345345
rsnd_mod_quit(rsnd_mod_get(mix));
346346
}
347347
}
348+
349+
void rsnd_mix_suspend(struct rsnd_priv *priv)
350+
{
351+
struct rsnd_mix *mix;
352+
int i;
353+
354+
for_each_rsnd_mix(mix, priv, i)
355+
rsnd_suspend_clk_reset(rsnd_mod_get(mix)->clk,
356+
rsnd_mod_get(mix)->rstc);
357+
}
358+
359+
void rsnd_mix_resume(struct rsnd_priv *priv)
360+
{
361+
struct rsnd_mix *mix;
362+
int i;
363+
364+
for_each_rsnd_mix(mix, priv, i)
365+
rsnd_resume_clk_reset(rsnd_mod_get(mix)->clk,
366+
rsnd_mod_get(mix)->rstc);
367+
}

sound/soc/renesas/rcar/rsnd.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
267267
int rsnd_dma_attach(struct rsnd_dai_stream *io,
268268
struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
269269
int rsnd_dma_probe(struct rsnd_priv *priv);
270+
void rsnd_dma_suspend(struct rsnd_priv *priv);
271+
void rsnd_dma_resume(struct rsnd_priv *priv);
270272
struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name,
271273
struct rsnd_mod *mod, char *x);
272274

@@ -429,6 +431,8 @@ int rsnd_mod_init(struct rsnd_priv *priv,
429431
enum rsnd_mod_type type,
430432
int id);
431433
void rsnd_mod_quit(struct rsnd_mod *mod);
434+
void rsnd_suspend_clk_reset(struct clk *clk, struct reset_control *rstc);
435+
void rsnd_resume_clk_reset(struct clk *clk, struct reset_control *rstc);
432436
struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
433437
struct rsnd_mod *mod);
434438
void rsnd_mod_interrupt(struct rsnd_mod *mod,
@@ -625,6 +629,8 @@ int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod);
625629
int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate);
626630
int rsnd_adg_probe(struct rsnd_priv *priv);
627631
void rsnd_adg_remove(struct rsnd_priv *priv);
632+
void rsnd_adg_suspend(struct rsnd_priv *priv);
633+
void rsnd_adg_resume(struct rsnd_priv *priv);
628634
int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
629635
struct rsnd_dai_stream *io,
630636
unsigned int in_rate,
@@ -822,6 +828,8 @@ extern const char * const volume_ramp_rate[];
822828
*/
823829
int rsnd_ssi_probe(struct rsnd_priv *priv);
824830
void rsnd_ssi_remove(struct rsnd_priv *priv);
831+
void rsnd_ssi_suspend(struct rsnd_priv *priv);
832+
void rsnd_ssi_resume(struct rsnd_priv *priv);
825833
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
826834
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io);
827835
u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io);
@@ -845,6 +853,8 @@ int rsnd_ssiu_attach(struct rsnd_dai_stream *io,
845853
struct rsnd_mod *mod);
846854
int rsnd_ssiu_probe(struct rsnd_priv *priv);
847855
void rsnd_ssiu_remove(struct rsnd_priv *priv);
856+
void rsnd_ssiu_suspend(struct rsnd_priv *priv);
857+
void rsnd_ssiu_resume(struct rsnd_priv *priv);
848858
void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
849859
struct device_node *playback,
850860
struct device_node *capture);
@@ -856,6 +866,8 @@ bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod);
856866
*/
857867
int rsnd_src_probe(struct rsnd_priv *priv);
858868
void rsnd_src_remove(struct rsnd_priv *priv);
869+
void rsnd_src_suspend(struct rsnd_priv *priv);
870+
void rsnd_src_resume(struct rsnd_priv *priv);
859871
struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
860872

861873
#define rsnd_src_get_in_rate(priv, io) rsnd_src_get_rate(priv, io, 1)
@@ -875,6 +887,8 @@ unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
875887
*/
876888
int rsnd_ctu_probe(struct rsnd_priv *priv);
877889
void rsnd_ctu_remove(struct rsnd_priv *priv);
890+
void rsnd_ctu_suspend(struct rsnd_priv *priv);
891+
void rsnd_ctu_resume(struct rsnd_priv *priv);
878892
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
879893
#define rsnd_ctu_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_CTU)
880894
#define rsnd_parse_connect_ctu(rdai, playback, capture) \
@@ -887,6 +901,8 @@ struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
887901
*/
888902
int rsnd_mix_probe(struct rsnd_priv *priv);
889903
void rsnd_mix_remove(struct rsnd_priv *priv);
904+
void rsnd_mix_suspend(struct rsnd_priv *priv);
905+
void rsnd_mix_resume(struct rsnd_priv *priv);
890906
struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
891907
#define rsnd_mix_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_MIX)
892908
#define rsnd_parse_connect_mix(rdai, playback, capture) \
@@ -899,6 +915,8 @@ struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
899915
*/
900916
int rsnd_dvc_probe(struct rsnd_priv *priv);
901917
void rsnd_dvc_remove(struct rsnd_priv *priv);
918+
void rsnd_dvc_suspend(struct rsnd_priv *priv);
919+
void rsnd_dvc_resume(struct rsnd_priv *priv);
902920
struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
903921
#define rsnd_dvc_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_DVC)
904922
#define rsnd_parse_connect_dvc(rdai, playback, capture) \

sound/soc/renesas/rcar/src.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,3 +834,37 @@ void rsnd_src_remove(struct rsnd_priv *priv)
834834
rsnd_mod_quit(rsnd_mod_get(src));
835835
}
836836
}
837+
838+
void rsnd_src_suspend(struct rsnd_priv *priv)
839+
{
840+
struct rsnd_src_ctrl *src_ctrl = rsnd_priv_to_src_ctrl(priv);
841+
struct rsnd_src *src;
842+
int i;
843+
844+
if (!src_ctrl)
845+
return;
846+
847+
for_each_rsnd_src(src, priv, i)
848+
rsnd_suspend_clk_reset(rsnd_mod_get(src)->clk,
849+
rsnd_mod_get(src)->rstc);
850+
851+
clk_disable_unprepare(src_ctrl->scu_x2);
852+
clk_disable_unprepare(src_ctrl->scu);
853+
}
854+
855+
void rsnd_src_resume(struct rsnd_priv *priv)
856+
{
857+
struct rsnd_src_ctrl *src_ctrl = rsnd_priv_to_src_ctrl(priv);
858+
struct rsnd_src *src;
859+
int i;
860+
861+
if (!src_ctrl)
862+
return;
863+
864+
clk_prepare_enable(src_ctrl->scu);
865+
clk_prepare_enable(src_ctrl->scu_x2);
866+
867+
for_each_rsnd_src(src, priv, i)
868+
rsnd_resume_clk_reset(rsnd_mod_get(src)->clk,
869+
rsnd_mod_get(src)->rstc);
870+
}

sound/soc/renesas/rcar/ssi.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,3 +1257,23 @@ void rsnd_ssi_remove(struct rsnd_priv *priv)
12571257
rsnd_mod_quit(rsnd_mod_get(ssi));
12581258
}
12591259
}
1260+
1261+
void rsnd_ssi_suspend(struct rsnd_priv *priv)
1262+
{
1263+
struct rsnd_ssi *ssi;
1264+
int i;
1265+
1266+
for_each_rsnd_ssi(ssi, priv, i)
1267+
rsnd_suspend_clk_reset(rsnd_mod_get(ssi)->clk,
1268+
rsnd_mod_get(ssi)->rstc);
1269+
}
1270+
1271+
void rsnd_ssi_resume(struct rsnd_priv *priv)
1272+
{
1273+
struct rsnd_ssi *ssi;
1274+
int i;
1275+
1276+
for_each_rsnd_ssi(ssi, priv, i)
1277+
rsnd_resume_clk_reset(rsnd_mod_get(ssi)->clk,
1278+
rsnd_mod_get(ssi)->rstc);
1279+
}

sound/soc/renesas/rcar/ssiu.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,3 +629,23 @@ void rsnd_ssiu_remove(struct rsnd_priv *priv)
629629
rsnd_mod_quit(rsnd_mod_get(ssiu));
630630
}
631631
}
632+
633+
void rsnd_ssiu_suspend(struct rsnd_priv *priv)
634+
{
635+
struct rsnd_ssiu *ssiu;
636+
int i;
637+
638+
for_each_rsnd_ssiu(ssiu, priv, i)
639+
rsnd_suspend_clk_reset(rsnd_mod_get(ssiu)->clk,
640+
rsnd_mod_get(ssiu)->rstc);
641+
}
642+
643+
void rsnd_ssiu_resume(struct rsnd_priv *priv)
644+
{
645+
struct rsnd_ssiu *ssiu;
646+
int i;
647+
648+
for_each_rsnd_ssiu(ssiu, priv, i)
649+
rsnd_resume_clk_reset(rsnd_mod_get(ssiu)->clk,
650+
rsnd_mod_get(ssiu)->rstc);
651+
}

0 commit comments

Comments
 (0)