| From 86f119e18638ed97072aa2d521dbd4bcf4592b1c Mon Sep 17 00:00:00 2001 |
| From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Date: Tue, 16 May 2017 01:51:41 +0000 |
| Subject: [PATCH 102/286] ASoC: rsnd: don't use PDTA bit for 24bit on SSI |
| |
| Current SSI uses PDTA bit which indicates data that Input/Output |
| data are Right-Aligned. But, 24bit sound should be Left-Aligned |
| in this HW. Because Linux is using Right-Aligned data, and HW uses |
| Left-Aligned data, current 24bit data is missing lower 8bit. |
| To fix this issue, this patch removes PDTA bit, and shift 8bit |
| in necessary module |
| |
| Reported-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com> |
| Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com> |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| (cherry picked from commit 90431eb49bff6d79814cbf0c96e13597ad53095c) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| sound/soc/sh/rcar/cmd.c | 1 |
| sound/soc/sh/rcar/core.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ |
| sound/soc/sh/rcar/gen.c | 1 |
| sound/soc/sh/rcar/rsnd.h | 2 + |
| sound/soc/sh/rcar/src.c | 12 +++++++++-- |
| sound/soc/sh/rcar/ssi.c | 2 - |
| sound/soc/sh/rcar/ssiu.c | 3 +- |
| 7 files changed, 68 insertions(+), 4 deletions(-) |
| |
| --- a/sound/soc/sh/rcar/cmd.c |
| +++ b/sound/soc/sh/rcar/cmd.c |
| @@ -92,6 +92,7 @@ static int rsnd_cmd_init(struct rsnd_mod |
| dev_dbg(dev, "ctu/mix path = 0x%08x", data); |
| |
| rsnd_mod_write(mod, CMD_ROUTE_SLCT, data); |
| + rsnd_mod_write(mod, CMD_BUSIF_MODE, rsnd_get_busif_shift(io, mod) | 1); |
| rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); |
| |
| rsnd_adg_set_cmd_timsel_gen2(mod, io); |
| --- a/sound/soc/sh/rcar/core.c |
| +++ b/sound/soc/sh/rcar/core.c |
| @@ -343,6 +343,57 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod |
| return 0x76543210; |
| } |
| |
| +u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod) |
| +{ |
| + enum rsnd_mod_type playback_mods[] = { |
| + RSND_MOD_SRC, |
| + RSND_MOD_CMD, |
| + RSND_MOD_SSIU, |
| + }; |
| + enum rsnd_mod_type capture_mods[] = { |
| + RSND_MOD_CMD, |
| + RSND_MOD_SRC, |
| + RSND_MOD_SSIU, |
| + }; |
| + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
| + struct rsnd_mod *tmod = NULL; |
| + enum rsnd_mod_type *mods = |
| + rsnd_io_is_play(io) ? |
| + playback_mods : capture_mods; |
| + int i; |
| + |
| + /* |
| + * This is needed for 24bit data |
| + * We need to shift 8bit |
| + * |
| + * Linux 24bit data is located as 0x00****** |
| + * HW 24bit data is located as 0x******00 |
| + * |
| + */ |
| + switch (runtime->sample_bits) { |
| + case 16: |
| + return 0; |
| + case 32: |
| + break; |
| + } |
| + |
| + for (i = 0; i < ARRAY_SIZE(playback_mods); i++) { |
| + tmod = rsnd_io_to_mod(io, mods[i]); |
| + if (tmod) |
| + break; |
| + } |
| + |
| + if (tmod != mod) |
| + return 0; |
| + |
| + if (rsnd_io_is_play(io)) |
| + return (0 << 20) | /* shift to Left */ |
| + (8 << 16); /* 8bit */ |
| + else |
| + return (1 << 20) | /* shift to Right */ |
| + (8 << 16); /* 8bit */ |
| +} |
| + |
| /* |
| * rsnd_dai functions |
| */ |
| --- a/sound/soc/sh/rcar/gen.c |
| +++ b/sound/soc/sh/rcar/gen.c |
| @@ -236,6 +236,7 @@ static int rsnd_gen2_probe(struct rsnd_p |
| RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), |
| RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), |
| RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), |
| + RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20), |
| RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188, 0x20), |
| RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), |
| RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), |
| --- a/sound/soc/sh/rcar/rsnd.h |
| +++ b/sound/soc/sh/rcar/rsnd.h |
| @@ -73,6 +73,7 @@ enum rsnd_reg { |
| RSND_REG_SCU_SYS_INT_EN0, |
| RSND_REG_SCU_SYS_INT_EN1, |
| RSND_REG_CMD_CTRL, |
| + RSND_REG_CMD_BUSIF_MODE, |
| RSND_REG_CMD_BUSIF_DALIGN, |
| RSND_REG_CMD_ROUTE_SLCT, |
| RSND_REG_CMDOUT_TIMSEL, |
| @@ -204,6 +205,7 @@ void rsnd_bset(struct rsnd_priv *priv, s |
| u32 mask, u32 data); |
| u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io); |
| u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io); |
| +u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod); |
| |
| /* |
| * R-Car DMA |
| --- a/sound/soc/sh/rcar/src.c |
| +++ b/sound/soc/sh/rcar/src.c |
| @@ -190,11 +190,13 @@ static void rsnd_src_set_convert_rate(st |
| 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); |
| + 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; |
| uint ratio; |
| |
| if (!runtime) |
| @@ -270,6 +272,11 @@ static void rsnd_src_set_convert_rate(st |
| break; |
| } |
| |
| + /* BUSIF_MODE */ |
| + tmp = rsnd_get_busif_shift(io, mod); |
| + i_busif = ( is_play ? tmp : 0) | 1; |
| + o_busif = (!is_play ? tmp : 0) | 1; |
| + |
| rsnd_mod_write(mod, SRC_ROUTE_MODE0, route); |
| |
| rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */ |
| @@ -281,8 +288,9 @@ static void rsnd_src_set_convert_rate(st |
| rsnd_mod_write(mod, SRC_BSISR, bsisr); |
| rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */ |
| |
| - rsnd_mod_write(mod, SRC_I_BUSIF_MODE, 1); |
| - rsnd_mod_write(mod, SRC_O_BUSIF_MODE, 1); |
| + rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif); |
| + rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif); |
| + |
| rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io)); |
| |
| rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout); |
| --- a/sound/soc/sh/rcar/ssi.c |
| +++ b/sound/soc/sh/rcar/ssi.c |
| @@ -316,7 +316,7 @@ static void rsnd_ssi_config_init(struct |
| * always use 32bit system word. |
| * see also rsnd_ssi_master_clk_enable() |
| */ |
| - cr_own = FORCE | SWL_32 | PDTA; |
| + cr_own = FORCE | SWL_32; |
| |
| if (rdai->bit_clk_inv) |
| cr_own |= SCKP; |
| --- a/sound/soc/sh/rcar/ssiu.c |
| +++ b/sound/soc/sh/rcar/ssiu.c |
| @@ -144,7 +144,8 @@ static int rsnd_ssiu_init_gen2(struct rs |
| (rsnd_io_is_play(io) ? |
| rsnd_runtime_channel_after_ctu(io) : |
| rsnd_runtime_channel_original(io))); |
| - rsnd_mod_write(mod, SSI_BUSIF_MODE, 1); |
| + rsnd_mod_write(mod, SSI_BUSIF_MODE, |
| + rsnd_get_busif_shift(io, mod) | 1); |
| rsnd_mod_write(mod, SSI_BUSIF_DALIGN, |
| rsnd_get_dalign(mod, io)); |
| } |