#define ADAU1701_OSCIPOW_OPD           0x04
 #define ADAU1701_DACSET_DACINIT                1
 
+#define ADAU1707_CLKDIV_UNSET          (-1UL)
+
 #define ADAU1701_FIRMWARE "adau1701.bin"
 
 struct adau1701 {
        int gpio_nreset;
+       int gpio_pll_mode[2];
        unsigned int dai_fmt;
+       unsigned int pll_clkdiv;
+       unsigned int sysclk;
 };
 
 static const struct snd_kcontrol_new adau1701_controls[] = {
        return value;
 }
 
-static int adau1701_reset(struct snd_soc_codec *codec)
+static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
 {
        struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
        struct i2c_client *client = to_i2c_client(codec->dev);
        int ret;
 
+       if (clkdiv != ADAU1707_CLKDIV_UNSET &&
+           gpio_is_valid(adau1701->gpio_pll_mode[0]) &&
+           gpio_is_valid(adau1701->gpio_pll_mode[1])) {
+               switch (clkdiv) {
+               case 64:
+                       gpio_set_value(adau1701->gpio_pll_mode[0], 0);
+                       gpio_set_value(adau1701->gpio_pll_mode[1], 0);
+                       break;
+               case 256:
+                       gpio_set_value(adau1701->gpio_pll_mode[0], 0);
+                       gpio_set_value(adau1701->gpio_pll_mode[1], 1);
+                       break;
+               case 384:
+                       gpio_set_value(adau1701->gpio_pll_mode[0], 1);
+                       gpio_set_value(adau1701->gpio_pll_mode[1], 0);
+                       break;
+               case 0: /* fallback */
+               case 512:
+                       gpio_set_value(adau1701->gpio_pll_mode[0], 1);
+                       gpio_set_value(adau1701->gpio_pll_mode[1], 1);
+                       break;
+               }
+       }
+
+       adau1701->pll_clkdiv = clkdiv;
+
        if (gpio_is_valid(adau1701->gpio_nreset)) {
                gpio_set_value(adau1701->gpio_nreset, 0);
                /* minimum reset time is 20ns */
                mdelay(85);
        }
 
-       ret = process_sigma_firmware(client, ADAU1701_FIRMWARE);
-       if (ret) {
-               dev_warn(codec->dev, "Failed to load firmware\n");
-               return ret;
+       /*
+        * Postpone the firmware download to a point in time when we
+        * know the correct PLL setup
+        */
+       if (clkdiv != ADAU1707_CLKDIV_UNSET) {
+               ret = process_sigma_firmware(client, ADAU1701_FIRMWARE);
+               if (ret) {
+                       dev_warn(codec->dev, "Failed to load firmware\n");
+                       return ret;
+               }
        }
 
        snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT);
                struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
+       struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
+       unsigned int clkdiv = adau1701->sysclk / params_rate(params);
        snd_pcm_format_t format;
        unsigned int val;
+       int ret;
+
+       /*
+        * If the mclk/lrclk ratio changes, the chip needs updated PLL
+        * mode GPIO settings, and a full reset cycle, including a new
+        * firmware upload.
+        */
+       if (clkdiv != adau1701->pll_clkdiv) {
+               ret = adau1701_reset(codec, clkdiv);
+               if (ret < 0)
+                       return ret;
+       }
 
        switch (params_rate(params)) {
        case 192000:
        int source, unsigned int freq, int dir)
 {
        unsigned int val;
+       struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
 
        switch (clk_id) {
        case ADAU1701_CLK_SRC_OSC:
        }
 
        snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val);
+       adau1701->sysclk = freq;
 
        return 0;
 }
 static int adau1701_probe(struct snd_soc_codec *codec)
 {
        int ret;
+       struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
 
        codec->control_data = to_i2c_client(codec->dev);
 
-       ret = adau1701_reset(codec);
-       if (ret)
+       /*
+        * Let the pll_clkdiv variable default to something that won't happen
+        * at runtime. That way, we can postpone the firmware download from
+        * adau1701_reset() to a point in time when we know the correct PLL
+        * mode parameters.
+        */
+       adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET;
+
+       /* initalize with pre-configured pll mode settings */
+       ret = adau1701_reset(codec, adau1701->pll_clkdiv);
+       if (ret < 0)
                return ret;
 
        return 0;
        struct adau1701 *adau1701;
        struct device *dev = &client->dev;
        int gpio_nreset = -EINVAL;
+       int gpio_pll_mode[2] = { -EINVAL, -EINVAL };
        int ret;
 
        adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL);
                gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0);
                if (gpio_nreset < 0 && gpio_nreset != -ENOENT)
                        return gpio_nreset;
+
+               gpio_pll_mode[0] = of_get_named_gpio(dev->of_node,
+                                                  "adi,pll-mode-gpios", 0);
+               if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT)
+                       return gpio_pll_mode[0];
+
+               gpio_pll_mode[1] = of_get_named_gpio(dev->of_node,
+                                                  "adi,pll-mode-gpios", 1);
+               if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT)
+                       return gpio_pll_mode[1];
        }
 
        if (gpio_is_valid(gpio_nreset)) {
                        return ret;
        }
 
+       if (gpio_is_valid(gpio_pll_mode[0]) &&
+           gpio_is_valid(gpio_pll_mode[1])) {
+               ret = devm_gpio_request_one(dev, gpio_pll_mode[0],
+                                           GPIOF_OUT_INIT_LOW,
+                                           "ADAU1701 PLL mode 0");
+               if (ret < 0)
+                       return ret;
+
+               ret = devm_gpio_request_one(dev, gpio_pll_mode[1],
+                                           GPIOF_OUT_INIT_LOW,
+                                           "ADAU1701 PLL mode 1");
+               if (ret < 0)
+                       return ret;
+       }
+
        adau1701->gpio_nreset = gpio_nreset;
+       adau1701->gpio_pll_mode[0] = gpio_pll_mode[0];
+       adau1701->gpio_pll_mode[1] = gpio_pll_mode[1];
 
        i2c_set_clientdata(client, adau1701);
        ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv,