提交 2a46db4a 编写于 作者: K Kuninori Morimoto 提交者: Mark Brown

ASoC: rsnd: add AUDIO_CLKOUT support

Renesas sound has AUDIO_CLKOUT (in Gen1/Gen2) AUDIO_CLKOUT1/2/3 (in Gen3)
This patch support these patches as clock provider.
Signed-off-by: NKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: NMark Brown <broonie@kernel.org>
上级 248e88c2
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
...@@ -34,6 +34,9 @@ Required properties: ...@@ -34,6 +34,9 @@ Required properties:
see below for detail. see below for detail.
- #sound-dai-cells : it must be 0 if your system is using single DAI - #sound-dai-cells : it must be 0 if your system is using single DAI
it must be 1 if your system is using multi DAI it must be 1 if your system is using multi DAI
- #clock-cells : it must be 0 if your system has audio_clkout
it must be 1 if your system has audio_clkout0/1/2/3
- clock-frequency : for all audio_clkout0/1/2/3
SSI subnode properties: SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer - interrupts : Should contain SSI interrupt for PIO transfer
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
*/ */
#include <linux/clk-provider.h>
#include "rsnd.h" #include "rsnd.h"
#define CLKA 0 #define CLKA 0
...@@ -15,6 +16,12 @@ ...@@ -15,6 +16,12 @@
#define CLKI 3 #define CLKI 3
#define CLKMAX 4 #define CLKMAX 4
#define CLKOUT 0
#define CLKOUT1 1
#define CLKOUT2 2
#define CLKOUT3 3
#define CLKOUTMAX 4
#define BRRx_MASK(x) (0x3FF & x) #define BRRx_MASK(x) (0x3FF & x)
static struct rsnd_mod_ops adg_ops = { static struct rsnd_mod_ops adg_ops = {
...@@ -23,6 +30,8 @@ static struct rsnd_mod_ops adg_ops = { ...@@ -23,6 +30,8 @@ static struct rsnd_mod_ops adg_ops = {
struct rsnd_adg { struct rsnd_adg {
struct clk *clk[CLKMAX]; struct clk *clk[CLKMAX];
struct clk *clkout[CLKOUTMAX];
struct clk_onecell_data onecell;
struct rsnd_mod mod; struct rsnd_mod mod;
int rbga_rate_for_441khz; /* RBGA */ int rbga_rate_for_441khz; /* RBGA */
...@@ -34,6 +43,11 @@ struct rsnd_adg { ...@@ -34,6 +43,11 @@ struct rsnd_adg {
(i < CLKMAX) && \ (i < CLKMAX) && \
((pos) = adg->clk[i]); \ ((pos) = adg->clk[i]); \
i++) i++)
#define for_each_rsnd_clkout(pos, adg, i) \
for (i = 0; \
(i < CLKOUTMAX) && \
((pos) = adg->clkout[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) static u32 rsnd_adg_calculate_rbgx(unsigned long div)
...@@ -416,14 +430,25 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv, ...@@ -416,14 +430,25 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv,
dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk)); dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk));
} }
static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) static void rsnd_adg_get_clkout(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);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
unsigned long rate, div; struct device_node *np = dev->of_node;
u32 ckr, rbgx, rbga, rbgb; u32 ckr, rbgx, rbga, rbgb;
u32 rate, req_rate, div;
uint32_t count = 0;
unsigned long req_48kHz_rate, req_441kHz_rate;
int i; int i;
const char *parent_clk_name = NULL;
static const char * const clkout_name[] = {
[CLKOUT] = "audio_clkout",
[CLKOUT1] = "audio_clkout1",
[CLKOUT2] = "audio_clkout2",
[CLKOUT3] = "audio_clkout3",
};
int brg_table[] = { int brg_table[] = {
[CLKA] = 0x0, [CLKA] = 0x0,
[CLKB] = 0x1, [CLKB] = 0x1,
...@@ -431,6 +456,20 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) ...@@ -431,6 +456,20 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
[CLKI] = 0x2, [CLKI] = 0x2,
}; };
of_property_read_u32(np, "#clock-cells", &count);
/*
* ADG supports BRRA/BRRB output only
* this means all clkout0/1/2/3 will be same rate
*/
of_property_read_u32(np, "clock-frequency", &req_rate);
req_48kHz_rate = 0;
req_441kHz_rate = 0;
if (0 == (req_rate % 44100))
req_441kHz_rate = req_rate;
if (0 == (req_rate % 48000))
req_48kHz_rate = req_rate;
/* /*
* This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
* have 44.1kHz or 48kHz base clocks for now. * have 44.1kHz or 48kHz base clocks for now.
...@@ -454,22 +493,72 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) ...@@ -454,22 +493,72 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
/* RBGA */ /* RBGA */
if (!adg->rbga_rate_for_441khz && (0 == rate % 44100)) { if (!adg->rbga_rate_for_441khz && (0 == rate % 44100)) {
div = 6; div = 6;
if (req_441kHz_rate)
div = rate / req_441kHz_rate;
rbgx = rsnd_adg_calculate_rbgx(div); rbgx = rsnd_adg_calculate_rbgx(div);
if (BRRx_MASK(rbgx) == rbgx) { if (BRRx_MASK(rbgx) == rbgx) {
rbga = rbgx; rbga = rbgx;
adg->rbga_rate_for_441khz = rate / div; adg->rbga_rate_for_441khz = rate / div;
ckr |= brg_table[i] << 20; ckr |= brg_table[i] << 20;
if (req_441kHz_rate)
parent_clk_name = __clk_get_name(clk);
} }
} }
/* RBGB */ /* RBGB */
if (!adg->rbgb_rate_for_48khz && (0 == rate % 48000)) { if (!adg->rbgb_rate_for_48khz && (0 == rate % 48000)) {
div = 6; div = 6;
if (req_48kHz_rate)
div = rate / req_48kHz_rate;
rbgx = rsnd_adg_calculate_rbgx(div); rbgx = rsnd_adg_calculate_rbgx(div);
if (BRRx_MASK(rbgx) == rbgx) { if (BRRx_MASK(rbgx) == rbgx) {
rbgb = rbgx; rbgb = rbgx;
adg->rbgb_rate_for_48khz = rate / div; adg->rbgb_rate_for_48khz = rate / div;
ckr |= brg_table[i] << 16; ckr |= brg_table[i] << 16;
if (req_48kHz_rate) {
parent_clk_name = __clk_get_name(clk);
ckr |= 0x80000000;
}
}
}
}
/*
* ADG supports BRRA/BRRB output only.
* this means all clkout0/1/2/3 will be * same rate
*/
/*
* for clkout
*/
if (!count) {
clk = clk_register_fixed_rate(dev, clkout_name[i],
parent_clk_name,
(parent_clk_name) ?
0 : CLK_IS_ROOT, req_rate);
if (!IS_ERR(clk)) {
adg->clkout[CLKOUT] = clk;
of_clk_add_provider(np, of_clk_src_simple_get, clk);
}
}
/*
* for clkout0/1/2/3
*/
else {
for (i = 0; i < CLKOUTMAX; i++) {
clk = clk_register_fixed_rate(dev, clkout_name[i],
parent_clk_name,
(parent_clk_name) ?
0 : CLK_IS_ROOT,
req_rate);
if (!IS_ERR(clk)) {
adg->onecell.clks = adg->clkout;
adg->onecell.clk_num = CLKOUTMAX;
adg->clkout[i] = clk;
of_clk_add_provider(np, of_clk_src_onecell_get,
&adg->onecell);
} }
} }
} }
...@@ -478,6 +567,8 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg) ...@@ -478,6 +567,8 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
rsnd_mod_write(adg_mod, BRRA, rbga); rsnd_mod_write(adg_mod, BRRA, rbga);
rsnd_mod_write(adg_mod, BRRB, rbgb); rsnd_mod_write(adg_mod, BRRB, rbgb);
for_each_rsnd_clkout(clk, adg, i)
dev_dbg(dev, "clkout %d : %p : %ld\n", i, clk, clk_get_rate(clk));
dev_dbg(dev, "SSICKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", dev_dbg(dev, "SSICKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
ckr, rbga, rbgb); ckr, rbga, rbgb);
} }
...@@ -504,8 +595,7 @@ int rsnd_adg_probe(struct platform_device *pdev, ...@@ -504,8 +595,7 @@ int rsnd_adg_probe(struct platform_device *pdev,
adg->mod.priv = priv; adg->mod.priv = priv;
rsnd_adg_get_clkin(priv, adg); rsnd_adg_get_clkin(priv, adg);
rsnd_adg_get_clkout(priv, adg);
rsnd_adg_ssi_clk_init(priv, adg);
priv->adg = adg; priv->adg = adg;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部