mirror of
https://github.com/torvalds/linux.git
synced 2024-12-16 16:12:52 +00:00
ASoC: rsnd: TDM 6ch needs 8ch clock for hw refine
Renesas sound needs 8ch clock if TDM 6ch mode, and needs 2ch clock for 6ch or 8ch sound if Multi SSI mode. And these are related to before/after CTU (= Channel Transfer Unit). To calculate these we already has rsnd_runtime_channel_for_ssi() which returns runtime necessary channels. But, it based on runtime->channels which is not yet set when hw refine. We need to use hw_params instead of runtime->xxx when hw refine, and it is not needed after runtime was set. This patch adds new hw_params on rsnd_dai_stream, and it will be removed on rsnd_hw_params(). This is very temporary durty code, but it seems no choice at this point. Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
180d9ef581
commit
b2fb31bb74
@ -197,16 +197,27 @@ int rsnd_io_is_working(struct rsnd_dai_stream *io)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rsnd_runtime_channel_original(struct rsnd_dai_stream *io)
|
int rsnd_runtime_channel_original_with_params(struct rsnd_dai_stream *io,
|
||||||
|
struct snd_pcm_hw_params *params)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
|
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
|
||||||
|
|
||||||
return runtime->channels;
|
/*
|
||||||
|
* params will be added when refine
|
||||||
|
* see
|
||||||
|
* __rsnd_soc_hw_rule_rate()
|
||||||
|
* __rsnd_soc_hw_rule_channels()
|
||||||
|
*/
|
||||||
|
if (params)
|
||||||
|
return params_channels(params);
|
||||||
|
else
|
||||||
|
return runtime->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io)
|
int rsnd_runtime_channel_after_ctu_with_params(struct rsnd_dai_stream *io,
|
||||||
|
struct snd_pcm_hw_params *params)
|
||||||
{
|
{
|
||||||
int chan = rsnd_runtime_channel_original(io);
|
int chan = rsnd_runtime_channel_original_with_params(io, params);
|
||||||
struct rsnd_mod *ctu_mod = rsnd_io_to_mod_ctu(io);
|
struct rsnd_mod *ctu_mod = rsnd_io_to_mod_ctu(io);
|
||||||
|
|
||||||
if (ctu_mod) {
|
if (ctu_mod) {
|
||||||
@ -219,12 +230,13 @@ int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io)
|
|||||||
return chan;
|
return chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io)
|
int rsnd_runtime_channel_for_ssi_with_params(struct rsnd_dai_stream *io,
|
||||||
|
struct snd_pcm_hw_params *params)
|
||||||
{
|
{
|
||||||
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
|
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
|
||||||
int chan = rsnd_io_is_play(io) ?
|
int chan = rsnd_io_is_play(io) ?
|
||||||
rsnd_runtime_channel_after_ctu(io) :
|
rsnd_runtime_channel_after_ctu_with_params(io, params) :
|
||||||
rsnd_runtime_channel_original(io);
|
rsnd_runtime_channel_original_with_params(io, params);
|
||||||
|
|
||||||
/* Use Multi SSI */
|
/* Use Multi SSI */
|
||||||
if (rsnd_runtime_is_ssi_multi(io))
|
if (rsnd_runtime_is_ssi_multi(io))
|
||||||
@ -616,8 +628,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
case SNDRV_PCM_TRIGGER_RESUME:
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
rsnd_dai_stream_init(io, substream);
|
|
||||||
|
|
||||||
ret = rsnd_dai_call(init, io, priv);
|
ret = rsnd_dai_call(init, io, priv);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto dai_trigger_end;
|
goto dai_trigger_end;
|
||||||
@ -639,7 +649,6 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||||||
|
|
||||||
ret |= rsnd_dai_call(quit, io, priv);
|
ret |= rsnd_dai_call(quit, io, priv);
|
||||||
|
|
||||||
rsnd_dai_stream_quit(io);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
@ -784,8 +793,9 @@ static int rsnd_soc_hw_rule(struct rsnd_priv *priv,
|
|||||||
return snd_interval_refine(iv, &p);
|
return snd_interval_refine(iv, &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
|
static int __rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
|
||||||
struct snd_pcm_hw_rule *rule)
|
struct snd_pcm_hw_rule *rule,
|
||||||
|
int is_play)
|
||||||
{
|
{
|
||||||
struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||||
struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
||||||
@ -793,25 +803,37 @@ static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
|
|||||||
struct snd_soc_dai *dai = rule->private;
|
struct snd_soc_dai *dai = rule->private;
|
||||||
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
|
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
|
||||||
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
|
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
|
||||||
|
struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* possible sampling rate limitation is same as
|
* possible sampling rate limitation is same as
|
||||||
* 2ch if it supports multi ssi
|
* 2ch if it supports multi ssi
|
||||||
|
* and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
|
||||||
*/
|
*/
|
||||||
ic = *ic_;
|
ic = *ic_;
|
||||||
if (1 < rsnd_rdai_ssi_lane_get(rdai)) {
|
ic.min =
|
||||||
ic.min = 2;
|
ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
|
||||||
ic.max = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rsnd_soc_hw_rule(priv, rsnd_soc_hw_rate_list,
|
return rsnd_soc_hw_rule(priv, rsnd_soc_hw_rate_list,
|
||||||
ARRAY_SIZE(rsnd_soc_hw_rate_list),
|
ARRAY_SIZE(rsnd_soc_hw_rate_list),
|
||||||
&ic, ir);
|
&ic, ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rsnd_soc_hw_rule_rate_playback(struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_pcm_hw_rule *rule)
|
||||||
|
{
|
||||||
|
return __rsnd_soc_hw_rule_rate(params, rule, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
|
static int rsnd_soc_hw_rule_rate_capture(struct snd_pcm_hw_params *params,
|
||||||
struct snd_pcm_hw_rule *rule)
|
struct snd_pcm_hw_rule *rule)
|
||||||
|
{
|
||||||
|
return __rsnd_soc_hw_rule_rate(params, rule, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_pcm_hw_rule *rule,
|
||||||
|
int is_play)
|
||||||
{
|
{
|
||||||
struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
struct snd_interval *ic_ = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||||
struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
struct snd_interval *ir = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
|
||||||
@ -819,22 +841,34 @@ static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
|
|||||||
struct snd_soc_dai *dai = rule->private;
|
struct snd_soc_dai *dai = rule->private;
|
||||||
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
|
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
|
||||||
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
|
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
|
||||||
|
struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* possible sampling rate limitation is same as
|
* possible sampling rate limitation is same as
|
||||||
* 2ch if it supports multi ssi
|
* 2ch if it supports multi ssi
|
||||||
|
* and same as 8ch if TDM 6ch (see rsnd_ssi_config_init())
|
||||||
*/
|
*/
|
||||||
ic = *ic_;
|
ic = *ic_;
|
||||||
if (1 < rsnd_rdai_ssi_lane_get(rdai)) {
|
ic.min =
|
||||||
ic.min = 2;
|
ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
|
||||||
ic.max = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rsnd_soc_hw_rule(priv, rsnd_soc_hw_channels_list,
|
return rsnd_soc_hw_rule(priv, rsnd_soc_hw_channels_list,
|
||||||
ARRAY_SIZE(rsnd_soc_hw_channels_list),
|
ARRAY_SIZE(rsnd_soc_hw_channels_list),
|
||||||
ir, &ic);
|
ir, &ic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rsnd_soc_hw_rule_channels_playback(struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_pcm_hw_rule *rule)
|
||||||
|
{
|
||||||
|
return __rsnd_soc_hw_rule_channels(params, rule, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rsnd_soc_hw_rule_channels_capture(struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_pcm_hw_rule *rule)
|
||||||
|
{
|
||||||
|
return __rsnd_soc_hw_rule_channels(params, rule, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct snd_pcm_hardware rsnd_pcm_hardware = {
|
static const struct snd_pcm_hardware rsnd_pcm_hardware = {
|
||||||
.info = SNDRV_PCM_INFO_INTERLEAVED |
|
.info = SNDRV_PCM_INFO_INTERLEAVED |
|
||||||
SNDRV_PCM_INFO_MMAP |
|
SNDRV_PCM_INFO_MMAP |
|
||||||
@ -859,6 +893,8 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
|
|||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
rsnd_dai_stream_init(io, substream);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Channel Limitation
|
* Channel Limitation
|
||||||
* It depends on Platform design
|
* It depends on Platform design
|
||||||
@ -886,11 +922,17 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
|
|||||||
* It depends on Clock Master Mode
|
* It depends on Clock Master Mode
|
||||||
*/
|
*/
|
||||||
if (rsnd_rdai_is_clk_master(rdai)) {
|
if (rsnd_rdai_is_clk_master(rdai)) {
|
||||||
|
int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
|
||||||
|
|
||||||
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
||||||
rsnd_soc_hw_rule_rate, dai,
|
is_play ? rsnd_soc_hw_rule_rate_playback :
|
||||||
|
rsnd_soc_hw_rule_rate_capture,
|
||||||
|
dai,
|
||||||
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
|
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
|
||||||
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||||
rsnd_soc_hw_rule_channels, dai,
|
is_play ? rsnd_soc_hw_rule_channels_playback :
|
||||||
|
rsnd_soc_hw_rule_channels_capture,
|
||||||
|
dai,
|
||||||
SNDRV_PCM_HW_PARAM_RATE, -1);
|
SNDRV_PCM_HW_PARAM_RATE, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -915,6 +957,8 @@ static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
|
|||||||
* call rsnd_dai_call without spinlock
|
* call rsnd_dai_call without spinlock
|
||||||
*/
|
*/
|
||||||
rsnd_dai_call(nolock_stop, io, priv);
|
rsnd_dai_call(nolock_stop, io, priv);
|
||||||
|
|
||||||
|
rsnd_dai_stream_quit(io);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
|
static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
|
||||||
|
@ -399,9 +399,18 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai,
|
|||||||
struct device_node *playback,
|
struct device_node *playback,
|
||||||
struct device_node *capture);
|
struct device_node *capture);
|
||||||
|
|
||||||
int rsnd_runtime_channel_original(struct rsnd_dai_stream *io);
|
#define rsnd_runtime_channel_original(io) \
|
||||||
int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io);
|
rsnd_runtime_channel_original_with_params(io, NULL)
|
||||||
int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io);
|
int rsnd_runtime_channel_original_with_params(struct rsnd_dai_stream *io,
|
||||||
|
struct snd_pcm_hw_params *params);
|
||||||
|
#define rsnd_runtime_channel_after_ctu(io) \
|
||||||
|
rsnd_runtime_channel_after_ctu_with_params(io, NULL)
|
||||||
|
int rsnd_runtime_channel_after_ctu_with_params(struct rsnd_dai_stream *io,
|
||||||
|
struct snd_pcm_hw_params *params);
|
||||||
|
#define rsnd_runtime_channel_for_ssi(io) \
|
||||||
|
rsnd_runtime_channel_for_ssi_with_params(io, NULL)
|
||||||
|
int rsnd_runtime_channel_for_ssi_with_params(struct rsnd_dai_stream *io,
|
||||||
|
struct snd_pcm_hw_params *params);
|
||||||
int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io);
|
int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io);
|
||||||
int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io);
|
int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user