Commit eae6fff4 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown

ASoC: rsnd: tidyup ADG clock calculate method

Current ADG clock calculation needs ADG and SSI settings.
Thus, SSI side clock request function depends on ADG settings.
After reconsideration,  we can close this method inside ADG.
This function uses new method. And it becomes preparation for
AUDIO_CLKOUT support.
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 5c6901d9
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#define CLKI 3 #define CLKI 3
#define CLKMAX 4 #define CLKMAX 4
#define BRRx_MASK(x) (0x3FF & x)
static struct rsnd_mod_ops adg_ops = { static struct rsnd_mod_ops adg_ops = {
.name = "adg", .name = "adg",
}; };
...@@ -23,8 +25,8 @@ struct rsnd_adg { ...@@ -23,8 +25,8 @@ struct rsnd_adg {
struct clk *clk[CLKMAX]; struct clk *clk[CLKMAX];
struct rsnd_mod mod; struct rsnd_mod mod;
int rbga_rate_for_441khz_div_6; /* RBGA */ int rbga_rate_for_441khz; /* RBGA */
int rbgb_rate_for_48khz_div_6; /* RBGB */ int rbgb_rate_for_48khz; /* RBGB */
}; };
#define for_each_rsnd_clk(pos, adg, i) \ #define for_each_rsnd_clk(pos, adg, i) \
...@@ -34,6 +36,21 @@ struct rsnd_adg { ...@@ -34,6 +36,21 @@ struct rsnd_adg {
i++) i++)
#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
static u32 rsnd_adg_calculate_rbgx(unsigned long div)
{
int i, ratio;
if (!div)
return 0;
for (i = 3; i >= 0; i--) {
ratio = 2 << (i * 2);
if (0 == (div % ratio))
return (u32)((i << 8) | ((div / ratio) - 1));
}
return ~0;
}
static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
{ {
...@@ -146,8 +163,8 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *src_mod, ...@@ -146,8 +163,8 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *src_mod,
clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */
clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */
clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */
adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */ adg->rbga_rate_for_441khz, /* 0011: RBGA */
adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */ adg->rbgb_rate_for_48khz, /* 0100: RBGB */
}; };
rsnd_mod_confirm_src(src_mod); rsnd_mod_confirm_src(src_mod);
...@@ -228,8 +245,8 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, ...@@ -228,8 +245,8 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
clk_get_rate(adg->clk[CLKB]), /* 001: CLKB */ clk_get_rate(adg->clk[CLKB]), /* 001: CLKB */
clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */ clk_get_rate(adg->clk[CLKC]), /* 010: CLKC */
0, /* 011: MLBCLK (not used) */ 0, /* 011: MLBCLK (not used) */
adg->rbga_rate_for_441khz_div_6,/* 100: RBGA */ adg->rbga_rate_for_441khz, /* 100: RBGA */
adg->rbgb_rate_for_48khz_div_6, /* 101: RBGB */ adg->rbgb_rate_for_48khz, /* 101: RBGB */
}; };
/* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */ /* find div (= 1/128, 1/256, 1/512, 1/1024, 1/2048 */
...@@ -348,14 +365,14 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate) ...@@ -348,14 +365,14 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
} }
/* /*
* find 1/6 clock from BRGA/BRGB * find divided clock from BRGA/BRGB
*/ */
if (rate == adg->rbga_rate_for_441khz_div_6) { if (rate == adg->rbga_rate_for_441khz) {
data = 0x10; data = 0x10;
goto found_clock; goto found_clock;
} }
if (rate == adg->rbgb_rate_for_48khz_div_6) { if (rate == adg->rbgb_rate_for_48khz) {
data = 0x20; data = 0x20;
goto found_clock; goto found_clock;
} }
...@@ -380,8 +397,9 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) ...@@ -380,8 +397,9 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
{ {
struct clk *clk; struct clk *clk;
struct rsnd_mod *adg_mod = rsnd_mod_get(adg); struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
unsigned long rate; struct device *dev = rsnd_priv_to_dev(priv);
u32 ckr; unsigned long rate, div;
u32 ckr, rbgx, rbga, rbgb;
int i; int i;
int brg_table[] = { int brg_table[] = {
[CLKA] = 0x0, [CLKA] = 0x0,
...@@ -395,15 +413,15 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) ...@@ -395,15 +413,15 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
* have 44.1kHz or 48kHz base clocks for now. * have 44.1kHz or 48kHz base clocks for now.
* *
* SSI itself can divide parent clock by 1/1 - 1/16 * SSI itself can divide parent clock by 1/1 - 1/16
* So, BRGA outputs 44.1kHz base parent clock 1/32,
* and, BRGB outputs 48.0kHz base parent clock 1/32 here.
* see * see
* rsnd_adg_ssi_clk_try_start() * rsnd_adg_ssi_clk_try_start()
* rsnd_ssi_master_clk_start() * rsnd_ssi_master_clk_start()
*/ */
ckr = 0; ckr = 0;
adg->rbga_rate_for_441khz_div_6 = 0; rbga = 2; /* default 1/6 */
adg->rbgb_rate_for_48khz_div_6 = 0; rbgb = 2; /* default 1/6 */
adg->rbga_rate_for_441khz = 0;
adg->rbgb_rate_for_48khz = 0;
for_each_rsnd_clk(clk, adg, i) { for_each_rsnd_clk(clk, adg, i) {
rate = clk_get_rate(clk); rate = clk_get_rate(clk);
...@@ -411,21 +429,34 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) ...@@ -411,21 +429,34 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
continue; continue;
/* RBGA */ /* RBGA */
if (!adg->rbga_rate_for_441khz_div_6 && (0 == rate % 44100)) { if (!adg->rbga_rate_for_441khz && (0 == rate % 44100)) {
adg->rbga_rate_for_441khz_div_6 = rate / 6; div = 6;
rbgx = rsnd_adg_calculate_rbgx(div);
if (BRRx_MASK(rbgx) == rbgx) {
rbga = rbgx;
adg->rbga_rate_for_441khz = rate / div;
ckr |= brg_table[i] << 20; ckr |= brg_table[i] << 20;
} }
}
/* RBGB */ /* RBGB */
if (!adg->rbgb_rate_for_48khz_div_6 && (0 == rate % 48000)) { if (!adg->rbgb_rate_for_48khz && (0 == rate % 48000)) {
adg->rbgb_rate_for_48khz_div_6 = rate / 6; div = 6;
rbgx = rsnd_adg_calculate_rbgx(div);
if (BRRx_MASK(rbgx) == rbgx) {
rbgb = rbgx;
adg->rbgb_rate_for_48khz = rate / div;
ckr |= brg_table[i] << 16; ckr |= brg_table[i] << 16;
} }
} }
}
rsnd_mod_bset(adg_mod, SSICKR, 0x00FF0000, ckr); rsnd_mod_bset(adg_mod, SSICKR, 0x00FF0000, ckr);
rsnd_mod_write(adg_mod, BRRA, 0x00000002); /* 1/6 */ rsnd_mod_write(adg_mod, BRRA, rbga);
rsnd_mod_write(adg_mod, BRRB, 0x00000002); /* 1/6 */ rsnd_mod_write(adg_mod, BRRB, rbgb);
dev_dbg(dev, "SSICKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
ckr, rbga, rbgb);
} }
int rsnd_adg_probe(struct platform_device *pdev, int rsnd_adg_probe(struct platform_device *pdev,
......
...@@ -129,10 +129,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, ...@@ -129,10 +129,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mod *mod = rsnd_mod_get(ssi); struct rsnd_mod *mod = rsnd_mod_get(ssi);
int i, j, ret; int j, ret;
int adg_clk_div_table[] = {
1, 6, /* see adg.c */
};
int ssi_clk_mul_table[] = { int ssi_clk_mul_table[] = {
1, 2, 4, 8, 16, 6, 12, 1, 2, 4, 8, 16, 6, 12,
}; };
...@@ -142,7 +139,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, ...@@ -142,7 +139,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
/* /*
* Find best clock, and try to start ADG * Find best clock, and try to start ADG
*/ */
for (i = 0; i < ARRAY_SIZE(adg_clk_div_table); i++) {
for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) { for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
/* /*
...@@ -150,8 +146,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, ...@@ -150,8 +146,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
* system word is 64fs (= 2 x 32bit) * system word is 64fs (= 2 x 32bit)
* see rsnd_ssi_init() * see rsnd_ssi_init()
*/ */
main_rate = rate / adg_clk_div_table[i] main_rate = rate * 32 * 2 * ssi_clk_mul_table[j];
* 32 * 2 * ssi_clk_mul_table[j];
ret = rsnd_adg_ssi_clk_try_start(mod, main_rate); ret = rsnd_adg_ssi_clk_try_start(mod, main_rate);
if (0 == ret) { if (0 == ret) {
...@@ -165,7 +160,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, ...@@ -165,7 +160,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
return 0; return 0;
} }
} }
}
dev_err(dev, "unsupported clock rate\n"); dev_err(dev, "unsupported clock rate\n");
return -EIO; return -EIO;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment