aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh/rcar/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh/rcar/core.c')
-rw-r--r--sound/soc/sh/rcar/core.c124
1 files changed, 60 insertions, 64 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index d23c2bbff0cf..f930f51b686f 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -102,7 +102,9 @@
#include "rsnd.h"
#define RSND_RATES SNDRV_PCM_RATE_8000_192000
-#define RSND_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
+#define RSND_FMTS (SNDRV_PCM_FMTBIT_S8 |\
+ SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
static const struct of_device_id rsnd_of_match[] = {
{ .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 },
@@ -280,6 +282,8 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
struct device *dev = rsnd_priv_to_dev(priv);
switch (snd_pcm_format_width(runtime->format)) {
+ case 8:
+ return 16 << 16;
case 16:
return 8 << 16;
case 24:
@@ -331,7 +335,7 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
target = cmd ? cmd : ssiu;
}
- /* Non target mod or 24bit data needs normal DALIGN */
+ /* Non target mod or non 16bit needs normal DALIGN */
if ((snd_pcm_format_width(runtime->format) != 16) ||
(mod != target))
return 0x76543210;
@@ -367,7 +371,7 @@ u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
* HW 24bit data is located as 0x******00
*
*/
- if (snd_pcm_format_width(runtime->format) == 16)
+ if (snd_pcm_format_width(runtime->format) != 24)
return 0;
for (i = 0; i < ARRAY_SIZE(playback_mods); i++) {
@@ -540,6 +544,14 @@ int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai,
return rdai->ssi_lane;
}
+int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width)
+{
+ if (width > 0)
+ rdai->chan_width = width;
+
+ return rdai->chan_width;
+}
+
struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id)
{
if ((id < 0) || (id >= rsnd_rdai_nr(priv)))
@@ -681,6 +693,7 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
rdai->frm_clk_inv = 0;
break;
case SND_SOC_DAIFMT_LEFT_J:
+ case SND_SOC_DAIFMT_DSP_B:
rdai->sys_delay = 1;
rdai->data_alignment = 0;
rdai->frm_clk_inv = 1;
@@ -690,6 +703,11 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
rdai->data_alignment = 1;
rdai->frm_clk_inv = 1;
break;
+ case SND_SOC_DAIFMT_DSP_A:
+ rdai->sys_delay = 0;
+ rdai->data_alignment = 0;
+ rdai->frm_clk_inv = 1;
+ break;
}
/* set clock inversion */
@@ -720,6 +738,16 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
struct device *dev = rsnd_priv_to_dev(priv);
+ switch (slot_width) {
+ case 16:
+ case 24:
+ case 32:
+ break;
+ default:
+ /* use default */
+ slot_width = 32;
+ }
+
switch (slots) {
case 2:
case 6:
@@ -727,6 +755,7 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
/* TDM Extend Mode */
rsnd_rdai_channels_set(rdai, slots);
rsnd_rdai_ssi_lane_set(rdai, 1);
+ rsnd_rdai_width_set(rdai, slot_width);
break;
default:
dev_err(dev, "unsupported TDM slots (%d)\n", slots);
@@ -755,7 +784,7 @@ static unsigned int rsnd_soc_hw_rate_list[] = {
192000,
};
-static int rsnd_soc_hw_rule(struct rsnd_priv *priv,
+static int rsnd_soc_hw_rule(struct rsnd_dai *rdai,
unsigned int *list, int list_num,
struct snd_interval *baseline, struct snd_interval *iv)
{
@@ -772,14 +801,14 @@ static int rsnd_soc_hw_rule(struct rsnd_priv *priv,
if (!snd_interval_test(iv, list[i]))
continue;
- rate = rsnd_ssi_clk_query(priv,
+ rate = rsnd_ssi_clk_query(rdai,
baseline->min, list[i], NULL);
if (rate > 0) {
p.min = min(p.min, list[i]);
p.max = max(p.max, list[i]);
}
- rate = rsnd_ssi_clk_query(priv,
+ rate = rsnd_ssi_clk_query(rdai,
baseline->max, list[i], NULL);
if (rate > 0) {
p.min = min(p.min, list[i]);
@@ -790,17 +819,14 @@ static int rsnd_soc_hw_rule(struct rsnd_priv *priv,
return snd_interval_refine(iv, &p);
}
-static int __rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
- struct snd_pcm_hw_rule *rule,
- int is_play)
+static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
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 ic;
- struct snd_soc_dai *dai = rule->private;
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture;
+ struct rsnd_dai_stream *io = rule->private;
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
/*
* possible sampling rate limitation is same as
@@ -811,34 +837,19 @@ static int __rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params,
ic.min =
ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
- return rsnd_soc_hw_rule(priv, rsnd_soc_hw_rate_list,
+ return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_rate_list,
ARRAY_SIZE(rsnd_soc_hw_rate_list),
&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_rate_capture(struct snd_pcm_hw_params *params,
- 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)
+static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
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 ic;
- struct snd_soc_dai *dai = rule->private;
- struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
- struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
- struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture;
+ struct rsnd_dai_stream *io = rule->private;
+ struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
/*
* possible sampling rate limitation is same as
@@ -849,23 +860,11 @@ static int __rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
ic.min =
ic.max = rsnd_runtime_channel_for_ssi_with_params(io, params);
- return rsnd_soc_hw_rule(priv, rsnd_soc_hw_channels_list,
+ return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_channels_list,
ARRAY_SIZE(rsnd_soc_hw_channels_list),
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 = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
@@ -882,12 +881,10 @@ 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_priv *priv = rsnd_rdai_to_priv(rdai);
struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream);
struct snd_pcm_hw_constraint_list *constraint = &rdai->constraint;
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int max_channels = rsnd_rdai_channels_get(rdai);
- int ret;
int i;
rsnd_dai_stream_init(io, substream);
@@ -922,25 +919,16 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream,
int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
- is_play ? rsnd_soc_hw_rule_rate_playback :
- rsnd_soc_hw_rule_rate_capture,
- dai,
+ rsnd_soc_hw_rule_rate,
+ is_play ? &rdai->playback : &rdai->capture,
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
- is_play ? rsnd_soc_hw_rule_channels_playback :
- rsnd_soc_hw_rule_channels_capture,
- dai,
+ rsnd_soc_hw_rule_channels,
+ is_play ? &rdai->playback : &rdai->capture,
SNDRV_PCM_HW_PARAM_RATE, -1);
}
- /*
- * call rsnd_dai_call without spinlock
- */
- ret = rsnd_dai_call(nolock_start, io, priv);
- if (ret < 0)
- rsnd_dai_call(nolock_stop, io, priv);
-
- return ret;
+ return 0;
}
static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
@@ -953,7 +941,7 @@ static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream,
/*
* call rsnd_dai_call without spinlock
*/
- rsnd_dai_call(nolock_stop, io, priv);
+ rsnd_dai_call(cleanup, io, priv);
rsnd_dai_stream_quit(io);
}
@@ -1083,6 +1071,7 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
rdai->capture.rdai = rdai;
rsnd_rdai_channels_set(rdai, 2); /* default 2ch */
rsnd_rdai_ssi_lane_set(rdai, 1); /* default 1lane */
+ rsnd_rdai_width_set(rdai, 32); /* default 32bit width */
for (io_i = 0;; io_i++) {
playback = of_parse_phandle(dai_np, "playback", io_i);
@@ -1274,8 +1263,15 @@ int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io)
int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io)
{
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+ struct rsnd_priv *priv = rsnd_io_to_priv(io);
+ struct device *dev = rsnd_priv_to_dev(priv);
+
+ if (!runtime) {
+ dev_warn(dev, "Can't update kctrl when idle\n");
+ return 0;
+ }
- return !!runtime;
+ return 1;
}
struct rsnd_kctrl_cfg *rsnd_kctrl_init_m(struct rsnd_kctrl_cfg_m *cfg)