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 <kuninori.morimoto.gx@renesas.com> Tested-by: chaoliang qin <chaoliang.qin.jg@renesas.com> Tested-by: Yusuke Goda <yusuke.goda.sx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
5dc4ca2996
commit
7674bec4fc
@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "rsnd.h"
|
#include "rsnd.h"
|
||||||
|
#include <linux/sys_soc.h>
|
||||||
|
|
||||||
#define SRC_NAME "src"
|
#define SRC_NAME "src"
|
||||||
|
|
||||||
@ -134,20 +135,83 @@ unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
|
|||||||
return rate;
|
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,
|
static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
|
||||||
struct rsnd_mod *mod)
|
struct rsnd_mod *mod)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
const struct soc_device_attribute *soc = soc_device_match(ov_soc);
|
||||||
int is_play = rsnd_io_is_play(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 i_busif, o_busif, tmp;
|
u32 i_busif, o_busif, tmp;
|
||||||
|
const u32 *bsdsr_table;
|
||||||
|
const u32 *chptn;
|
||||||
uint ratio;
|
uint ratio;
|
||||||
|
int chan;
|
||||||
|
int idx;
|
||||||
|
|
||||||
if (!runtime)
|
if (!runtime)
|
||||||
return;
|
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);
|
fin = rsnd_src_get_in_rate(priv, io);
|
||||||
fout = rsnd_src_get_out_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 */
|
/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
|
||||||
if (fin == fout)
|
if (fin == fout)
|
||||||
ratio = 0;
|
ratio = 0;
|
||||||
@ -173,8 +239,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
|
|||||||
/*
|
/*
|
||||||
* SRC_ADINR
|
* SRC_ADINR
|
||||||
*/
|
*/
|
||||||
adinr = rsnd_get_adinr_bit(mod, io) |
|
adinr = rsnd_get_adinr_bit(mod, io) | chan;
|
||||||
rsnd_runtime_channel_original(io);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SRC_IFSCR / SRC_IFSVR
|
* SRC_IFSCR / SRC_IFSVR
|
||||||
@ -207,21 +272,56 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* SRC_BSDSR / SRC_BSISR
|
* SRC_BSDSR / SRC_BSISR
|
||||||
|
*
|
||||||
|
* see
|
||||||
|
* Combination of Register Setting Related to
|
||||||
|
* FSO/FSI Ratio and Channel, Latency
|
||||||
*/
|
*/
|
||||||
switch (rsnd_mod_id(mod)) {
|
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 5:
|
||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
bsdsr = 0x02400000; /* 6 - 1/6 */
|
chptn = chan222222;
|
||||||
bsisr = 0x00100060; /* 6 - 1/6 */
|
bsdsr_table = bsdsr_table_pattern2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bsdsr = 0x01800000; /* 6 - 1/6 */
|
goto convert_rate_err;
|
||||||
bsisr = 0x00100060 ;/* 6 - 1/6 */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 */
|
/* BUSIF_MODE */
|
||||||
tmp = rsnd_get_busif_shift(io, mod);
|
tmp = rsnd_get_busif_shift(io, mod);
|
||||||
i_busif = ( is_play ? tmp : 0) | 1;
|
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_IFSCR, ifscr);
|
||||||
rsnd_mod_write(mod, SRC_IFSVR, fsrate);
|
rsnd_mod_write(mod, SRC_IFSVR, fsrate);
|
||||||
rsnd_mod_write(mod, SRC_SRCCR, cr);
|
rsnd_mod_write(mod, SRC_SRCCR, cr);
|
||||||
rsnd_mod_write(mod, SRC_BSDSR, bsdsr);
|
rsnd_mod_write(mod, SRC_BSDSR, bsdsr_table[idx]);
|
||||||
rsnd_mod_write(mod, SRC_BSISR, bsisr);
|
rsnd_mod_write(mod, SRC_BSISR, bsisr_table[idx]);
|
||||||
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, i_busif);
|
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_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);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
convert_rate_err:
|
||||||
|
dev_err(dev, "unknown BSDSR/BSDIR settings\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rsnd_src_irq(struct rsnd_mod *mod,
|
static int rsnd_src_irq(struct rsnd_mod *mod,
|
||||||
|
Loading…
Reference in New Issue
Block a user