int pll_d;
        int pll_p;
        unsigned long real_pll;
+       unsigned long overclock_pll;
+       unsigned long overclock_dac;
+       unsigned long overclock_dsp;
 };
 
 /*
        }
 }
 
+static int pcm512x_overclock_pll_get(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = pcm512x->overclock_pll;
+       return 0;
+}
+
+static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+       switch (codec->dapm.bias_level) {
+       case SND_SOC_BIAS_OFF:
+       case SND_SOC_BIAS_STANDBY:
+               break;
+       default:
+               return -EBUSY;
+       }
+
+       pcm512x->overclock_pll = ucontrol->value.integer.value[0];
+       return 0;
+}
+
+static int pcm512x_overclock_dsp_get(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = pcm512x->overclock_dsp;
+       return 0;
+}
+
+static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+       switch (codec->dapm.bias_level) {
+       case SND_SOC_BIAS_OFF:
+       case SND_SOC_BIAS_STANDBY:
+               break;
+       default:
+               return -EBUSY;
+       }
+
+       pcm512x->overclock_dsp = ucontrol->value.integer.value[0];
+       return 0;
+}
+
+static int pcm512x_overclock_dac_get(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = pcm512x->overclock_dac;
+       return 0;
+}
+
+static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+       struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
+
+       switch (codec->dapm.bias_level) {
+       case SND_SOC_BIAS_OFF:
+       case SND_SOC_BIAS_STANDBY:
+               break;
+       default:
+               return -EBUSY;
+       }
+
+       pcm512x->overclock_dac = ucontrol->value.integer.value[0];
+       return 0;
+}
+
 static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
 static const DECLARE_TLV_DB_SCALE(analog_tlv, -600, 600, 0);
 static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 80, 0);
 SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
 SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
 SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
+
+SOC_SINGLE_EXT("Max Overclock PLL", SND_SOC_NOPM, 0, 20, 0,
+              pcm512x_overclock_pll_get, pcm512x_overclock_pll_put),
+SOC_SINGLE_EXT("Max Overclock DSP", SND_SOC_NOPM, 0, 40, 0,
+              pcm512x_overclock_dsp_get, pcm512x_overclock_dsp_put),
+SOC_SINGLE_EXT("Max Overclock DAC", SND_SOC_NOPM, 0, 40, 0,
+              pcm512x_overclock_dac_get, pcm512x_overclock_dac_put),
 };
 
 static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
        { "OUTR", NULL, "DACR" },
 };
 
+static unsigned long pcm512x_pll_max(struct pcm512x_priv *pcm512x)
+{
+       return 25000000 + 25000000 * pcm512x->overclock_pll / 100;
+}
+
+static unsigned long pcm512x_dsp_max(struct pcm512x_priv *pcm512x)
+{
+       return 50000000 + 50000000 * pcm512x->overclock_dsp / 100;
+}
+
+static unsigned long pcm512x_dac_max(struct pcm512x_priv *pcm512x,
+                                    unsigned long rate)
+{
+       return rate + rate * pcm512x->overclock_dac / 100;
+}
+
+static unsigned long pcm512x_sck_max(struct pcm512x_priv *pcm512x)
+{
+       if (!pcm512x->pll_out)
+               return 25000000;
+       return pcm512x_pll_max(pcm512x);
+}
+
+static unsigned long pcm512x_ncp_target(struct pcm512x_priv *pcm512x,
+                                       unsigned long dac_rate)
+{
+       /*
+        * If the DAC is not actually overclocked, use the good old
+        * NCP target rate...
+        */
+       if (dac_rate <= 6144000)
+               return 1536000;
+       /*
+        * ...but if the DAC is in fact overclocked, bump the NCP target
+        * rate to get the recommended dividers even when overclocking.
+        */
+       return pcm512x_dac_max(pcm512x, 1536000);
+}
+
 static const u32 pcm512x_dai_rates[] = {
        8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
        88200, 96000, 176400, 192000, 384000,
 static int pcm512x_hw_rule_rate(struct snd_pcm_hw_params *params,
                                struct snd_pcm_hw_rule *rule)
 {
+       struct pcm512x_priv *pcm512x = rule->private;
        struct snd_interval ranges[2];
        int frame_size;
 
                 */
                memset(ranges, 0, sizeof(ranges));
                ranges[0].min = 8000;
-               ranges[0].max = 25000000 / frame_size / 2;
+               ranges[0].max = pcm512x_sck_max(pcm512x) / frame_size / 2;
                ranges[1].min = DIV_ROUND_UP(16000000, frame_size);
                ranges[1].max = 384000;
                break;
                return snd_pcm_hw_rule_add(substream->runtime, 0,
                                           SNDRV_PCM_HW_PARAM_RATE,
                                           pcm512x_hw_rule_rate,
-                                          NULL,
+                                          pcm512x,
                                           SNDRV_PCM_HW_PARAM_FRAME_BITS,
                                           SNDRV_PCM_HW_PARAM_CHANNELS, -1);
 
                                      unsigned long bclk_rate)
 {
        struct device *dev = dai->dev;
+       struct snd_soc_codec *codec = dai->codec;
+       struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec);
        unsigned long sck_rate;
        int pow2;
 
         * as many factors of 2 as possible, as that makes it easier
         * to find a fast DAC rate
         */
-       pow2 = 1 << fls((25000000 - 16000000) / bclk_rate);
+       pow2 = 1 << fls((pcm512x_pll_max(pcm512x) - 16000000) / bclk_rate);
        for (; pow2; pow2 >>= 1) {
-               sck_rate = rounddown(25000000, bclk_rate * pow2);
+               sck_rate = rounddown(pcm512x_pll_max(pcm512x),
+                                    bclk_rate * pow2);
                if (sck_rate >= 16000000)
                        break;
        }
                return 0; /* futile, quit early */
 
        /* run DAC no faster than 6144000 Hz */
-       for (dac_rate = rounddown(6144000, osr_rate);
+       for (dac_rate = rounddown(pcm512x_dac_max(pcm512x, 6144000), osr_rate);
             dac_rate;
             dac_rate -= osr_rate) {
 
        osr_rate = 16 * sample_rate;
 
        /* run DSP no faster than 50 MHz */
-       dsp_div = mck_rate > 50000000 ? 2 : 1;
+       dsp_div = mck_rate > pcm512x_dsp_max(pcm512x) ? 2 : 1;
 
        dac_rate = pcm512x_pllin_dac_rate(dai, osr_rate, pllin_rate);
        if (dac_rate) {
                dacsrc_rate = pllin_rate;
        } else {
                /* run DAC no faster than 6144000 Hz */
-               unsigned long dac_mul = 6144000 / osr_rate;
+               unsigned long dac_mul = pcm512x_dac_max(pcm512x, 6144000)
+                       / osr_rate;
                unsigned long sck_mul = sck_rate / osr_rate;
 
                for (; dac_mul; dac_mul--) {
        }
        dac_rate = dacsrc_rate / dac_div;
 
-       ncp_div = DIV_ROUND_CLOSEST(dac_rate, 1536000);
+       ncp_div = DIV_ROUND_CLOSEST(dac_rate,
+                                   pcm512x_ncp_target(pcm512x, dac_rate));
        if (ncp_div > 128 || dac_rate / ncp_div > 2048000) {
                /* run NCP no faster than 2048000 Hz, but why? */
                ncp_div = DIV_ROUND_UP(dac_rate, 2048000);
                return ret;
        }
 
-       if (sample_rate <= 48000)
+       if (sample_rate <= pcm512x_dac_max(pcm512x, 48000))
                fssp = PCM512x_FSSP_48KHZ;
-       else if (sample_rate <= 96000)
+       else if (sample_rate <= pcm512x_dac_max(pcm512x, 96000))
                fssp = PCM512x_FSSP_96KHZ;
-       else if (sample_rate <= 192000)
+       else if (sample_rate <= pcm512x_dac_max(pcm512x, 192000))
                fssp = PCM512x_FSSP_192KHZ;
        else
                fssp = PCM512x_FSSP_384KHZ;