diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index f0c7ec2a2f31..d46d6cdb6b87 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[] = {
 	{ PCM512x_VCOM_CTRL_2,       0x01 },
 	{ PCM512x_BCLK_LRCLK_CFG,    0x00 },
 	{ PCM512x_MASTER_MODE,       0x7c },
+	{ PCM512x_GPIO_DACIN,        0x00 },
 	{ PCM512x_GPIO_PLLIN,        0x00 },
 	{ PCM512x_SYNCHRONIZE,       0x10 },
 	{ PCM512x_PLL_COEFF_0,       0x00 },
@@ -138,6 +139,7 @@ static bool pcm512x_readable(struct device *dev, unsigned int reg)
 	case PCM512x_MASTER_MODE:
 	case PCM512x_PLL_REF:
 	case PCM512x_DAC_REF:
+	case PCM512x_GPIO_DACIN:
 	case PCM512x_GPIO_PLLIN:
 	case PCM512x_SYNCHRONIZE:
 	case PCM512x_PLL_COEFF_0:
@@ -659,6 +661,37 @@ done:
 	return 0;
 }
 
+static unsigned long pcm512x_pllin_dac_rate(struct snd_soc_dai *dai,
+					    unsigned long osr_rate,
+					    unsigned long pllin_rate)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+	unsigned long dac_rate;
+
+	if (!pcm512x->pll_out)
+		return 0; /* no PLL to bypass, force SCK as DAC input */
+
+	if (pllin_rate % osr_rate)
+		return 0; /* futile, quit early */
+
+	/* run DAC no faster than 6144000 Hz */
+	for (dac_rate = rounddown(6144000, osr_rate);
+	     dac_rate;
+	     dac_rate -= osr_rate) {
+
+		if (pllin_rate / dac_rate > 128)
+			return 0; /* DAC divider would be too big */
+
+		if (!(pllin_rate % dac_rate))
+			return dac_rate;
+
+		dac_rate -= osr_rate;
+	}
+
+	return 0;
+}
+
 static int pcm512x_set_dividers(struct snd_soc_dai *dai,
 				struct snd_pcm_hw_params *params)
 {
@@ -672,6 +705,7 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
 	unsigned long bclk_rate;
 	unsigned long sample_rate;
 	unsigned long osr_rate;
+	unsigned long dacsrc_rate;
 	int bclk_div;
 	int lrclk_div;
 	int dsp_div;
@@ -679,11 +713,10 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
 	unsigned long dac_rate;
 	int ncp_div;
 	int osr_div;
-	unsigned long dac_mul;
-	unsigned long sck_mul;
 	int ret;
 	int idac;
 	int fssp;
+	int gpio;
 
 	lrclk_div = snd_soc_params_to_frame_size(params);
 	if (lrclk_div == 0) {
@@ -772,31 +805,72 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai,
 	/* run DSP no faster than 50 MHz */
 	dsp_div = mck_rate > 50000000 ? 2 : 1;
 
-	/* run DAC no faster than 6144000 Hz */
-	dac_mul = 6144000 / osr_rate;
-	sck_mul = sck_rate / osr_rate;
-	for (; dac_mul; dac_mul--) {
-		if (!(sck_mul % dac_mul))
-			break;
-	}
-	if (!dac_mul) {
-		dev_err(dev, "Failed to find DAC rate\n");
-		return -EINVAL;
-	}
+	dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate);
+	if (dac_rate) {
+		/* the desired clock rate is "compatible" with the pll input
+		 * clock, so use that clock as dac input instead of the pll
+		 * output clock since the pll will introduce jitter and thus
+		 * noise.
+		 */
+		dev_dbg(dev, "using pll input as dac input\n");
+		ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
+					 PCM512x_SDAC, PCM512x_SDAC_GPIO);
+		if (ret != 0) {
+			dev_err(codec->dev,
+				"Failed to set gpio as dacref: %d\n", ret);
+			return ret;
+		}
 
-	dac_rate = dac_mul * osr_rate;
-	dev_dbg(dev, "dac_rate %lu sample_rate %lu\n", dac_rate, sample_rate);
+		gpio = PCM512x_GREF_GPIO1 + pcm512x->pll_in - 1;
+		ret = regmap_update_bits(pcm512x->regmap, PCM512x_GPIO_DACIN,
+					 PCM512x_GREF, gpio);
+		if (ret != 0) {
+			dev_err(codec->dev,
+				"Failed to set gpio %d as dacin: %d\n",
+				pcm512x->pll_in, ret);
+			return ret;
+		}
+
+		dacsrc_rate = pllin_rate;
+	} else {
+		/* run DAC no faster than 6144000 Hz */
+		unsigned long dac_mul = 6144000 / osr_rate;
+		unsigned long sck_mul = sck_rate / osr_rate;
+
+		for (; dac_mul; dac_mul--) {
+			if (!(sck_mul % dac_mul))
+				break;
+		}
+		if (!dac_mul) {
+			dev_err(dev, "Failed to find DAC rate\n");
+			return -EINVAL;
+		}
 
-	dac_div = DIV_ROUND_CLOSEST(sck_rate, dac_rate);
+		dac_rate = dac_mul * osr_rate;
+		dev_dbg(dev, "dac_rate %lu sample_rate %lu\n",
+			dac_rate, sample_rate);
+
+		ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
+					 PCM512x_SDAC, PCM512x_SDAC_SCK);
+		if (ret != 0) {
+			dev_err(codec->dev,
+				"Failed to set sck as dacref: %d\n", ret);
+			return ret;
+		}
+
+		dacsrc_rate = sck_rate;
+	}
+
+	dac_div = DIV_ROUND_CLOSEST(dacsrc_rate, dac_rate);
 	if (dac_div > 128) {
 		dev_err(dev, "Failed to find DAC divider\n");
 		return -EINVAL;
 	}
 
-	ncp_div = DIV_ROUND_CLOSEST(sck_rate / dac_div, 1536000);
-	if (ncp_div > 128 || sck_rate / dac_div / ncp_div > 2048000) {
+	ncp_div = DIV_ROUND_CLOSEST(dacsrc_rate / dac_div, 1536000);
+	if (ncp_div > 128 || dacsrc_rate / dac_div / ncp_div > 2048000) {
 		/* run NCP no faster than 2048000 Hz, but why? */
-		ncp_div = DIV_ROUND_UP(sck_rate / dac_div, 2048000);
+		ncp_div = DIV_ROUND_UP(dacsrc_rate / dac_div, 2048000);
 		if (ncp_div > 128) {
 			dev_err(dev, "Failed to find NCP divider\n");
 			return -EINVAL;
@@ -1011,13 +1085,6 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 	if (ret != 0)
 		return ret;
 
-	ret = regmap_update_bits(pcm512x->regmap, PCM512x_DAC_REF,
-				 PCM512x_SDAC, PCM512x_SDAC_SCK);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to set sck as dacref: %d\n", ret);
-		return ret;
-	}
-
 	if (pcm512x->pll_out) {
 		ret = regmap_update_bits(pcm512x->regmap, PCM512x_PLL_REF,
 					 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 @@
 #define PCM512x_MASTER_MODE       (PCM512x_PAGE_BASE(0) +  12)
 #define PCM512x_PLL_REF           (PCM512x_PAGE_BASE(0) +  13)
 #define PCM512x_DAC_REF           (PCM512x_PAGE_BASE(0) +  14)
+#define PCM512x_GPIO_DACIN        (PCM512x_PAGE_BASE(0) +  16)
 #define PCM512x_GPIO_PLLIN        (PCM512x_PAGE_BASE(0) +  18)
 #define PCM512x_SYNCHRONIZE       (PCM512x_PAGE_BASE(0) +  19)
 #define PCM512x_PLL_COEFF_0       (PCM512x_PAGE_BASE(0) +  20)
@@ -162,8 +163,9 @@
 #define PCM512x_SDAC_PLL    (1 << 4)
 #define PCM512x_SDAC_SCK    (3 << 4)
 #define PCM512x_SDAC_BCK    (4 << 4)
+#define PCM512x_SDAC_GPIO   (5 << 4)
 
-/* Page 0, Register 18 - GPIO source for PLL */
+/* Page 0, Register 16, 18 - GPIO source for DAC, PLL */
 #define PCM512x_GREF        (7 << 0)
 #define PCM512x_GREF_SHIFT  0
 #define PCM512x_GREF_GPIO1  (0 << 0)
