From 7674bec4fc09e85803a8f2bd26a013d0076a80a9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 25 Dec 2018 14:05:28 +0900 Subject: ASoC: rsnd: update BSDSR/BSDISR handling Current BSDSR/BSDISR are using temporary/generic settings, but it can't handle all SRCx/SoC. It needs to handle correctry. Otherwise, sampling rate converted sound channel will be broken if it was TDM. One note is that it needs to overwrite settings on E3 case. Signed-off-by: Kuninori Morimoto Tested-by: chaoliang qin Tested-by: Yusuke Goda Signed-off-by: Mark Brown --- sound/soc/sh/rcar/src.c | 125 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 115 insertions(+), 10 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 50348a2c9203..db81e066b92e 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -14,6 +14,7 @@ */ #include "rsnd.h" +#include #define SRC_NAME "src" @@ -134,20 +135,83 @@ unsigned int rsnd_src_get_rate(struct rsnd_priv *priv, return rate; } +const static u32 bsdsr_table_pattern1[] = { + 0x01800000, /* 6 - 1/6 */ + 0x01000000, /* 6 - 1/4 */ + 0x00c00000, /* 6 - 1/3 */ + 0x00800000, /* 6 - 1/2 */ + 0x00600000, /* 6 - 2/3 */ + 0x00400000, /* 6 - 1 */ +}; + +const static u32 bsdsr_table_pattern2[] = { + 0x02400000, /* 6 - 1/6 */ + 0x01800000, /* 6 - 1/4 */ + 0x01200000, /* 6 - 1/3 */ + 0x00c00000, /* 6 - 1/2 */ + 0x00900000, /* 6 - 2/3 */ + 0x00600000, /* 6 - 1 */ +}; + +const static u32 bsisr_table[] = { + 0x00100060, /* 6 - 1/6 */ + 0x00100040, /* 6 - 1/4 */ + 0x00100030, /* 6 - 1/3 */ + 0x00100020, /* 6 - 1/2 */ + 0x00100020, /* 6 - 2/3 */ + 0x00100020, /* 6 - 1 */ +}; + +const static u32 chan288888[] = { + 0x00000006, /* 1 to 2 */ + 0x000001fe, /* 1 to 8 */ + 0x000001fe, /* 1 to 8 */ + 0x000001fe, /* 1 to 8 */ + 0x000001fe, /* 1 to 8 */ + 0x000001fe, /* 1 to 8 */ +}; + +const static u32 chan244888[] = { + 0x00000006, /* 1 to 2 */ + 0x0000001e, /* 1 to 4 */ + 0x0000001e, /* 1 to 4 */ + 0x000001fe, /* 1 to 8 */ + 0x000001fe, /* 1 to 8 */ + 0x000001fe, /* 1 to 8 */ +}; + +const static u32 chan222222[] = { + 0x00000006, /* 1 to 2 */ + 0x00000006, /* 1 to 2 */ + 0x00000006, /* 1 to 2 */ + 0x00000006, /* 1 to 2 */ + 0x00000006, /* 1 to 2 */ + 0x00000006, /* 1 to 2 */ +}; + +static const struct soc_device_attribute ov_soc[] = { + { .soc_id = "r8a77990" }, /* E3 */ + { /* sentinel */ } +}; + static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, struct rsnd_mod *mod) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + const struct soc_device_attribute *soc = soc_device_match(ov_soc); int is_play = rsnd_io_is_play(io); int use_src = 0; u32 fin, fout; u32 ifscr, fsrate, adinr; u32 cr, route; - u32 bsdsr, bsisr; u32 i_busif, o_busif, tmp; + const u32 *bsdsr_table; + const u32 *chptn; uint ratio; + int chan; + int idx; if (!runtime) return; @@ -155,6 +219,8 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, fin = rsnd_src_get_in_rate(priv, io); fout = rsnd_src_get_out_rate(priv, io); + chan = rsnd_runtime_channel_original(io); + /* 6 - 1/6 are very enough ratio for SRC_BSDSR */ if (fin == fout) ratio = 0; @@ -173,8 +239,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, /* * SRC_ADINR */ - adinr = rsnd_get_adinr_bit(mod, io) | - rsnd_runtime_channel_original(io); + adinr = rsnd_get_adinr_bit(mod, io) | chan; /* * SRC_IFSCR / SRC_IFSVR @@ -207,21 +272,56 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, /* * SRC_BSDSR / SRC_BSISR + * + * see + * Combination of Register Setting Related to + * FSO/FSI Ratio and Channel, Latency */ switch (rsnd_mod_id(mod)) { + case 0: + chptn = chan288888; + bsdsr_table = bsdsr_table_pattern1; + break; + case 1: + case 3: + case 4: + chptn = chan244888; + bsdsr_table = bsdsr_table_pattern1; + break; + case 2: + case 9: + chptn = chan222222; + bsdsr_table = bsdsr_table_pattern1; + break; case 5: case 6: case 7: case 8: - bsdsr = 0x02400000; /* 6 - 1/6 */ - bsisr = 0x00100060; /* 6 - 1/6 */ + chptn = chan222222; + bsdsr_table = bsdsr_table_pattern2; break; default: - bsdsr = 0x01800000; /* 6 - 1/6 */ - bsisr = 0x00100060 ;/* 6 - 1/6 */ - break; + goto convert_rate_err; } + /* + * E3 need to overwrite + */ + if (soc) + switch (rsnd_mod_id(mod)) { + case 0: + case 4: + chptn = chan222222; + } + + for (idx = 0; idx < ARRAY_SIZE(chan222222); idx++) + if (chptn[idx] & (1 << chan)) + break; + + if (chan > 8 || + idx >= ARRAY_SIZE(chan222222)) + goto convert_rate_err; + /* BUSIF_MODE */ tmp = rsnd_get_busif_shift(io, mod); i_busif = ( is_play ? tmp : 0) | 1; @@ -234,8 +334,8 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, rsnd_mod_write(mod, SRC_IFSCR, ifscr); rsnd_mod_write(mod, SRC_IFSVR, fsrate); rsnd_mod_write(mod, SRC_SRCCR, cr); - rsnd_mod_write(mod, SRC_BSDSR, bsdsr); - rsnd_mod_write(mod, SRC_BSISR, bsisr); + rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]); + rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]); rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */ rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif); @@ -244,6 +344,11 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout); + + return; + +convert_rate_err: + dev_err(dev, "unknown BSDSR/BSDIR settings\n"); } static int rsnd_src_irq(struct rsnd_mod *mod, -- cgit v1.2.3 From 7aea8a9d71d54f449f49e20324df06341cc18395 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 1 Feb 2019 16:49:30 +0900 Subject: ASoC: rsnd: fixup MIX kctrl registration Renesas sound device has many IPs and many situations. If platform/board uses MIXer, situation will be more complex. To avoid duplicate DVC kctrl registration when MIXer was used, it had original flags. But it was issue when sound card was re-binded, because no one can't cleanup this flags then. To solve this issue, commit 9c698e8481a15237a ("ASoC: rsnd: tidyup registering method for rsnd_kctrl_new()") checks registered card->controls, because if card was re-binded, these were cleanuped automatically. This patch could solve re-binding issue. But, it start to avoid MIX kctrl. To solve these issues, we need below. To avoid card re-binding issue: check registered card->controls To avoid duplicate DVC registration: check registered rsnd_kctrl_cfg To allow multiple MIX registration: check registered rsnd_kctrl_cfg This patch do it. Fixes: 9c698e8481a15237a ("ASoC: rsnd: tidyup registering method for rsnd_kctrl_new()") Reported-by: Jiada Wang Signed-off-by: Kuninori Morimoto Tested-By: Jiada Wang Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 59e250cc2e9d..e819e965e1db 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1526,14 +1526,14 @@ int rsnd_kctrl_new(struct rsnd_mod *mod, int ret; /* - * 1) Avoid duplicate register (ex. MIXer case) - * 2) re-register if card was rebinded + * 1) Avoid duplicate register for DVC with MIX case + * 2) Allow duplicate register for MIX + * 3) re-register if card was rebinded */ list_for_each_entry(kctrl, &card->controls, list) { struct rsnd_kctrl_cfg *c = kctrl->private_data; - if (strcmp(kctrl->id.name, name) == 0 && - c->mod == mod) + if (c == cfg) return 0; } -- cgit v1.2.3 From f497c88b195eaee8733a304f2a1dc27fb319c9c3 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 1 Feb 2019 16:46:27 +0900 Subject: ASoC: rsnd: synchronize connection check for simple-card/audio-graph Current rsnd driver has below function to check connection rsnd_parse_connect_simple() rsnd_parse_connect_graph() But these have different parameters. This patch synchronize these for cleanup. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 59e250cc2e9d..2a48d8a6cc76 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1032,16 +1032,13 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { }; static void rsnd_parse_connect_simple(struct rsnd_priv *priv, - struct device_node *dai_np, - int dai_i, int is_play) + struct rsnd_dai_stream *io, + struct device_node *dai_np) { struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); - struct rsnd_dai_stream *io = is_play ? - &rdai->playback : - &rdai->capture; struct device_node *ssiu_np = rsnd_ssiu_of_node(priv); struct device_node *np; + int is_play = rsnd_io_is_play(io); int i, j; if (!ssiu_np) @@ -1292,8 +1289,10 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) for_each_child_of_node(dai_node, dai_np) { __rsnd_dai_probe(priv, dai_np, dai_i); if (rsnd_is_gen3(priv)) { - rsnd_parse_connect_simple(priv, dai_np, dai_i, 1); - rsnd_parse_connect_simple(priv, dai_np, dai_i, 0); + struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); + + rsnd_parse_connect_simple(priv, &rdai->playback, dai_np); + rsnd_parse_connect_simple(priv, &rdai->capture, dai_np); } dai_i++; } -- cgit v1.2.3 From 2264cf2e5db99cdff995592bf80ab6dea567ea91 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 1 Feb 2019 16:47:25 +0900 Subject: ASoC: rsnd: fixup TDM Split mode check for CTU Renesas sound card need to judge that whether it is using "TDM Split mode". To judge it and for other purpose, it has rsnd_parse_connect_simple() and rsnd_parse_connect_graph(), but these are using different judgement policy for TDM Split mode. It is pointless and confusable. This patch add new rsnd_parse_tdm_split_mode() and use common judgement policy for simple-card/audio-graph. Without this patch, CTU will be judged as TDM Split mode on audio-graph card. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'sound/soc/sh') diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 2a48d8a6cc76..2c2c60a3f276 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1031,7 +1031,7 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { .prepare = rsnd_soc_dai_prepare, }; -static void rsnd_parse_connect_simple(struct rsnd_priv *priv, +static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct device_node *dai_np) { @@ -1044,9 +1044,6 @@ static void rsnd_parse_connect_simple(struct rsnd_priv *priv, if (!ssiu_np) return; - if (!rsnd_io_to_mod_ssi(io)) - return; - /* * This driver assumes that it is TDM Split mode * if it includes ssiu node @@ -1071,12 +1068,21 @@ static void rsnd_parse_connect_simple(struct rsnd_priv *priv, } } +static void rsnd_parse_connect_simple(struct rsnd_priv *priv, + struct rsnd_dai_stream *io, + struct device_node *dai_np) +{ + if (!rsnd_io_to_mod_ssi(io)) + return; + + rsnd_parse_tdm_split_mode(priv, io, dai_np); +} + static void rsnd_parse_connect_graph(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct device_node *endpoint) { struct device *dev = rsnd_priv_to_dev(priv); - struct device_node *remote_port = of_graph_get_remote_port(endpoint); struct device_node *remote_node = of_graph_get_remote_port_parent(endpoint); if (!rsnd_io_to_mod_ssi(io)) @@ -1094,14 +1100,7 @@ static void rsnd_parse_connect_graph(struct rsnd_priv *priv, dev_dbg(dev, "%s connected to HDMI1\n", io->name); } - /* - * This driver assumes that it is TDM Split mode - * if remote node has multi endpoint - */ - if (of_get_child_count(remote_port) > 1) { - rsnd_flags_set(io, RSND_STREAM_TDM_SPLIT); - dev_dbg(dev, "%s is part of TDM Split\n", io->name); - } + rsnd_parse_tdm_split_mode(priv, io, endpoint); } void rsnd_parse_connect_common(struct rsnd_dai *rdai, -- cgit v1.2.3