diff --git a/patch/kernel/odroidxu4-dev/add-odroid-0ae2774.patch.patch b/patch/kernel/odroidxu4-dev/add-odroid-0ae2774.patch similarity index 99% rename from patch/kernel/odroidxu4-dev/add-odroid-0ae2774.patch.patch rename to patch/kernel/odroidxu4-dev/add-odroid-0ae2774.patch index 7c7e476bf8..03a54b5aa1 100644 --- a/patch/kernel/odroidxu4-dev/add-odroid-0ae2774.patch.patch +++ b/patch/kernel/odroidxu4-dev/add-odroid-0ae2774.patch @@ -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; - }