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>
This commit is contained in:
parent
2ea659a9ef
commit
90431eb49b
|
@ -89,6 +89,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod,
|
||||||
dev_dbg(dev, "ctu/mix path = 0x%08x", data);
|
dev_dbg(dev, "ctu/mix path = 0x%08x", data);
|
||||||
|
|
||||||
rsnd_mod_write(mod, CMD_ROUTE_SLCT, 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_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
|
||||||
|
|
||||||
rsnd_adg_set_cmd_timsel_gen2(mod, io);
|
rsnd_adg_set_cmd_timsel_gen2(mod, io);
|
||||||
|
|
|
@ -343,6 +343,57 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
|
||||||
return 0x76543210;
|
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
|
* rsnd_dai functions
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -236,6 +236,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
|
||||||
RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
|
RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
|
||||||
RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
|
RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
|
||||||
RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 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_BUSIF_DALIGN,0x188, 0x20),
|
||||||
RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
|
RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
|
||||||
RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
|
RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
|
||||||
|
|
|
@ -73,6 +73,7 @@ enum rsnd_reg {
|
||||||
RSND_REG_SCU_SYS_INT_EN0,
|
RSND_REG_SCU_SYS_INT_EN0,
|
||||||
RSND_REG_SCU_SYS_INT_EN1,
|
RSND_REG_SCU_SYS_INT_EN1,
|
||||||
RSND_REG_CMD_CTRL,
|
RSND_REG_CMD_CTRL,
|
||||||
|
RSND_REG_CMD_BUSIF_MODE,
|
||||||
RSND_REG_CMD_BUSIF_DALIGN,
|
RSND_REG_CMD_BUSIF_DALIGN,
|
||||||
RSND_REG_CMD_ROUTE_SLCT,
|
RSND_REG_CMD_ROUTE_SLCT,
|
||||||
RSND_REG_CMDOUT_TIMSEL,
|
RSND_REG_CMDOUT_TIMSEL,
|
||||||
|
@ -204,6 +205,7 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
|
||||||
u32 mask, u32 data);
|
u32 mask, u32 data);
|
||||||
u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
|
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_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
|
* R-Car DMA
|
||||||
|
|
|
@ -190,11 +190,13 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
|
||||||
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
|
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
|
||||||
struct device *dev = rsnd_priv_to_dev(priv);
|
struct device *dev = rsnd_priv_to_dev(priv);
|
||||||
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
|
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
|
||||||
|
int is_play = rsnd_io_is_play(io);
|
||||||
int use_src = 0;
|
int use_src = 0;
|
||||||
u32 fin, fout;
|
u32 fin, fout;
|
||||||
u32 ifscr, fsrate, adinr;
|
u32 ifscr, fsrate, adinr;
|
||||||
u32 cr, route;
|
u32 cr, route;
|
||||||
u32 bsdsr, bsisr;
|
u32 bsdsr, bsisr;
|
||||||
|
u32 i_busif, o_busif, tmp;
|
||||||
uint ratio;
|
uint ratio;
|
||||||
|
|
||||||
if (!runtime)
|
if (!runtime)
|
||||||
|
@ -270,6 +272,11 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
|
||||||
break;
|
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_ROUTE_MODE0, route);
|
||||||
|
|
||||||
rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */
|
rsnd_mod_write(mod, SRC_SRCIR, 1); /* initialize */
|
||||||
|
@ -281,8 +288,9 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
|
||||||
rsnd_mod_write(mod, SRC_BSISR, bsisr);
|
rsnd_mod_write(mod, SRC_BSISR, bsisr);
|
||||||
rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */
|
rsnd_mod_write(mod, SRC_SRCIR, 0); /* cancel initialize */
|
||||||
|
|
||||||
rsnd_mod_write(mod, SRC_I_BUSIF_MODE, 1);
|
rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
|
||||||
rsnd_mod_write(mod, SRC_O_BUSIF_MODE, 1);
|
rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
|
||||||
|
|
||||||
rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
|
rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
|
||||||
|
|
||||||
rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
|
rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
|
||||||
|
|
|
@ -302,7 +302,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
|
||||||
* always use 32bit system word.
|
* always use 32bit system word.
|
||||||
* see also rsnd_ssi_master_clk_enable()
|
* see also rsnd_ssi_master_clk_enable()
|
||||||
*/
|
*/
|
||||||
cr_own = FORCE | SWL_32 | PDTA;
|
cr_own = FORCE | SWL_32;
|
||||||
|
|
||||||
if (rdai->bit_clk_inv)
|
if (rdai->bit_clk_inv)
|
||||||
cr_own |= SCKP;
|
cr_own |= SCKP;
|
||||||
|
|
|
@ -144,7 +144,8 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
|
||||||
(rsnd_io_is_play(io) ?
|
(rsnd_io_is_play(io) ?
|
||||||
rsnd_runtime_channel_after_ctu(io) :
|
rsnd_runtime_channel_after_ctu(io) :
|
||||||
rsnd_runtime_channel_original(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_mod_write(mod, SSI_BUSIF_DALIGN,
|
||||||
rsnd_get_dalign(mod, io));
|
rsnd_get_dalign(mod, io));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue