aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/fsl/fsl_spdif.c81
1 files changed, 51 insertions, 30 deletions
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index abd669e233eb..1a92d7fe1a86 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -76,6 +76,7 @@ struct fsl_spdif_priv {
76 struct regmap *regmap; 76 struct regmap *regmap;
77 bool dpll_locked; 77 bool dpll_locked;
78 u8 txclk_df[SPDIF_TXRATE_MAX]; 78 u8 txclk_df[SPDIF_TXRATE_MAX];
79 u8 sysclk_df[SPDIF_TXRATE_MAX];
79 u8 txclk_src[SPDIF_TXRATE_MAX]; 80 u8 txclk_src[SPDIF_TXRATE_MAX];
80 u8 rxclk_src; 81 u8 rxclk_src;
81 struct clk *txclk[SPDIF_TXRATE_MAX]; 82 struct clk *txclk[SPDIF_TXRATE_MAX];
@@ -351,7 +352,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
351 struct platform_device *pdev = spdif_priv->pdev; 352 struct platform_device *pdev = spdif_priv->pdev;
352 unsigned long csfs = 0; 353 unsigned long csfs = 0;
353 u32 stc, mask, rate; 354 u32 stc, mask, rate;
354 u8 clk, txclk_df; 355 u8 clk, txclk_df, sysclk_df;
355 int ret; 356 int ret;
356 357
357 switch (sample_rate) { 358 switch (sample_rate) {
@@ -384,6 +385,8 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
384 return -EINVAL; 385 return -EINVAL;
385 } 386 }
386 387
388 sysclk_df = spdif_priv->sysclk_df[rate];
389
387 /* Don't mess up the clocks from other modules */ 390 /* Don't mess up the clocks from other modules */
388 if (clk != STC_TXCLK_SPDIF_ROOT) 391 if (clk != STC_TXCLK_SPDIF_ROOT)
389 goto clk_set_bypass; 392 goto clk_set_bypass;
@@ -400,7 +403,7 @@ static int spdif_set_sample_rate(struct snd_pcm_substream *substream,
400 403
401clk_set_bypass: 404clk_set_bypass:
402 dev_dbg(&pdev->dev, "expected clock rate = %d\n", 405 dev_dbg(&pdev->dev, "expected clock rate = %d\n",
403 (64 * sample_rate * txclk_df)); 406 (64 * sample_rate * txclk_df * sysclk_df));
404 dev_dbg(&pdev->dev, "actual clock rate = %ld\n", 407 dev_dbg(&pdev->dev, "actual clock rate = %ld\n",
405 clk_get_rate(spdif_priv->txclk[rate])); 408 clk_get_rate(spdif_priv->txclk[rate]));
406 409
@@ -412,6 +415,9 @@ clk_set_bypass:
412 mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | STC_TXCLK_DF_MASK; 415 mask = STC_TXCLK_ALL_EN_MASK | STC_TXCLK_SRC_MASK | STC_TXCLK_DF_MASK;
413 regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc); 416 regmap_update_bits(regmap, REG_SPDIF_STC, mask, stc);
414 417
418 regmap_update_bits(regmap, REG_SPDIF_STC,
419 STC_SYSCLK_DF_MASK, STC_SYSCLK_DF(sysclk_df));
420
415 dev_dbg(&pdev->dev, "set sample rate to %d\n", sample_rate); 421 dev_dbg(&pdev->dev, "set sample rate to %d\n", sample_rate);
416 422
417 return 0; 423 return 0;
@@ -1018,43 +1024,55 @@ static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
1018 enum spdif_txrate index, bool round) 1024 enum spdif_txrate index, bool round)
1019{ 1025{
1020 const u32 rate[] = { 32000, 44100, 48000 }; 1026 const u32 rate[] = { 32000, 44100, 48000 };
1027 bool is_sysclk = clk == spdif_priv->sysclk;
1021 u64 rate_ideal, rate_actual, sub; 1028 u64 rate_ideal, rate_actual, sub;
1022 u32 txclk_df, arate; 1029 u32 sysclk_dfmin, sysclk_dfmax;
1023 1030 u32 txclk_df, sysclk_df, arate;
1024 for (txclk_df = 1; txclk_df <= 128; txclk_df++) { 1031
1025 rate_ideal = rate[index] * (txclk_df + 1) * 64; 1032 /* The sysclk has an extra divisor [2, 512] */
1026 if (round) 1033 sysclk_dfmin = is_sysclk ? 2 : 1;
1027 rate_actual = clk_round_rate(clk, rate_ideal); 1034 sysclk_dfmax = is_sysclk ? 512 : 1;
1028 else 1035
1029 rate_actual = clk_get_rate(clk); 1036 for (sysclk_df = sysclk_dfmin; sysclk_df <= sysclk_dfmax; sysclk_df++) {
1030 1037 for (txclk_df = 1; txclk_df <= 128; txclk_df++) {
1031 arate = rate_actual / 64; 1038 rate_ideal = rate[index] * (txclk_df + 1) * 64;
1032 arate /= txclk_df; 1039 if (round)
1033 1040 rate_actual = clk_round_rate(clk, rate_ideal);
1034 if (arate == rate[index]) { 1041 else
1035 /* We are lucky */ 1042 rate_actual = clk_get_rate(clk);
1036 savesub = 0; 1043
1037 spdif_priv->txclk_df[index] = txclk_df; 1044 arate = rate_actual / 64;
1038 break; 1045 arate /= txclk_df * sysclk_df;
1039 } else if (arate / rate[index] == 1) { 1046
1040 /* A little bigger than expect */ 1047 if (arate == rate[index]) {
1041 sub = (arate - rate[index]) * 100000; 1048 /* We are lucky */
1042 do_div(sub, rate[index]); 1049 savesub = 0;
1043 if (sub < savesub) { 1050 spdif_priv->txclk_df[index] = txclk_df;
1051 spdif_priv->sysclk_df[index] = sysclk_df;
1052 goto out;
1053 } else if (arate / rate[index] == 1) {
1054 /* A little bigger than expect */
1055 sub = (arate - rate[index]) * 100000;
1056 do_div(sub, rate[index]);
1057 if (sub >= savesub)
1058 continue;
1044 savesub = sub; 1059 savesub = sub;
1045 spdif_priv->txclk_df[index] = txclk_df; 1060 spdif_priv->txclk_df[index] = txclk_df;
1046 } 1061 spdif_priv->sysclk_df[index] = sysclk_df;
1047 } else if (rate[index] / arate == 1) { 1062 } else if (rate[index] / arate == 1) {
1048 /* A little smaller than expect */ 1063 /* A little smaller than expect */
1049 sub = (rate[index] - arate) * 100000; 1064 sub = (rate[index] - arate) * 100000;
1050 do_div(sub, rate[index]); 1065 do_div(sub, rate[index]);
1051 if (sub < savesub) { 1066 if (sub >= savesub)
1067 continue;
1052 savesub = sub; 1068 savesub = sub;
1053 spdif_priv->txclk_df[index] = txclk_df; 1069 spdif_priv->txclk_df[index] = txclk_df;
1070 spdif_priv->sysclk_df[index] = sysclk_df;
1054 } 1071 }
1055 } 1072 }
1056 } 1073 }
1057 1074
1075out:
1058 return savesub; 1076 return savesub;
1059} 1077}
1060 1078
@@ -1097,6 +1115,9 @@ static int fsl_spdif_probe_txclk(struct fsl_spdif_priv *spdif_priv,
1097 spdif_priv->txclk_src[index], rate[index]); 1115 spdif_priv->txclk_src[index], rate[index]);
1098 dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n", 1116 dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
1099 spdif_priv->txclk_df[index], rate[index]); 1117 spdif_priv->txclk_df[index], rate[index]);
1118 if (spdif_priv->txclk[index] == spdif_priv->sysclk)
1119 dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
1120 spdif_priv->sysclk_df[index], rate[index]);
1100 1121
1101 return 0; 1122 return 0;
1102} 1123}