aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/pcm512x.c119
-rw-r--r--sound/soc/codecs/pcm512x.h4
2 files changed, 96 insertions, 27 deletions
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 66dd036f0141..8b474196d52a 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -105,6 +105,7 @@ static const struct reg_default pcm512x_reg_defaults[] = {
105 { PCM512x_VCOM_CTRL_2, 0x01 }, 105 { PCM512x_VCOM_CTRL_2, 0x01 },
106 { PCM512x_BCLK_LRCLK_CFG, 0x00 }, 106 { PCM512x_BCLK_LRCLK_CFG, 0x00 },
107 { PCM512x_MASTER_MODE, 0x7c }, 107 { PCM512x_MASTER_MODE, 0x7c },
108 { PCM512x_GPIO_DACIN, 0x00 },
108 { PCM512x_GPIO_PLLIN, 0x00 }, 109 { PCM512x_GPIO_PLLIN, 0x00 },
109 { PCM512x_SYNCHRONIZE, 0x10 }, 110 { PCM512x_SYNCHRONIZE, 0x10 },
110 { PCM512x_PLL_COEFF_0, 0x00 }, 111 { PCM512x_PLL_COEFF_0, 0x00 },
@@ -138,6 +139,7 @@ static bool pcm512x_readable(struct device *dev, unsigned int reg)
138 case PCM512x_MASTER_MODE: 139 case PCM512x_MASTER_MODE:
139 case PCM512x_PLL_REF: 140 case PCM512x_PLL_REF:
140 case PCM512x_DAC_REF: 141 case PCM512x_DAC_REF:
142 case PCM512x_GPIO_DACIN:
141 case PCM512x_GPIO_PLLIN: 143 case PCM512x_GPIO_PLLIN:
142 case PCM512x_SYNCHRONIZE: 144 case PCM512x_SYNCHRONIZE:
143 case PCM512x_PLL_COEFF_0: 145 case PCM512x_PLL_COEFF_0:
@@ -659,6 +661,37 @@ done:
659 return 0; 661 return 0;
660} 662}
661 663
664static unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai,
665 unsigned long osr_rate,
666 unsigned long pllin_rate)
667{
668 struct snd_soc_codec *codec = dai->codec;
669 struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
670 unsigned long dac_rate;
671
672 if (!pcm512x->pll_out)
673 return 0; /* no PLL to bypass, force SCK as DAC input */
674
675 if (pllin_rate % osr_rate)
676 return 0; /* futile, quit early */
677
678 /* run DAC no faster than 6144000 Hz */
679 for (dac_rate = rounddown(6144000, osr_rate);
680 dac_rate;
681 dac_rate -= osr_rate) {
682
683 if (pllin_rate / dac_rate > 128)
684 return 0; /* DAC divider would be too big */
685
686 if (!(pllin_rate % dac_rate))
687 return dac_rate;
688
689 dac_rate -= osr_rate;
690 }
691
692 return 0;
693}
694
662static int pcm512x_set_dividers(struct snd_soc_dai *dai, 695static int pcm512x_set_dividers(struct snd_soc_dai *dai,
663 struct snd_pcm_hw_params *params) 696 struct snd_pcm_hw_params *params)
664{ 697{
@@ -672,6 +705,7 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
672 unsigned long bclk_rate; 705 unsigned long bclk_rate;
673 unsigned long sample_rate; 706 unsigned long sample_rate;
674 unsigned long osr_rate; 707 unsigned long osr_rate;
708 unsigned long dacsrc_rate;
675 int bclk_div; 709 int bclk_div;
676 int lrclk_div; 710 int lrclk_div;
677 int dsp_div; 711 int dsp_div;
@@ -679,11 +713,10 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
679 unsigned long dac_rate; 713 unsigned long dac_rate;
680 int ncp_div; 714 int ncp_div;
681 int osr_div; 715 int osr_div;
682 unsigned long dac_mul;
683 unsigned long sck_mul;
684 int ret; 716 int ret;
685 int idac; 717 int idac;
686 int fssp; 718 int fssp;
719 int gpio;
687 720
688 lrclk_div = snd_soc_params_to_frame_size(params); 721 lrclk_div = snd_soc_params_to_frame_size(params);
689 if (lrclk_div == 0) { 722 if (lrclk_div == 0) {
@@ -772,31 +805,72 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
772 /* run DSP no faster than 50 MHz */ 805 /* run DSP no faster than 50 MHz */
773 dsp_div = mck_rate > 50000000 ? 2 : 1; 806 dsp_div = mck_rate > 50000000 ? 2 : 1;
774 807
775 /* run DAC no faster than 6144000 Hz */ 808 dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate);
776 dac_mul = 6144000 / osr_rate; 809 if (dac_rate) {
777 sck_mul = sck_rate / osr_rate; 810 /* the desired clock rate is "compatible" with the pll input
778 for (; dac_mul; dac_mul--) { 811 * clock, so use that clock as dac input instead of the pll
779 if (!(sck_mul % dac_mul)) 812 * output clock since the pll will introduce jitter and thus
780 break; 813 * noise.
781 } 814 */
782 if (!dac_mul) { 815 dev_dbg(dev, "using pll input as dac input\n");
783 dev_err(dev, "Failed to find DAC rate\n"); 816 ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
784 return -EINVAL; 817 PCM512x_SDAC, PCM512x_SDAC_GPIO);
785 } 818 if (ret != 0) {
819 dev_err(codec->dev,
820 "Failed to set gpio as dacref: %d\n", ret);
821 return ret;
822 }
786 823
787 dac_rate = dac_mul * osr_rate; 824 gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1;
788 dev_dbg(dev, "dac_rate %lu sample_rate %lu\n", dac_rate, sample_rate); 825 ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_DACIN,
826 PCM512x_GREF, gpio);
827 if (ret != 0) {
828 dev_err(codec->dev,
829 "Failed to set gpio %d as dacin: %d\n",
830 pcm512x->pll_in, ret);
831 return ret;
832 }
833
834 dacsrc_rate = pllin_rate;
835 } else {
836 /* run DAC no faster than 6144000 Hz */
837 unsigned long dac_mul = 6144000 / osr_rate;
838 unsigned long sck_mul = sck_rate / osr_rate;
839
840 for (; dac_mul; dac_mul--) {
841 if (!(sck_mul % dac_mul))
842 break;
843 }
844 if (!dac_mul) {
845 dev_err(dev, "Failed to find DAC rate\n");
846 return -EINVAL;
847 }
789 848
790 dac_div = DIV_ROUND_CLOSEST(sck_rate, dac_rate); 849 dac_rate = dac_mul * osr_rate;
850 dev_dbg(dev, "dac_rate %lu sample_rate %lu\n",
851 dac_rate, sample_rate);
852
853 ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
854 PCM512x_SDAC, PCM512x_SDAC_SCK);
855 if (ret != 0) {
856 dev_err(codec->dev,
857 "Failed to set sck as dacref: %d\n", ret);
858 return ret;
859 }
860
861 dacsrc_rate = sck_rate;
862 }
863
864 dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate);
791 if (dac_div > 128) { 865 if (dac_div > 128) {
792 dev_err(dev, "Failed to find DAC divider\n"); 866 dev_err(dev, "Failed to find DAC divider\n");
793 return -EINVAL; 867 return -EINVAL;
794 } 868 }
795 869
796 ncp_div = DIV_ROUND_CLOSEST(sck_rate / dac_div, 1536000); 870 ncp_div = DIV_ROUND_CLOSEST(dacsrc_rate / dac_div, 1536000);
797 if (ncp_div > 128 || sck_rate / dac_div / ncp_div > 2048000) { 871 if (ncp_div > 128 || dacsrc_rate / dac_div / ncp_div > 2048000) {
798 /* run NCP no faster than 2048000 Hz, but why? */ 872 /* run NCP no faster than 2048000 Hz, but why? */
799 ncp_div = DIV_ROUND_UP(sck_rate / dac_div, 2048000); 873 ncp_div = DIV_ROUND_UP(dacsrc_rate / dac_div, 2048000);
800 if (ncp_div > 128) { 874 if (ncp_div > 128) {
801 dev_err(dev, "Failed to find NCP divider\n"); 875 dev_err(dev, "Failed to find NCP divider\n");
802 return -EINVAL; 876 return -EINVAL;
@@ -1011,13 +1085,6 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
1011 if (ret != 0) 1085 if (ret != 0)
1012 return ret; 1086 return ret;
1013 1087
1014 ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
1015 PCM512x_SDAC, PCM512x_SDAC_SCK);
1016 if (ret != 0) {
1017 dev_err(codec->dev, "Failed to set sck as dacref: %d\n", ret);
1018 return ret;
1019 }
1020
1021 if (pcm512x->pll_out) { 1088 if (pcm512x->pll_out) {
1022 ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF, 1089 ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF,
1023 PCM512x_SREF, PCM512x_SREF_GPIO); 1090 PCM512x_SREF, PCM512x_SREF_GPIO);
diff --git a/sound/soc/codecs/pcm512x.h b/sound/soc/codecs/pcm512x.h
index eba5adc2cdb1..b7c310207223 100644
--- a/sound/soc/codecs/pcm512x.h
+++ b/sound/soc/codecs/pcm512x.h
@@ -38,6 +38,7 @@
38#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12) 38#define PCM512x_MASTER_MODE (PCM512x_PAGE_BASE(0) + 12)
39#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13) 39#define PCM512x_PLL_REF (PCM512x_PAGE_BASE(0) + 13)
40#define PCM512x_DAC_REF (PCM512x_PAGE_BASE(0) + 14) 40#define PCM512x_DAC_REF (PCM512x_PAGE_BASE(0) + 14)
41#define PCM512x_GPIO_DACIN (PCM512x_PAGE_BASE(0) + 16)
41#define PCM512x_GPIO_PLLIN (PCM512x_PAGE_BASE(0) + 18) 42#define PCM512x_GPIO_PLLIN (PCM512x_PAGE_BASE(0) + 18)
42#define PCM512x_SYNCHRONIZE (PCM512x_PAGE_BASE(0) + 19) 43#define PCM512x_SYNCHRONIZE (PCM512x_PAGE_BASE(0) + 19)
43#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20) 44#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_BASE(0) + 20)
@@ -162,8 +163,9 @@
162#define PCM512x_SDAC_PLL (1 << 4) 163#define PCM512x_SDAC_PLL (1 << 4)
163#define PCM512x_SDAC_SCK (3 << 4) 164#define PCM512x_SDAC_SCK (3 << 4)
164#define PCM512x_SDAC_BCK (4 << 4) 165#define PCM512x_SDAC_BCK (4 << 4)
166#define PCM512x_SDAC_GPIO (5 << 4)
165 167
166/* Page 0, Register 18 - GPIO source for PLL */ 168/* Page 0, Register 16, 18 - GPIO source for DAC, PLL */
167#define PCM512x_GREF (7 << 0) 169#define PCM512x_GREF (7 << 0)
168#define PCM512x_GREF_SHIFT 0 170#define PCM512x_GREF_SHIFT 0
169#define PCM512x_GREF_GPIO1 (0 << 0) 171#define PCM512x_GREF_GPIO1 (0 << 0)