Fixes for XU4 patch
This commit is contained in:
parent
48c71e6d83
commit
56aaae211d
@ -99337,419 +99337,3 @@ diff -ruN b/sound/soc/samsung/Kconfig a/sound/soc/samsung/Kconfig
|
||||
help
|
||||
Say Y here to enable audio support for the Odroid XU3/XU4.
|
||||
|
||||
diff -ruN b/sound/soc/samsung/odroid.c a/sound/soc/samsung/odroid.c
|
||||
--- b/sound/soc/samsung/odroid.c 2018-03-27 10:17:59.846849052 +0200
|
||||
+++ a/sound/soc/samsung/odroid.c 2018-03-27 10:06:54.366190706 +0200
|
||||
@@ -18,75 +18,321 @@
|
||||
struct odroid_priv {
|
||||
struct snd_soc_card card;
|
||||
struct snd_soc_dai_link dai_link;
|
||||
-
|
||||
- struct clk *clk_i2s_bus;
|
||||
- struct clk *sclk_i2s;
|
||||
};
|
||||
|
||||
-static int odroid_card_startup(struct snd_pcm_substream *substream)
|
||||
+static int set_audio_clock_heirachy(struct device *card_dev);
|
||||
+
|
||||
+/*
|
||||
+ * The initial rate that EPLL will be set to. This is the smallest multiple (4)
|
||||
+ * of the desired master clock frequency 256 * FS for FS = 44.1khz that can
|
||||
+ * be generated on both the 5250 and 5420 SoCs.
|
||||
+ */
|
||||
+static int set_audss_pll_rate(struct device *card_dev, unsigned long epll,
|
||||
+ unsigned long sclk, unsigned long rclk)
|
||||
{
|
||||
- struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
+ int ret;
|
||||
+ struct clk *fout_epll;
|
||||
+ struct clk *dout_srp, *dout_aud_bus;
|
||||
+ unsigned long clk_margin=500;
|
||||
+
|
||||
+ ret = set_audio_clock_heirachy(card_dev);
|
||||
+ if (ret) {
|
||||
+ dev_err(card_dev, "failed to set up clock hierarchy (%d)\n",
|
||||
+ ret);
|
||||
+ }
|
||||
+ fout_epll = devm_clk_get(card_dev, "fout_epll");
|
||||
+ if (IS_ERR(fout_epll)) {
|
||||
+ dev_err(card_dev, "%s: failed to get fout_epll\n", __func__);
|
||||
+ return PTR_ERR(fout_epll);
|
||||
+ }
|
||||
+ dout_srp = devm_clk_get(card_dev, "dout_srp");
|
||||
+ if (IS_ERR(dout_srp)) {
|
||||
+ dev_err(card_dev, "%s: failed to get dout_srp\n", __func__);
|
||||
+ goto out1;
|
||||
+ }
|
||||
+ dout_aud_bus = devm_clk_get(card_dev, "dout_aud_bus");
|
||||
+ if (IS_ERR(dout_aud_bus)) {
|
||||
+ dev_err(card_dev, "%s: failed to get dout_aud_bus\n", __func__);
|
||||
+ goto out2;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_set_rate(fout_epll, epll);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(card_dev, "failed to clk_set_rate of fout_epll for audio\n");
|
||||
+ goto out3;
|
||||
+ }
|
||||
+ ret = clk_set_rate(dout_srp, sclk+clk_margin);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(card_dev, "failed to clk_set_rate of dout_srp for audio\n");
|
||||
+ goto out3;
|
||||
+ }
|
||||
+ ret = clk_set_rate(dout_aud_bus, rclk+clk_margin);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(card_dev, "failed to clk_set_rate of dout_aud_bus for audio\n");
|
||||
+ goto out3;
|
||||
+ }
|
||||
+ dev_dbg(card_dev,"%s[%d] : epll=%ld\n",__func__,__LINE__,clk_get_rate(fout_epll));
|
||||
+ dev_dbg(card_dev,"%s[%d] : dout_srp=%ld\n",__func__,__LINE__,clk_get_rate(dout_srp));
|
||||
+ dev_dbg(card_dev,"%s[%d] : dout_bus=%ld\n",__func__,__LINE__,clk_get_rate(dout_aud_bus));
|
||||
+out3:
|
||||
+ clk_put(dout_aud_bus);
|
||||
+out2:
|
||||
+ clk_put(dout_srp);
|
||||
+out1:
|
||||
+ clk_put(fout_epll);
|
||||
|
||||
- snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_CHANNELS, 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* Audio clock settings are belonged to board specific part. Every
|
||||
+ * board can set audio source clock setting which is matched with H/W
|
||||
+ * like this function-'set_audio_clock_heirachy'.
|
||||
+ */
|
||||
+static int set_audio_clock_heirachy(struct device *card_dev)
|
||||
+{
|
||||
+ struct clk *fout_epll, *mout_sclk_epll;
|
||||
+ struct clk *mout_mau_epll, *mout_mau_epll_user;
|
||||
+ struct clk *mout_audss, *mout_i2s;
|
||||
+ struct clk *mau_epll;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ fout_epll = devm_clk_get(card_dev, "fout_epll");
|
||||
+ if (IS_ERR(fout_epll)) {
|
||||
+ dev_err(card_dev, "%s: Cannot find fout_epll.\n",
|
||||
+ __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ clk_prepare_enable(fout_epll);
|
||||
+
|
||||
+ mout_sclk_epll = devm_clk_get(card_dev, "mout_sclk_epll");
|
||||
+ if (IS_ERR(mout_sclk_epll)) {
|
||||
+ dev_err(card_dev, "%s: Cannot find mout_sclk_epll.\n", __func__);
|
||||
+ ret = -EINVAL;
|
||||
+ goto out1;
|
||||
+ }
|
||||
+ clk_prepare_enable(mout_sclk_epll);
|
||||
+
|
||||
+ mout_mau_epll = devm_clk_get(card_dev, "mout_mau_epll");
|
||||
+ if (IS_ERR(mout_mau_epll)) {
|
||||
+ dev_err(card_dev,
|
||||
+ "%s: Cannot find mout_mau_epll clocks.\n", __func__);
|
||||
+ ret = -EINVAL;
|
||||
+ goto out2;
|
||||
+ }
|
||||
+ clk_prepare_enable(mout_mau_epll);
|
||||
+
|
||||
+ mout_mau_epll_user = devm_clk_get(card_dev, "mout_mau_epll_user");
|
||||
+ if (IS_ERR(mout_mau_epll_user)) {
|
||||
+ dev_err(card_dev,
|
||||
+ "%s: Cannot find mout_mau_epll_user clocks.\n", __func__);
|
||||
+ ret = -EINVAL;
|
||||
+ goto out3;
|
||||
+ }
|
||||
+ clk_prepare_enable(mout_mau_epll_user);
|
||||
+
|
||||
+ mout_audss = devm_clk_get(card_dev, "mout_audss");
|
||||
+ if (IS_ERR(mout_audss)) {
|
||||
+ dev_err(card_dev,
|
||||
+ "%s: Cannot find mout_audss clocks.\n", __func__);
|
||||
+ ret = -EINVAL;
|
||||
+ goto out4;
|
||||
+ }
|
||||
+ clk_prepare_enable(mout_audss);
|
||||
+
|
||||
+ mout_i2s = devm_clk_get(card_dev, "mout_i2s");
|
||||
+ if (IS_ERR(mout_i2s)) {
|
||||
+ dev_err(card_dev,
|
||||
+ "%s: Cannot find mout_i2s clocks.\n", __func__);
|
||||
+ ret = -EINVAL;
|
||||
+ goto out5;
|
||||
+ }
|
||||
+ clk_prepare_enable(mout_i2s);
|
||||
+
|
||||
+ mau_epll = devm_clk_get(card_dev, "mau_epll_clk");
|
||||
+ if (IS_ERR(mau_epll)) {
|
||||
+ dev_err(card_dev,
|
||||
+ "%s: Cannot find mau_epll clocks.\n", __func__);
|
||||
+ ret = -EINVAL;
|
||||
+ goto out6;
|
||||
+ }
|
||||
+ clk_prepare_enable(mau_epll);
|
||||
+
|
||||
+ /* Set audio clock hierarchy for S/PDIF */
|
||||
+ ret = clk_set_parent(mout_sclk_epll, fout_epll);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(card_dev, "Failed to set parent of epll.\n");
|
||||
+ goto out7;
|
||||
+ }
|
||||
+ ret = clk_set_parent(mout_mau_epll, mout_sclk_epll);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(card_dev, "Failed to set parent of mout_mau_epll.\n");
|
||||
+ goto out7;
|
||||
+ }
|
||||
+ ret = clk_set_parent(mout_mau_epll_user, mout_mau_epll);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(card_dev, "Failed to set parent of epll.\n");
|
||||
+ goto out7;
|
||||
+ }
|
||||
+ ret = clk_set_parent(mout_audss, mout_mau_epll_user);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(card_dev, "Failed to set parent of audss.\n");
|
||||
+ goto out7;
|
||||
+ }
|
||||
+ ret = clk_set_parent(mout_i2s, mout_audss);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(card_dev, "Failed to set parent of mout i2s.\n");
|
||||
+ goto out7;
|
||||
+ }
|
||||
+out7:
|
||||
+ clk_put(mau_epll);
|
||||
+out6:
|
||||
+ clk_put(mout_i2s);
|
||||
+out5:
|
||||
+ clk_put(mout_audss);
|
||||
+out4:
|
||||
+ clk_put(mout_mau_epll_user);
|
||||
+out3:
|
||||
+ clk_put(mout_mau_epll);
|
||||
+out2:
|
||||
+ clk_put(mout_sclk_epll);
|
||||
+out1:
|
||||
+ clk_put(fout_epll);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int odroid_card_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
- struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||
- unsigned int pll_freq, rclk_freq;
|
||||
- int ret;
|
||||
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||
+ int bfs, psr, rfs, ret, div=4;
|
||||
+ unsigned long rclk, sclk;
|
||||
+ unsigned long pll;
|
||||
+ struct device *card_dev = substream->pcm->card->dev;
|
||||
+
|
||||
+ switch (params_format(params)) {
|
||||
+ case SNDRV_PCM_FORMAT_U24_LE:
|
||||
+ case SNDRV_PCM_FORMAT_S24_LE:
|
||||
+ bfs = 48;
|
||||
+ break;
|
||||
+ case SNDRV_PCM_FORMAT_U16_LE:
|
||||
+ case SNDRV_PCM_FORMAT_S16_LE:
|
||||
+ bfs = 32;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
switch (params_rate(params)) {
|
||||
+ case 16000:
|
||||
+ case 22050:
|
||||
+ case 24000:
|
||||
case 32000:
|
||||
- case 64000:
|
||||
- pll_freq = 131072006U;
|
||||
- break;
|
||||
case 44100:
|
||||
- case 88200:
|
||||
- case 176400:
|
||||
- pll_freq = 180633609U;
|
||||
- break;
|
||||
case 48000:
|
||||
+ case 88200:
|
||||
case 96000:
|
||||
- case 192000:
|
||||
- pll_freq = 196608001U;
|
||||
+ if (bfs == 48)
|
||||
+ rfs = 384;
|
||||
+ else
|
||||
+ rfs = 256;
|
||||
+ break;
|
||||
+ case 64000:
|
||||
+ rfs = 384;
|
||||
+ break;
|
||||
+ case 8000:
|
||||
+ case 11025:
|
||||
+ case 12000:
|
||||
+ if (bfs == 48)
|
||||
+ rfs = 768;
|
||||
+ else
|
||||
+ rfs = 512;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- ret = clk_set_rate(priv->clk_i2s_bus, pll_freq / 2 + 1);
|
||||
+ rclk = params_rate(params) * rfs;
|
||||
+
|
||||
+ switch (rclk) {
|
||||
+ case 4096000:
|
||||
+ case 5644800:
|
||||
+ case 6144000:
|
||||
+ case 8467200:
|
||||
+ case 9216000:
|
||||
+ psr = 8;
|
||||
+ break;
|
||||
+ case 8192000:
|
||||
+ case 11289600:
|
||||
+ case 12288000:
|
||||
+ case 16934400:
|
||||
+ case 18432000:
|
||||
+ psr = 4;
|
||||
+ break;
|
||||
+ case 22579200:
|
||||
+ case 24576000:
|
||||
+ case 33868800:
|
||||
+ case 36864000:
|
||||
+ psr = 2;
|
||||
+ break;
|
||||
+ case 67737600:
|
||||
+ case 73728000:
|
||||
+ psr = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
+ dev_err(card_dev, "rclk = %lu is not yet supported!\n", rclk);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ dev_dbg(card_dev,"%s[%d]: rate=%d, bfs=%d, rfs=%d, psr=%d \n",
|
||||
+ __func__,__LINE__, params_rate(params), bfs, rfs, psr);
|
||||
+
|
||||
+ sclk = rclk * psr;
|
||||
+ pll = sclk * div;
|
||||
+ dev_dbg(card_dev,"%s[%d]: rclk=%ld, sclk=%ld, pll=%ld\n",
|
||||
+ __func__,__LINE__, rclk, sclk, pll);
|
||||
+
|
||||
+ ret = set_audss_pll_rate(card_dev, pll, sclk, rclk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- /*
|
||||
- * We add 1 to the rclk_freq value in order to avoid too low clock
|
||||
- * frequency values due to the EPLL output frequency not being exact
|
||||
- * multiple of the audio sampling rate.
|
||||
- */
|
||||
- rclk_freq = params_rate(params) * 256 + 1;
|
||||
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
|
||||
+ | SND_SOC_DAIFMT_NB_NF
|
||||
+ | SND_SOC_DAIFMT_CBS_CFS);
|
||||
+
|
||||
+ ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk, SND_SOC_CLOCK_IN);
|
||||
+
|
||||
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
|
||||
+ | SND_SOC_DAIFMT_NB_NF
|
||||
+ | SND_SOC_DAIFMT_CBS_CFS);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
- ret = clk_set_rate(priv->sclk_i2s, rclk_freq);
|
||||
+ ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_OPCLK,
|
||||
+ 0, MOD_OPCLK_PCLK);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
- if (rtd->num_codecs > 1) {
|
||||
- struct snd_soc_dai *codec_dai = rtd->codec_dais[1];
|
||||
+ ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0,
|
||||
+ rclk, SND_SOC_CLOCK_OUT);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk_freq,
|
||||
- SND_SOC_CLOCK_IN);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
- }
|
||||
+ ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
|
||||
+ rfs, SND_SOC_CLOCK_OUT);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = snd_soc_dai_set_clkdiv(cpu_dai, SAMSUNG_I2S_DIV_BCLK, bfs);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_ops odroid_card_ops = {
|
||||
- .startup = odroid_card_startup,
|
||||
.hw_params = odroid_card_hw_params,
|
||||
};
|
||||
|
||||
@@ -117,7 +363,6 @@
|
||||
|
||||
card = &priv->card;
|
||||
card->dev = dev;
|
||||
-
|
||||
card->owner = THIS_MODULE;
|
||||
card->fully_routed = true;
|
||||
|
||||
@@ -168,32 +413,22 @@
|
||||
link->name = "Primary";
|
||||
link->stream_name = link->name;
|
||||
|
||||
-
|
||||
- priv->sclk_i2s = of_clk_get_by_name(link->cpu_of_node, "i2s_opclk1");
|
||||
- if (IS_ERR(priv->sclk_i2s)) {
|
||||
- ret = PTR_ERR(priv->sclk_i2s);
|
||||
- goto err_put_i2s_n;
|
||||
- }
|
||||
-
|
||||
- priv->clk_i2s_bus = of_clk_get_by_name(link->cpu_of_node, "iis");
|
||||
- if (IS_ERR(priv->clk_i2s_bus)) {
|
||||
- ret = PTR_ERR(priv->clk_i2s_bus);
|
||||
- goto err_put_sclk;
|
||||
- }
|
||||
-
|
||||
ret = devm_snd_soc_register_card(dev, card);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "snd_soc_register_card() failed: %d\n", ret);
|
||||
goto err_put_clk_i2s;
|
||||
}
|
||||
|
||||
+ ret = set_audio_clock_heirachy(&pdev->dev);
|
||||
+ if (ret) {
|
||||
+ dev_err(&pdev->dev, "failed to set up clock hierarchy (%d)\n",
|
||||
+ ret);
|
||||
+ snd_soc_unregister_card(card);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_put_clk_i2s:
|
||||
- clk_put(priv->clk_i2s_bus);
|
||||
-err_put_sclk:
|
||||
- clk_put(priv->sclk_i2s);
|
||||
-err_put_i2s_n:
|
||||
of_node_put(link->cpu_of_node);
|
||||
err_put_codec_n:
|
||||
odroid_put_codec_of_nodes(link);
|
||||
@@ -206,8 +441,6 @@
|
||||
|
||||
of_node_put(priv->dai_link.cpu_of_node);
|
||||
odroid_put_codec_of_nodes(&priv->dai_link);
|
||||
- clk_put(priv->sclk_i2s);
|
||||
- clk_put(priv->clk_i2s_bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user