Commit 43b64af5 authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next

parents 52708d05 b99258a3
menu "SoC Audio support for SuperH" menu "SoC Audio support for SuperH"
depends on SUPERH || ARCH_SHMOBILE depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
config SND_SOC_PCM_SH7760 config SND_SOC_PCM_SH7760
tristate "SoC Audio support for Renesas SH7760" tristate "SoC Audio support for Renesas SH7760"
...@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU ...@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
config SND_SOC_RCAR config SND_SOC_RCAR
tristate "R-Car series SRU/SCU/SSIU/SSI support" tristate "R-Car series SRU/SCU/SSIU/SSI support"
depends on COMMON_CLK depends on COMMON_CLK
depends on OF || COMPILE_TEST
select SND_SIMPLE_CARD select SND_SIMPLE_CARD
select REGMAP_MMIO select REGMAP_MMIO
help help
......
...@@ -34,6 +34,9 @@ struct rsnd_adg { ...@@ -34,6 +34,9 @@ struct rsnd_adg {
struct clk_onecell_data onecell; struct clk_onecell_data onecell;
struct rsnd_mod mod; struct rsnd_mod mod;
u32 flags; u32 flags;
u32 ckr;
u32 rbga;
u32 rbgb;
int rbga_rate_for_441khz; /* RBGA */ int rbga_rate_for_441khz; /* RBGA */
int rbgb_rate_for_48khz; /* RBGB */ int rbgb_rate_for_48khz; /* RBGB */
...@@ -316,9 +319,11 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ...@@ -316,9 +319,11 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
struct clk *clk; struct clk *clk;
int i; int i;
u32 data; u32 data;
u32 ckr = 0;
int sel_table[] = { int sel_table[] = {
[CLKA] = 0x1, [CLKA] = 0x1,
[CLKB] = 0x2, [CLKB] = 0x2,
...@@ -360,15 +365,14 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ...@@ -360,15 +365,14 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
rsnd_adg_set_ssi_clk(ssi_mod, data); rsnd_adg_set_ssi_clk(ssi_mod, data);
if (!(adg_mode_flags(adg) & LRCLK_ASYNC)) { if (!(adg_mode_flags(adg) & LRCLK_ASYNC)) {
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
u32 ckr = 0;
if (0 == (rate % 8000)) if (0 == (rate % 8000))
ckr = 0x80000000; ckr = 0x80000000;
rsnd_mod_bset(adg_mod, SSICKR, 0x80000000, ckr);
} }
rsnd_mod_bset(adg_mod, BRGCKR, 0x80FF0000, adg->ckr | ckr);
rsnd_mod_write(adg_mod, BRRA, adg->rbga);
rsnd_mod_write(adg_mod, BRRB, adg->rbgb);
dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n", dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n",
rsnd_mod_name(ssi_mod), rsnd_mod_id(ssi_mod), rsnd_mod_name(ssi_mod), rsnd_mod_id(ssi_mod),
data, rate); data, rate);
...@@ -376,6 +380,25 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ...@@ -376,6 +380,25 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
return 0; return 0;
} }
void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
{
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct device *dev = rsnd_priv_to_dev(priv);
struct clk *clk;
int i, ret;
for_each_rsnd_clk(clk, adg, i) {
ret = 0;
if (enable)
ret = clk_prepare_enable(clk);
else
clk_disable_unprepare(clk);
if (ret < 0)
dev_warn(dev, "can't use clk %d\n", i);
}
}
static void rsnd_adg_get_clkin(struct rsnd_priv *priv, static void rsnd_adg_get_clkin(struct rsnd_priv *priv,
struct rsnd_adg *adg) struct rsnd_adg *adg)
{ {
...@@ -387,27 +410,21 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv, ...@@ -387,27 +410,21 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv,
[CLKC] = "clk_c", [CLKC] = "clk_c",
[CLKI] = "clk_i", [CLKI] = "clk_i",
}; };
int i, ret; int i;
for (i = 0; i < CLKMAX; i++) { for (i = 0; i < CLKMAX; i++) {
clk = devm_clk_get(dev, clk_name[i]); clk = devm_clk_get(dev, clk_name[i]);
adg->clk[i] = IS_ERR(clk) ? NULL : clk; adg->clk[i] = IS_ERR(clk) ? NULL : clk;
} }
for_each_rsnd_clk(clk, adg, i) { for_each_rsnd_clk(clk, adg, i)
ret = clk_prepare_enable(clk);
if (ret < 0)
dev_warn(dev, "can't use clk %d\n", i);
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_get_clkout(struct rsnd_priv *priv, static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
struct rsnd_adg *adg) struct rsnd_adg *adg)
{ {
struct clk *clk; struct clk *clk;
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);
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
u32 ckr, rbgx, rbga, rbgb; u32 ckr, rbgx, rbga, rbgb;
...@@ -532,13 +549,13 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, ...@@ -532,13 +549,13 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
} }
} }
rsnd_mod_bset(adg_mod, SSICKR, 0x80FF0000, ckr); adg->ckr = ckr;
rsnd_mod_write(adg_mod, BRRA, rbga); adg->rbga = rbga;
rsnd_mod_write(adg_mod, BRRB, rbgb); adg->rbgb = rbgb;
for_each_rsnd_clkout(clk, adg, i) for_each_rsnd_clkout(clk, adg, i)
dev_dbg(dev, "clkout %d : %p : %ld\n", i, clk, clk_get_rate(clk)); 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, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
ckr, rbga, rbgb); ckr, rbga, rbgb);
} }
...@@ -565,16 +582,12 @@ int rsnd_adg_probe(struct rsnd_priv *priv) ...@@ -565,16 +582,12 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
priv->adg = adg; priv->adg = adg;
rsnd_adg_clk_enable(priv);
return 0; return 0;
} }
void rsnd_adg_remove(struct rsnd_priv *priv) void rsnd_adg_remove(struct rsnd_priv *priv)
{ {
struct rsnd_adg *adg = rsnd_priv_to_adg(priv); rsnd_adg_clk_disable(priv);
struct clk *clk;
int i;
for_each_rsnd_clk(clk, adg, i) {
clk_disable_unprepare(clk);
}
} }
...@@ -306,7 +306,7 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io) ...@@ -306,7 +306,7 @@ 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)
{ {
struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); struct rsnd_mod *ssiu = rsnd_io_to_mod_ssiu(io);
struct rsnd_mod *target; struct rsnd_mod *target;
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
u32 val = 0x76543210; u32 val = 0x76543210;
...@@ -315,11 +315,11 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) ...@@ -315,11 +315,11 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
if (rsnd_io_is_play(io)) { if (rsnd_io_is_play(io)) {
struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct rsnd_mod *src = rsnd_io_to_mod_src(io);
target = src ? src : ssi; target = src ? src : ssiu;
} else { } else {
struct rsnd_mod *cmd = rsnd_io_to_mod_cmd(io); struct rsnd_mod *cmd = rsnd_io_to_mod_cmd(io);
target = cmd ? cmd : ssi; target = cmd ? cmd : ssiu;
} }
mask <<= runtime->channels * 4; mask <<= runtime->channels * 4;
...@@ -348,32 +348,28 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) ...@@ -348,32 +348,28 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
/* /*
* rsnd_dai functions * rsnd_dai functions
*/ */
#define rsnd_mod_call(idx, io, func, param...) \ struct rsnd_mod *rsnd_mod_next(int *iterator,
({ \ struct rsnd_dai_stream *io,
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ enum rsnd_mod_type *array,
struct rsnd_mod *mod = (io)->mod[idx]; \ int array_size)
struct device *dev = rsnd_priv_to_dev(priv); \ {
u32 *status = mod->get_status(io, mod, idx); \ struct rsnd_mod *mod;
u32 mask = 0xF << __rsnd_mod_shift_##func; \ enum rsnd_mod_type type;
u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \ int max = array ? array_size : RSND_MOD_MAX;
u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \
int ret = 0; \ for (; *iterator < max; (*iterator)++) {
int call = (val == __rsnd_mod_call_##func) && (mod)->ops->func; \ type = (array) ? array[*iterator] : *iterator;
if (add == 0xF) \ mod = io->mod[type];
call = 0; \ if (!mod)
else \ continue;
*status = (*status & ~mask) + \
(add << __rsnd_mod_shift_##func); \ (*iterator)++;
dev_dbg(dev, "%s[%d]\t0x%08x %s\n", \
rsnd_mod_name(mod), rsnd_mod_id(mod), \ return mod;
*status, call ? #func : ""); \ }
if (call) \
ret = (mod)->ops->func(mod, io, param); \ return NULL;
if (ret) \ }
dev_dbg(dev, "%s[%d] : rsnd_mod_call error %d\n", \
rsnd_mod_name(mod), rsnd_mod_id(mod), ret); \
ret; \
})
static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = { static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = {
{ {
...@@ -409,17 +405,47 @@ static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = { ...@@ -409,17 +405,47 @@ static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = {
}, },
}; };
static int rsnd_status_update(u32 *status,
int shift, int add, int timing)
{
u32 mask = 0xF << shift;
u8 val = (*status >> shift) & 0xF;
u8 next_val = (val + add) & 0xF;
int func_call = (val == timing);
if (next_val == 0xF) /* underflow case */
func_call = 0;
else
*status = (*status & ~mask) + (next_val << shift);
return func_call;
}
#define rsnd_dai_call(fn, io, param...) \ #define rsnd_dai_call(fn, io, param...) \
({ \ ({ \
struct rsnd_priv *priv = rsnd_io_to_priv(io); \
struct device *dev = rsnd_priv_to_dev(priv); \
struct rsnd_mod *mod; \ struct rsnd_mod *mod; \
int type, is_play = rsnd_io_is_play(io); \ int is_play = rsnd_io_is_play(io); \
int ret = 0, i; \ int ret = 0, i; \
for (i = 0; i < RSND_MOD_MAX; i++) { \ enum rsnd_mod_type *types = rsnd_mod_sequence[is_play]; \
type = rsnd_mod_sequence[is_play][i]; \ for_each_rsnd_mod_arrays(i, mod, io, types, RSND_MOD_MAX) { \
mod = (io)->mod[type]; \ int tmp = 0; \
if (!mod) \ u32 *status = mod->get_status(io, mod, types[i]); \
continue; \ int func_call = rsnd_status_update(status, \
ret |= rsnd_mod_call(type, io, fn, param); \ __rsnd_mod_shift_##fn, \
__rsnd_mod_add_##fn, \
__rsnd_mod_call_##fn); \
dev_dbg(dev, "%s[%d]\t0x%08x %s\n", \
rsnd_mod_name(mod), rsnd_mod_id(mod), *status, \
(func_call && (mod)->ops->fn) ? #fn : ""); \
if (func_call && (mod)->ops->fn) \
tmp = (mod)->ops->fn(mod, io, param); \
if (tmp) \
dev_err(dev, "%s[%d] : %s error %d\n", \
rsnd_mod_name(mod), rsnd_mod_id(mod), \
#fn, tmp); \
ret |= tmp; \
} \ } \
ret; \ ret; \
}) })
...@@ -690,7 +716,33 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai, ...@@ -690,7 +716,33 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
return 0; return 0;
} }
static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
/*
* call rsnd_dai_call without spinlock
*/
return rsnd_dai_call(nolock_start, io, priv);
}
static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
/*
* call rsnd_dai_call without spinlock
*/
rsnd_dai_call(nolock_stop, io, priv);
}
static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
.startup = rsnd_soc_dai_startup,
.shutdown = rsnd_soc_dai_shutdown,
.trigger = rsnd_soc_dai_trigger, .trigger = rsnd_soc_dai_trigger,
.set_fmt = rsnd_soc_dai_set_fmt, .set_fmt = rsnd_soc_dai_set_fmt,
.set_tdm_slot = rsnd_soc_set_dai_tdm_slot, .set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
...@@ -993,7 +1045,11 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod, ...@@ -993,7 +1045,11 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg) void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg)
{ {
if (cfg->card && cfg->kctrl)
snd_ctl_remove(cfg->card, cfg->kctrl); snd_ctl_remove(cfg->card, cfg->kctrl);
cfg->card = NULL;
cfg->kctrl = NULL;
} }
int rsnd_kctrl_new_m(struct rsnd_mod *mod, int rsnd_kctrl_new_m(struct rsnd_mod *mod,
...@@ -1070,8 +1126,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) ...@@ -1070,8 +1126,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
return snd_pcm_lib_preallocate_pages_for_all( return snd_pcm_lib_preallocate_pages_for_all(
rtd->pcm, rtd->pcm,
SNDRV_DMA_TYPE_DEV, SNDRV_DMA_TYPE_CONTINUOUS,
rtd->card->snd_card->dev, snd_dma_continuous_data(GFP_KERNEL),
PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
} }
...@@ -1092,6 +1148,7 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, ...@@ -1092,6 +1148,7 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
ret = rsnd_dai_call(probe, io, priv); ret = rsnd_dai_call(probe, io, priv);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
struct rsnd_mod *mod;
int i; int i;
/* /*
...@@ -1111,8 +1168,8 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv, ...@@ -1111,8 +1168,8 @@ static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
* remove all mod from io * remove all mod from io
* and, re connect ssi * and, re connect ssi
*/ */
for (i = 0; i < RSND_MOD_MAX; i++) for_each_rsnd_mod(i, mod, io)
rsnd_dai_disconnect((io)->mod[i], io, i); rsnd_dai_disconnect(mod, io, i);
rsnd_dai_connect(ssi_mod, io, RSND_MOD_SSI); rsnd_dai_connect(ssi_mod, io, RSND_MOD_SSI);
/* /*
...@@ -1251,9 +1308,33 @@ static int rsnd_remove(struct platform_device *pdev) ...@@ -1251,9 +1308,33 @@ static int rsnd_remove(struct platform_device *pdev)
return ret; return ret;
} }
static int rsnd_suspend(struct device *dev)
{
struct rsnd_priv *priv = dev_get_drvdata(dev);
rsnd_adg_clk_disable(priv);
return 0;
}
static int rsnd_resume(struct device *dev)
{
struct rsnd_priv *priv = dev_get_drvdata(dev);
rsnd_adg_clk_enable(priv);
return 0;
}
static struct dev_pm_ops rsnd_pm_ops = {
.suspend = rsnd_suspend,
.resume = rsnd_resume,
};
static struct platform_driver rsnd_driver = { static struct platform_driver rsnd_driver = {
.driver = { .driver = {
.name = "rcar_sound", .name = "rcar_sound",
.pm = &rsnd_pm_ops,
.of_match_table = rsnd_of_match, .of_match_table = rsnd_of_match,
}, },
.probe = rsnd_probe, .probe = rsnd_probe,
......
This diff is collapsed.
...@@ -48,8 +48,6 @@ struct rsnd_dvc { ...@@ -48,8 +48,6 @@ struct rsnd_dvc {
#define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id) #define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id)
#define rsnd_dvc_nr(priv) ((priv)->dvc_nr) #define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
#define rsnd_dvc_of_node(priv) \
of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc")
#define rsnd_mod_to_dvc(_mod) \ #define rsnd_mod_to_dvc(_mod) \
container_of((_mod), struct rsnd_dvc, mod) container_of((_mod), struct rsnd_dvc, mod)
......
...@@ -211,6 +211,14 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) ...@@ -211,6 +211,14 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
RSND_GEN_S_REG(SSI_MODE1, 0x804), RSND_GEN_S_REG(SSI_MODE1, 0x804),
RSND_GEN_S_REG(SSI_MODE2, 0x808), RSND_GEN_S_REG(SSI_MODE2, 0x808),
RSND_GEN_S_REG(SSI_CONTROL, 0x810), RSND_GEN_S_REG(SSI_CONTROL, 0x810),
RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844),
RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c),
RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880),
RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884),
RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888),
RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c),
/* FIXME: it needs SSI_MODE2/3 in the future */ /* FIXME: it needs SSI_MODE2/3 in the future */
RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80),
...@@ -311,7 +319,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) ...@@ -311,7 +319,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
static const struct rsnd_regmap_field_conf conf_adg[] = { static const struct rsnd_regmap_field_conf conf_adg[] = {
RSND_GEN_S_REG(BRRA, 0x00), RSND_GEN_S_REG(BRRA, 0x00),
RSND_GEN_S_REG(BRRB, 0x04), RSND_GEN_S_REG(BRRB, 0x04),
RSND_GEN_S_REG(SSICKR, 0x08), RSND_GEN_S_REG(BRGCKR, 0x08),
RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14), RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14),
...@@ -362,7 +370,7 @@ static int rsnd_gen1_probe(struct rsnd_priv *priv) ...@@ -362,7 +370,7 @@ static int rsnd_gen1_probe(struct rsnd_priv *priv)
static const struct rsnd_regmap_field_conf conf_adg[] = { static const struct rsnd_regmap_field_conf conf_adg[] = {
RSND_GEN_S_REG(BRRA, 0x00), RSND_GEN_S_REG(BRRA, 0x00),
RSND_GEN_S_REG(BRRB, 0x04), RSND_GEN_S_REG(BRRB, 0x04),
RSND_GEN_S_REG(SSICKR, 0x08), RSND_GEN_S_REG(BRGCKR, 0x08),
RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
}; };
......
This diff is collapsed.
...@@ -189,6 +189,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, ...@@ -189,6 +189,7 @@ 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 use_src = 0;
u32 fin, fout; u32 fin, fout;
u32 ifscr, fsrate, adinr; u32 ifscr, fsrate, adinr;
u32 cr, route; u32 cr, route;
...@@ -214,6 +215,8 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, ...@@ -214,6 +215,8 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
return; return;
} }
use_src = (fin != fout) | rsnd_src_sync_is_enabled(mod);
/* /*
* SRC_ADINR * SRC_ADINR
*/ */
...@@ -225,7 +228,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, ...@@ -225,7 +228,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
*/ */
ifscr = 0; ifscr = 0;
fsrate = 0; fsrate = 0;
if (fin != fout) { if (use_src) {
u64 n; u64 n;
ifscr = 1; ifscr = 1;
...@@ -239,7 +242,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, ...@@ -239,7 +242,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
*/ */
cr = 0x00011110; cr = 0x00011110;
route = 0x0; route = 0x0;
if (fin != fout) { if (use_src) {
route = 0x1; route = 0x1;
if (rsnd_src_sync_is_enabled(mod)) { if (rsnd_src_sync_is_enabled(mod)) {
...@@ -327,8 +330,8 @@ static void rsnd_src_status_clear(struct rsnd_mod *mod) ...@@ -327,8 +330,8 @@ static void rsnd_src_status_clear(struct rsnd_mod *mod)
{ {
u32 val = OUF_SRC(rsnd_mod_id(mod)); u32 val = OUF_SRC(rsnd_mod_id(mod));
rsnd_mod_bset(mod, SCU_SYS_STATUS0, val, val); rsnd_mod_write(mod, SCU_SYS_STATUS0, val);
rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val); rsnd_mod_write(mod, SCU_SYS_STATUS1, val);
} }
static bool rsnd_src_error_occurred(struct rsnd_mod *mod) static bool rsnd_src_error_occurred(struct rsnd_mod *mod)
...@@ -475,7 +478,7 @@ static int rsnd_src_probe_(struct rsnd_mod *mod, ...@@ -475,7 +478,7 @@ static int rsnd_src_probe_(struct rsnd_mod *mod,
return ret; return ret;
} }
ret = rsnd_dma_attach(io, mod, &src->dma, 0); ret = rsnd_dma_attach(io, mod, &src->dma);
return ret; return ret;
} }
......
...@@ -417,11 +417,14 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod, ...@@ -417,11 +417,14 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
int chan = params_channels(params); int chan = params_channels(params);
/* /*
* Already working. * snd_pcm_ops::hw_params will be called *before*
* It will happen if SSI has parent/child connection. * snd_soc_dai_ops::trigger. Thus, ssi->usrcnt is 0
* in 1st call.
*/ */
if (ssi->usrcnt > 1) { if (ssi->usrcnt) {
/* /*
* Already working.
* It will happen if SSI has parent/child connection.
* it is error if child <-> parent SSI uses * it is error if child <-> parent SSI uses
* different channels. * different channels.
*/ */
...@@ -644,7 +647,11 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod, ...@@ -644,7 +647,11 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = devm_request_irq(dev, ssi->irq, /*
* SSI might be called again as PIO fallback
* It is easy to manual handling for IRQ request/free
*/
ret = request_irq(ssi->irq,
rsnd_ssi_interrupt, rsnd_ssi_interrupt,
IRQF_SHARED, IRQF_SHARED,
dev_name(dev), mod); dev_name(dev), mod);
...@@ -669,7 +676,6 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, ...@@ -669,7 +676,6 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
struct rsnd_priv *priv) struct rsnd_priv *priv)
{ {
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
int dma_id = 0; /* not needed */
int ret; int ret;
/* /*
...@@ -684,7 +690,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, ...@@ -684,7 +690,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
return ret; return ret;
/* SSI probe might be called many times in MUX multi path */ /* SSI probe might be called many times in MUX multi path */
ret = rsnd_dma_attach(io, mod, &ssi->dma, dma_id); ret = rsnd_dma_attach(io, mod, &ssi->dma);
return ret; return ret;
} }
...@@ -694,11 +700,9 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, ...@@ -694,11 +700,9 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
struct rsnd_priv *priv) struct rsnd_priv *priv)
{ {
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct device *dev = rsnd_priv_to_dev(priv);
int irq = ssi->irq;
/* PIO will request IRQ again */ /* PIO will request IRQ again */
devm_free_irq(dev, irq, mod); free_irq(ssi->irq, mod);
return 0; return 0;
} }
......
...@@ -33,6 +33,26 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod, ...@@ -33,6 +33,26 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
u32 mask1, val1; u32 mask1, val1;
u32 mask2, val2; u32 mask2, val2;
/* clear status */
switch (id) {
case 0:
case 1:
case 2:
case 3:
case 4:
rsnd_mod_write(mod, SSI_SYS_STATUS0, 0xf << (id * 4));
rsnd_mod_write(mod, SSI_SYS_STATUS2, 0xf << (id * 4));
rsnd_mod_write(mod, SSI_SYS_STATUS4, 0xf << (id * 4));
rsnd_mod_write(mod, SSI_SYS_STATUS6, 0xf << (id * 4));
break;
case 9:
rsnd_mod_write(mod, SSI_SYS_STATUS1, 0xf << 4);
rsnd_mod_write(mod, SSI_SYS_STATUS3, 0xf << 4);
rsnd_mod_write(mod, SSI_SYS_STATUS5, 0xf << 4);
rsnd_mod_write(mod, SSI_SYS_STATUS7, 0xf << 4);
break;
}
/* /*
* SSI_MODE0 * SSI_MODE0
*/ */
......
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