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

This commit is contained in:
Mark Brown 2017-04-30 22:15:42 +09:00
commit 245e302a4d
5 changed files with 110 additions and 143 deletions

View File

@ -43,6 +43,7 @@ struct rsnd_adg {
};
#define LRCLK_ASYNC (1 << 0)
#define AUDIO_OUT_48 (1 << 1)
#define adg_mode_flags(adg) (adg->flags)
#define for_each_rsnd_clk(pos, adg, i) \
@ -364,7 +365,10 @@ found_clock:
rsnd_adg_set_ssi_clk(ssi_mod, data);
if (!(adg_mode_flags(adg) & LRCLK_ASYNC)) {
if (adg_mode_flags(adg) & LRCLK_ASYNC) {
if (adg_mode_flags(adg) & AUDIO_OUT_48)
ckr = 0x80000000;
} else {
if (0 == (rate % 8000))
ckr = 0x80000000;
}
@ -427,11 +431,14 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
struct clk *clk;
struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
struct property *prop;
u32 ckr, rbgx, rbga, rbgb;
u32 rate, req_rate = 0, div;
u32 rate, div;
#define REQ_SIZE 2
u32 req_rate[REQ_SIZE] = {};
uint32_t count = 0;
unsigned long req_48kHz_rate, req_441kHz_rate;
int i;
int i, req_size;
const char *parent_clk_name = NULL;
static const char * const clkout_name[] = {
[CLKOUT] = "audio_clkout",
@ -446,19 +453,32 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
[CLKI] = 0x2,
};
of_property_read_u32(np, "#clock-cells", &count);
ckr = 0;
rbga = 2; /* default 1/6 */
rbgb = 2; /* default 1/6 */
/*
* 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);
prop = of_find_property(np, "clock-frequency", NULL);
if (!prop)
goto rsnd_adg_get_clkout_end;
req_size = prop->length / sizeof(u32);
of_property_read_u32_array(np, "clock-frequency", req_rate, req_size);
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;
for (i = 0; i < req_size; i++) {
if (0 == (req_rate[i] % 44100))
req_441kHz_rate = req_rate[i];
if (0 == (req_rate[i] % 48000))
req_48kHz_rate = req_rate[i];
}
if (req_rate[0] % 48000 == 0)
adg->flags = AUDIO_OUT_48;
/*
* This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC
@ -469,9 +489,6 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
* rsnd_adg_ssi_clk_try_start()
* rsnd_ssi_master_clk_start()
*/
ckr = 0;
rbga = 2; /* default 1/6 */
rbgb = 2; /* default 1/6 */
adg->rbga_rate_for_441khz = 0;
adg->rbgb_rate_for_48khz = 0;
for_each_rsnd_clk(clk, adg, i) {
@ -505,10 +522,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
rbgb = rbgx;
adg->rbgb_rate_for_48khz = rate / div;
ckr |= brg_table[i] << 16;
if (req_48kHz_rate) {
if (req_48kHz_rate)
parent_clk_name = __clk_get_name(clk);
ckr |= 0x80000000;
}
}
}
}
@ -518,12 +533,13 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
* this means all clkout0/1/2/3 will be * same rate
*/
of_property_read_u32(np, "#clock-cells", &count);
/*
* for clkout
*/
if (!count) {
clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT],
parent_clk_name, 0, req_rate);
parent_clk_name, 0, req_rate[0]);
if (!IS_ERR(clk)) {
adg->clkout[CLKOUT] = clk;
of_clk_add_provider(np, of_clk_src_simple_get, clk);
@ -536,7 +552,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
for (i = 0; i < CLKOUTMAX; i++) {
clk = clk_register_fixed_rate(dev, clkout_name[i],
parent_clk_name, 0,
req_rate);
req_rate[0]);
adg->clkout[i] = ERR_PTR(-ENOENT);
if (!IS_ERR(clk))
adg->clkout[i] = clk;
@ -547,6 +563,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
&adg->onecell);
}
rsnd_adg_get_clkout_end:
adg->ckr = ckr;
adg->rbga = rbga;
adg->rbgb = rbgb;
@ -562,6 +579,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
struct rsnd_adg *adg;
struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
int ret;
adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
if (!adg) {
@ -569,8 +587,10 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
return -ENOMEM;
}
rsnd_mod_init(priv, &adg->mod, &adg_ops,
ret = rsnd_mod_init(priv, &adg->mod, &adg_ops,
NULL, NULL, 0, 0);
if (ret)
return ret;
rsnd_adg_get_clkin(priv, adg);
rsnd_adg_get_clkout(priv, adg);

View File

@ -96,7 +96,7 @@
#include <linux/pm_runtime.h>
#include "rsnd.h"
#define RSND_RATES SNDRV_PCM_RATE_8000_96000
#define RSND_RATES SNDRV_PCM_RATE_8000_192000
#define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
static const struct of_device_id rsnd_of_match[] = {
@ -110,7 +110,6 @@ MODULE_DEVICE_TABLE(of, rsnd_of_match);
/*
* rsnd_mod functions
*/
#ifdef DEBUG
void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type)
{
if (mod->type != type) {
@ -121,7 +120,6 @@ void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type)
rsnd_mod_name(mod), rsnd_mod_id(mod));
}
}
#endif
char *rsnd_mod_name(struct rsnd_mod *mod)
{
@ -674,12 +672,10 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
/* set clock inversion */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_IF:
rdai->bit_clk_inv = rdai->bit_clk_inv;
rdai->frm_clk_inv = !rdai->frm_clk_inv;
break;
case SND_SOC_DAIFMT_IB_NF:
rdai->bit_clk_inv = !rdai->bit_clk_inv;
rdai->frm_clk_inv = rdai->frm_clk_inv;
break;
case SND_SOC_DAIFMT_IB_IF:
rdai->bit_clk_inv = !rdai->bit_clk_inv;
@ -1002,13 +998,30 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl,
return change;
}
static int __rsnd_kctrl_new(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
struct rsnd_kctrl_cfg *cfg,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod))
struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg)
{
cfg->cfg.val = cfg->val;
return &cfg->cfg;
}
struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg)
{
cfg->cfg.val = &cfg->val;
return &cfg->cfg;
}
int rsnd_kctrl_new(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
struct rsnd_kctrl_cfg *cfg,
const char * const *texts,
int size,
u32 max)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_kcontrol *kctrl;
@ -1023,6 +1036,9 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
};
int ret;
if (size > RSND_MAX_CHANNELS)
return -EINVAL;
kctrl = snd_ctl_new1(&knew, mod);
if (!kctrl)
return -ENOMEM;
@ -1031,74 +1047,17 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
if (ret < 0)
return ret;
cfg->update = update;
cfg->card = card;
cfg->kctrl = kctrl;
cfg->io = io;
cfg->texts = texts;
cfg->max = max;
cfg->size = size;
cfg->update = update;
cfg->card = card;
cfg->kctrl = kctrl;
cfg->io = io;
return 0;
}
void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg)
{
if (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,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
struct rsnd_kctrl_cfg_m *_cfg,
int ch_size,
u32 max)
{
if (ch_size > RSND_MAX_CHANNELS)
return -EINVAL;
_cfg->cfg.max = max;
_cfg->cfg.size = ch_size;
_cfg->cfg.val = _cfg->val;
return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update);
}
int rsnd_kctrl_new_s(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
struct rsnd_kctrl_cfg_s *_cfg,
u32 max)
{
_cfg->cfg.max = max;
_cfg->cfg.size = 1;
_cfg->cfg.val = &_cfg->val;
return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update);
}
int rsnd_kctrl_new_e(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
struct rsnd_kctrl_cfg_s *_cfg,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
const char * const *texts,
u32 max)
{
_cfg->cfg.max = max;
_cfg->cfg.size = 1;
_cfg->cfg.val = &_cfg->val;
_cfg->cfg.texts = texts;
return __rsnd_kctrl_new(mod, io, rtd, name, &_cfg->cfg, update);
}
/*
* snd_soc_platform
*/

View File

@ -218,21 +218,6 @@ static int rsnd_dvc_probe_(struct rsnd_mod *mod,
return rsnd_cmd_attach(io, rsnd_mod_id(mod));
}
static int rsnd_dvc_remove_(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
rsnd_kctrl_remove(dvc->volume);
rsnd_kctrl_remove(dvc->mute);
rsnd_kctrl_remove(dvc->ren);
rsnd_kctrl_remove(dvc->rup);
rsnd_kctrl_remove(dvc->rdown);
return 0;
}
static int rsnd_dvc_init(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
@ -300,18 +285,18 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
ret = rsnd_kctrl_new_e(mod, io, rtd,
is_play ?
"DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate",
&dvc->rup,
rsnd_dvc_volume_update,
dvc_ramp_rate, ARRAY_SIZE(dvc_ramp_rate));
&dvc->rup,
dvc_ramp_rate);
if (ret < 0)
return ret;
ret = rsnd_kctrl_new_e(mod, io, rtd,
is_play ?
"DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate",
&dvc->rdown,
rsnd_dvc_volume_update,
dvc_ramp_rate, ARRAY_SIZE(dvc_ramp_rate));
&dvc->rdown,
dvc_ramp_rate);
if (ret < 0)
return ret;
@ -332,7 +317,6 @@ static struct rsnd_mod_ops rsnd_dvc_ops = {
.name = DVC_NAME,
.dma_req = rsnd_dvc_dma_req,
.probe = rsnd_dvc_probe_,
.remove = rsnd_dvc_remove_,
.init = rsnd_dvc_init,
.quit = rsnd_dvc_quit,
.pcm_new = rsnd_dvc_pcm_new,

View File

@ -611,35 +611,30 @@ struct rsnd_kctrl_cfg_s {
u32 val;
};
void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg);
#define rsnd_kctrl_remove(_cfg) _rsnd_kctrl_remove(&((_cfg).cfg))
struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg);
struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg);
int rsnd_kctrl_new(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
struct rsnd_kctrl_cfg *cfg,
const char * const *texts,
int size,
u32 max);
int rsnd_kctrl_new_m(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
struct rsnd_kctrl_cfg_m *_cfg,
int ch_size,
u32 max);
int rsnd_kctrl_new_s(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
struct rsnd_kctrl_cfg_s *_cfg,
u32 max);
int rsnd_kctrl_new_e(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
struct rsnd_kctrl_cfg_s *_cfg,
void (*update)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod),
const char * const *texts,
u32 max);
#define rsnd_kctrl_new_m(mod, io, rtd, name, update, cfg, size, max) \
rsnd_kctrl_new(mod, io, rtd, name, update, rsnd_kctrl_init_m(cfg), \
NULL, size, max)
#define rsnd_kctrl_new_s(mod, io, rtd, name, update, cfg, max) \
rsnd_kctrl_new(mod, io, rtd, name, update, rsnd_kctrl_init_s(cfg), \
NULL, 1, max)
#define rsnd_kctrl_new_e(mod, io, rtd, name, update, cfg, texts) \
rsnd_kctrl_new(mod, io, rtd, name, update, rsnd_kctrl_init_s(cfg), \
texts, 1, ARRAY_SIZE(texts))
/*
* R-Car SSI
@ -732,8 +727,8 @@ void rsnd_cmd_remove(struct rsnd_priv *priv);
int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id);
struct rsnd_mod *rsnd_cmd_mod_get(struct rsnd_priv *priv, int id);
#ifdef DEBUG
void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type);
#ifdef DEBUG
#define rsnd_mod_confirm_ssi(mssi) rsnd_mod_make_sure(mssi, RSND_MOD_SSI)
#define rsnd_mod_confirm_src(msrc) rsnd_mod_make_sure(msrc, RSND_MOD_SRC)
#define rsnd_mod_confirm_dvc(mdvc) rsnd_mod_make_sure(mdvc, RSND_MOD_DVC)

View File

@ -227,6 +227,15 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
*/
for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
/*
* It will set SSIWSR.CONT here, but SSICR.CKDV = 000
* with it is not allowed. (SSIWSR.WS_MODE with
* SSICR.CKDV = 000 is not allowed either).
* Skip it. See SSICR.CKDV
*/
if (j == 0)
continue;
/*
* this driver is assuming that
* system word is 32bit x chan