summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ak4613.c
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2017-06-16 01:47:34 +0000
committerMark Brown <broonie@kernel.org>2017-06-16 17:56:41 +0100
commit907cd8809eebccc57a6a3ee9fa87b7602e72df38 (patch)
tree82c205a8556eb7c1f38d1ff07a4e1393772b9433 /sound/soc/codecs/ak4613.c
parenta83ac4860925e1d0a7e38e7bea331fd2f2e0460d (diff)
downloadlinux-907cd8809eebccc57a6a3ee9fa87b7602e72df38.tar.bz2
ASoC: ak4613: add hw_constraint rule for Sampling Rate
Current ak4613 accepts all range of Sampling Rate, but it depends on inputed master clock. This patch adds hw constraint rule for it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/ak4613.c')
-rw-r--r--sound/soc/codecs/ak4613.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index d5beca008dea..a4520a1f849d 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -94,6 +94,8 @@ struct ak4613_interface {
struct ak4613_priv {
struct mutex lock;
const struct ak4613_interface *iface;
+ struct snd_pcm_hw_constraint_list constraint;
+ unsigned int sysclk;
unsigned int fmt;
u8 oc;
@@ -252,6 +254,50 @@ static void ak4613_dai_shutdown(struct snd_pcm_substream *substream,
mutex_unlock(&priv->lock);
}
+static void ak4613_hw_constraints(struct ak4613_priv *priv,
+ struct snd_pcm_runtime *runtime)
+{
+ static const unsigned int ak4613_rates[] = {
+ 32000,
+ 44100,
+ 48000,
+ 64000,
+ 88200,
+ 96000,
+ 176400,
+ 192000,
+ };
+ struct snd_pcm_hw_constraint_list *constraint = &priv->constraint;
+ unsigned int fs;
+ int i;
+
+ constraint->list = ak4613_rates;
+ constraint->mask = 0;
+ constraint->count = 0;
+
+ /*
+ * Slave Mode
+ * Normal: [32kHz, 48kHz] : 256fs,384fs or 512fs
+ * Double: [64kHz, 96kHz] : 256fs
+ * Quad : [128kHz,192kHz]: 128fs
+ *
+ * Master mode
+ * Normal: [32kHz, 48kHz] : 256fs or 512fs
+ * Double: [64kHz, 96kHz] : 256fs
+ * Quad : [128kHz,192kHz]: 128fs
+ */
+ for (i = 0; i < ARRAY_SIZE(ak4613_rates); i++) {
+ /* minimum fs on each range */
+ fs = (ak4613_rates[i] <= 96000) ? 256 : 128;
+
+ if (priv->sysclk >= ak4613_rates[i] * fs)
+ constraint->count = i + 1;
+ }
+
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, constraint);
+}
+
static int ak4613_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
@@ -260,6 +306,19 @@ static int ak4613_dai_startup(struct snd_pcm_substream *substream,
priv->cnt++;
+ ak4613_hw_constraints(priv, substream->runtime);
+
+ return 0;
+}
+
+static int ak4613_dai_set_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct ak4613_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ priv->sysclk = freq;
+
return 0;
}
@@ -411,6 +470,7 @@ static int ak4613_set_bias_level(struct snd_soc_codec *codec,
static const struct snd_soc_dai_ops ak4613_dai_ops = {
.startup = ak4613_dai_startup,
.shutdown = ak4613_dai_shutdown,
+ .set_sysclk = ak4613_dai_set_sysclk,
.set_fmt = ak4613_dai_set_fmt,
.hw_params = ak4613_dai_hw_params,
};
@@ -529,6 +589,7 @@ static int ak4613_i2c_probe(struct i2c_client *i2c,
priv->iface = NULL;
priv->cnt = 0;
+ priv->sysclk = 0;
mutex_init(&priv->lock);