ASoC: rsnd: DVC settings matches to datasheet

Current DVC settings order was rough.
This patch makes it match to datasheet.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Kuninori Morimoto 2015-11-04 08:44:12 +00:00 committed by Mark Brown
parent dcc5a7b3b0
commit ca16cc6159
1 changed files with 78 additions and 43 deletions

View File

@ -70,66 +70,106 @@ static void rsnd_dvc_soft_reset(struct rsnd_mod *mod)
rsnd_mod_write(mod, DVC_SWRSR, 1);
}
#define rsnd_dvc_initialize_lock(mod) __rsnd_dvc_initialize_lock(mod, 1)
#define rsnd_dvc_initialize_unlock(mod) __rsnd_dvc_initialize_lock(mod, 0)
static void __rsnd_dvc_initialize_lock(struct rsnd_mod *mod, u32 enable)
{
rsnd_mod_write(mod, DVC_DVUIR, enable);
}
#define rsnd_dvc_get_vrpdr(dvc) (dvc->rup.val << 8 | dvc->rdown.val)
#define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (dvc->volume.val[0] >> 13))
static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
u32 val[RSND_DVC_CHANNELS];
u32 dvucr = 0;
u32 mute = 0;
int i;
for (i = 0; i < dvc->mute.cfg.size; i++)
mute |= (!!dvc->mute.cfg.val[i]) << i;
/* Enable Ramp */
if (dvc->ren.val)
for (i = 0; i < RSND_DVC_CHANNELS; i++)
val[i] = dvc->volume.cfg.max;
else
for (i = 0; i < RSND_DVC_CHANNELS; i++)
val[i] = dvc->volume.val[i];
/* Disable DVC Register access */
rsnd_mod_write(mod, DVC_DVUER, 0);
/* Enable Digital Volume */
rsnd_mod_write(mod, DVC_VOL0R, val[0]);
rsnd_mod_write(mod, DVC_VOL1R, val[1]);
}
static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
u32 dvucr = 0;
u32 vrctr = 0;
u32 vrpdr = 0;
u32 vrdbr = 0;
/* Enable Digital Volume, Zero Cross Mute Mode */
dvucr |= 0x101;
/* Enable Ramp */
if (dvc->ren.val) {
dvucr |= 0x10;
/* Digital Volume Max */
for (i = 0; i < RSND_DVC_CHANNELS; i++)
val[i] = dvc->volume.cfg.max;
rsnd_mod_write(mod, DVC_VRCTR, 0xff);
rsnd_mod_write(mod, DVC_VRPDR, dvc->rup.val << 8 |
dvc->rdown.val);
/*
* FIXME !!
* use scale-downed Digital Volume
* as Volume Ramp
* 7F FFFF -> 3FF
*/
rsnd_mod_write(mod, DVC_VRDBR,
0x3ff - (dvc->volume.val[0] >> 13));
} else {
for (i = 0; i < RSND_DVC_CHANNELS; i++)
val[i] = dvc->volume.val[i];
vrctr = 0xff;
vrpdr = rsnd_dvc_get_vrpdr(dvc);
vrdbr = rsnd_dvc_get_vrdbr(dvc);
}
/* Enable Digital Volume */
dvucr |= 0x100;
rsnd_mod_write(mod, DVC_VOL0R, val[0]);
rsnd_mod_write(mod, DVC_VOL1R, val[1]);
/* Enable Mute */
if (mute) {
dvucr |= 0x1;
rsnd_mod_write(mod, DVC_ZCMCR, mute);
}
/* Initialize operation */
rsnd_mod_write(mod, DVC_DVUIR, 1);
/* General Information */
rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io));
rsnd_mod_write(mod, DVC_DVUCR, dvucr);
/* Volume Ramp Parameter */
rsnd_mod_write(mod, DVC_VRCTR, vrctr);
rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
/* Digital Volume Function Parameter */
rsnd_dvc_volume_parameter(io, mod);
/* cancel operation */
rsnd_mod_write(mod, DVC_DVUIR, 0);
}
static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
struct rsnd_mod *mod)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
u32 zcmcr = 0;
u32 vrpdr = 0;
u32 vrdbr = 0;
int i;
for (i = 0; i < dvc->mute.cfg.size; i++)
zcmcr |= (!!dvc->mute.cfg.val[i]) << i;
if (dvc->ren.val) {
vrpdr = rsnd_dvc_get_vrpdr(dvc);
vrdbr = rsnd_dvc_get_vrdbr(dvc);
}
/* Disable DVC Register access */
rsnd_mod_write(mod, DVC_DVUER, 0);
/* Zero Cross Mute Function */
rsnd_mod_write(mod, DVC_ZCMCR, zcmcr);
/* Volume Ramp Function */
rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
/* add DVC_VRWTR here */
/* Digital Volume Function Parameter */
rsnd_dvc_volume_parameter(io, mod);
/* Enable DVC Register access */
rsnd_mod_write(mod, DVC_DVUER, 1);
}
@ -164,15 +204,10 @@ static int rsnd_dvc_init(struct rsnd_mod *mod,
rsnd_dvc_soft_reset(mod);
rsnd_dvc_initialize_lock(mod);
rsnd_dvc_volume_init(io, mod);
rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io));
/* ch0/ch1 Volume */
rsnd_dvc_volume_update(io, mod);
rsnd_dvc_initialize_unlock(mod);
return 0;
}