mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
This commit is contained in:
commit
245e302a4d
5 changed files with 110 additions and 143 deletions
|
@ -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 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
|
|||
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue