ASoC: codecs: add support for rk3328
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / adav80x.c
index 3c839cc4e00ecb48a5e3948567c14dbede7706a3..acff8d62059cf49de24585aeac9c2143412c0175 100644 (file)
@@ -8,17 +8,15 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
-#include <sound/core.h>
+
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
-#include <sound/tlv.h>
 #include <sound/soc.h>
+#include <sound/tlv.h>
 
 #include "adav80x.h"
 
 
 #define ADAV80X_PLL_OUTE_SYSCLKPD(x)           BIT(2 - (x))
 
-static u8 adav80x_default_regs[] = {
-       0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0x80, 0x26, 0x00, 0x00,
-       0x02, 0x40, 0x20, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x92, 0xb1, 0x37,
-       0x48, 0xd2, 0xfb, 0xca, 0xd2, 0x15, 0xe8, 0x29, 0xb9, 0x6a, 0xda, 0x2b,
-       0xb7, 0xc0, 0x11, 0x65, 0x5c, 0xf6, 0xff, 0x8d, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00,
-       0x00, 0xe8, 0x46, 0xe1, 0x5b, 0xd3, 0x43, 0x77, 0x93, 0xa7, 0x44, 0xee,
-       0x32, 0x12, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x3f,
-       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x52, 0x00,
+static const struct reg_default adav80x_reg_defaults[] = {
+       { ADAV80X_PLAYBACK_CTRL,        0x01 },
+       { ADAV80X_AUX_IN_CTRL,          0x01 },
+       { ADAV80X_REC_CTRL,             0x02 },
+       { ADAV80X_AUX_OUT_CTRL,         0x01 },
+       { ADAV80X_DPATH_CTRL1,          0xc0 },
+       { ADAV80X_DPATH_CTRL2,          0x11 },
+       { ADAV80X_DAC_CTRL1,            0x00 },
+       { ADAV80X_DAC_CTRL2,            0x00 },
+       { ADAV80X_DAC_CTRL3,            0x00 },
+       { ADAV80X_DAC_L_VOL,            0xff },
+       { ADAV80X_DAC_R_VOL,            0xff },
+       { ADAV80X_PGA_L_VOL,            0x00 },
+       { ADAV80X_PGA_R_VOL,            0x00 },
+       { ADAV80X_ADC_CTRL1,            0x00 },
+       { ADAV80X_ADC_CTRL2,            0x00 },
+       { ADAV80X_ADC_L_VOL,            0xff },
+       { ADAV80X_ADC_R_VOL,            0xff },
+       { ADAV80X_PLL_CTRL1,            0x00 },
+       { ADAV80X_PLL_CTRL2,            0x00 },
+       { ADAV80X_ICLK_CTRL1,           0x00 },
+       { ADAV80X_ICLK_CTRL2,           0x00 },
+       { ADAV80X_PLL_CLK_SRC,          0x00 },
+       { ADAV80X_PLL_OUTE,             0x00 },
 };
 
 struct adav80x {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
 
        enum adav80x_clk_src clk_src;
        unsigned int sysclk;
@@ -162,14 +172,14 @@ static ADAV80X_MUX_ENUM_DECL(adav80x_capture_enum, ADAV80X_DPATH_CTRL1, 3);
 static ADAV80X_MUX_ENUM_DECL(adav80x_dac_enum, ADAV80X_DPATH_CTRL2, 3);
 
 static const struct snd_kcontrol_new adav80x_aux_capture_mux_ctrl =
-       SOC_DAPM_VALUE_ENUM("Route", adav80x_aux_capture_enum);
+       SOC_DAPM_ENUM("Route", adav80x_aux_capture_enum);
 static const struct snd_kcontrol_new adav80x_capture_mux_ctrl =
-       SOC_DAPM_VALUE_ENUM("Route", adav80x_capture_enum);
+       SOC_DAPM_ENUM("Route", adav80x_capture_enum);
 static const struct snd_kcontrol_new adav80x_dac_mux_ctrl =
-       SOC_DAPM_VALUE_ENUM("Route", adav80x_dac_enum);
+       SOC_DAPM_ENUM("Route", adav80x_dac_enum);
 
 #define ADAV80X_MUX(name, ctrl) \
-       SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+       SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
 static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = {
        SND_SOC_DAPM_DAC("DAC", NULL, ADAV80X_DAC_CTRL1, 7, 1),
@@ -202,7 +212,7 @@ static const struct snd_soc_dapm_widget adav80x_dapm_widgets[] = {
 static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source,
                         struct snd_soc_dapm_widget *sink)
 {
-       struct snd_soc_codec *codec = source->codec;
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        const char *clk;
 
@@ -226,7 +236,7 @@ static int adav80x_dapm_sysclk_check(struct snd_soc_dapm_widget *source,
 static int adav80x_dapm_pll_check(struct snd_soc_dapm_widget *source,
                         struct snd_soc_dapm_widget *sink)
 {
-       struct snd_soc_codec *codec = source->codec;
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
        return adav80x->pll_src == ADAV80X_PLL_SRC_XTAL;
@@ -298,16 +308,16 @@ static int adav80x_set_deemph(struct snd_soc_codec *codec)
                val = ADAV80X_DAC_CTRL2_DEEMPH_NONE;
        }
 
-       return snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2,
+       return regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2,
                ADAV80X_DAC_CTRL2_DEEMPH_MASK, val);
 }
 
 static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
-       unsigned int deemph = ucontrol->value.enumerated.item[0];
+       unsigned int deemph = ucontrol->value.integer.value[0];
 
        if (deemph > 1)
                return -EINVAL;
@@ -320,10 +330,10 @@ static int adav80x_put_deemph(struct snd_kcontrol *kcontrol,
 static int adav80x_get_deemph(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_value *ucontrol)
 {
-       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.enumerated.item[0] = adav80x->deemph;
+       ucontrol->value.integer.value[0] = adav80x->deemph;
        return 0;
 };
 
@@ -394,10 +404,11 @@ static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
 
-       snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0],
+       regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0],
                ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER,
                capture);
-       snd_soc_write(codec, adav80x_port_ctrl_regs[dai->id][1], playback);
+       regmap_write(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1],
+               playback);
 
        adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 
@@ -407,6 +418,7 @@ static int adav80x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static int adav80x_set_adc_clock(struct snd_soc_codec *codec,
                unsigned int sample_rate)
 {
+       struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        unsigned int val;
 
        if (sample_rate <= 48000)
@@ -414,7 +426,7 @@ static int adav80x_set_adc_clock(struct snd_soc_codec *codec,
        else
                val = ADAV80X_ADC_CTRL1_MODULATOR_64FS;
 
-       snd_soc_update_bits(codec, ADAV80X_ADC_CTRL1,
+       regmap_update_bits(adav80x->regmap, ADAV80X_ADC_CTRL1,
                ADAV80X_ADC_CTRL1_MODULATOR_MASK, val);
 
        return 0;
@@ -423,6 +435,7 @@ static int adav80x_set_adc_clock(struct snd_soc_codec *codec,
 static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
                unsigned int sample_rate)
 {
+       struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        unsigned int val;
 
        if (sample_rate <= 48000)
@@ -430,7 +443,7 @@ static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
        else
                val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS;
 
-       snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2,
+       regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2,
                ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK,
                val);
 
@@ -438,35 +451,36 @@ static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
 }
 
 static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec,
-               struct snd_soc_dai *dai, snd_pcm_format_t format)
+               struct snd_soc_dai *dai, struct snd_pcm_hw_params *params)
 {
+       struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        unsigned int val;
 
-       switch (format) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                val = ADAV80X_CAPTURE_WORD_LEN16;
                break;
-       case SNDRV_PCM_FORMAT_S18_3LE:
+       case 18:
                val = ADAV80X_CAPTRUE_WORD_LEN18;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                val = ADAV80X_CAPTURE_WORD_LEN20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                val = ADAV80X_CAPTURE_WORD_LEN24;
                break;
        default:
                return -EINVAL;
        }
 
-       snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0],
+       regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0],
                ADAV80X_CAPTURE_WORD_LEN_MASK, val);
 
        return 0;
 }
 
 static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec,
-               struct snd_soc_dai *dai, snd_pcm_format_t format)
+               struct snd_soc_dai *dai, struct snd_pcm_hw_params *params)
 {
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        unsigned int val;
@@ -474,24 +488,24 @@ static int adav80x_set_playback_pcm_format(struct snd_soc_codec *codec,
        if (adav80x->dai_fmt[dai->id] != SND_SOC_DAIFMT_RIGHT_J)
                return 0;
 
-       switch (format) {
-       case SNDRV_PCM_FORMAT_S16_LE:
+       switch (params_width(params)) {
+       case 16:
                val = ADAV80X_PLAYBACK_MODE_RIGHT_J_16;
                break;
-       case SNDRV_PCM_FORMAT_S18_3LE:
+       case 18:
                val = ADAV80X_PLAYBACK_MODE_RIGHT_J_18;
                break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
+       case 20:
                val = ADAV80X_PLAYBACK_MODE_RIGHT_J_20;
                break;
-       case SNDRV_PCM_FORMAT_S24_LE:
+       case 24:
                val = ADAV80X_PLAYBACK_MODE_RIGHT_J_24;
                break;
        default:
                return -EINVAL;
        }
 
-       snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][1],
+       regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1],
                ADAV80X_PLAYBACK_MODE_MASK, val);
 
        return 0;
@@ -508,12 +522,10 @@ static int adav80x_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               adav80x_set_playback_pcm_format(codec, dai,
-                       params_format(params));
+               adav80x_set_playback_pcm_format(codec, dai, params);
                adav80x_set_dac_clock(codec, rate);
        } else {
-               adav80x_set_capture_pcm_format(codec, dai,
-                       params_format(params));
+               adav80x_set_capture_pcm_format(codec, dai, params);
                adav80x_set_adc_clock(codec, rate);
        }
        adav80x->rate = rate;
@@ -527,6 +539,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
                              unsigned int freq, int dir)
 {
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+       struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 
        if (dir == SND_SOC_CLOCK_IN) {
                switch (clk_id) {
@@ -554,10 +567,12 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
                                        ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id);
                        iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id);
 
-                       snd_soc_write(codec, ADAV80X_ICLK_CTRL1, iclk_ctrl1);
-                       snd_soc_write(codec, ADAV80X_ICLK_CTRL2, iclk_ctrl2);
+                       regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL1,
+                               iclk_ctrl1);
+                       regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2,
+                               iclk_ctrl2);
 
-                       snd_soc_dapm_sync(&codec->dapm);
+                       snd_soc_dapm_sync(dapm);
                }
        } else {
                unsigned int mask;
@@ -575,24 +590,30 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
                mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id);
 
                if (freq == 0) {
-                       snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, mask);
+                       regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE,
+                               mask, mask);
                        adav80x->sysclk_pd[clk_id] = true;
                } else {
-                       snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, 0);
+                       regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE,
+                               mask, 0);
                        adav80x->sysclk_pd[clk_id] = false;
                }
 
+               snd_soc_dapm_mutex_lock(dapm);
+
                if (adav80x->sysclk_pd[0])
-                       snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
+                       snd_soc_dapm_disable_pin_unlocked(dapm, "PLL1");
                else
-                       snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
+                       snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL1");
 
                if (adav80x->sysclk_pd[1] || adav80x->sysclk_pd[2])
-                       snd_soc_dapm_disable_pin(&codec->dapm, "PLL2");
+                       snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2");
                else
-                       snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
+                       snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2");
 
-               snd_soc_dapm_sync(&codec->dapm);
+               snd_soc_dapm_sync_unlocked(dapm);
+
+               snd_soc_dapm_mutex_unlock(dapm);
        }
 
        return 0;
@@ -601,6 +622,7 @@ static int adav80x_set_sysclk(struct snd_soc_codec *codec,
 static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
                int source, unsigned int freq_in, unsigned int freq_out)
 {
+       struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        unsigned int pll_ctrl1 = 0;
        unsigned int pll_ctrl2 = 0;
@@ -650,9 +672,9 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
                return -EINVAL;
        }
 
-       snd_soc_update_bits(codec, ADAV80X_PLL_CTRL1, ADAV80X_PLL_CTRL1_PLLDIV,
-               pll_ctrl1);
-       snd_soc_update_bits(codec, ADAV80X_PLL_CTRL2,
+       regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL1,
+                       ADAV80X_PLL_CTRL1_PLLDIV, pll_ctrl1);
+       regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL2,
                        ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2);
 
        if (source != adav80x->pll_src) {
@@ -661,12 +683,12 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
                else
                        pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id);
 
-               snd_soc_update_bits(codec, ADAV80X_PLL_CLK_SRC,
+               regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CLK_SRC,
                                ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src);
 
                adav80x->pll_src = source;
 
-               snd_soc_dapm_sync(&codec->dapm);
+               snd_soc_dapm_sync(dapm);
        }
 
        return 0;
@@ -675,6 +697,7 @@ static int adav80x_set_pll(struct snd_soc_codec *codec, int pll_id,
 static int adav80x_set_bias_level(struct snd_soc_codec *codec,
                enum snd_soc_bias_level level)
 {
+       struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
        unsigned int mask = ADAV80X_DAC_CTRL1_PD;
 
        switch (level) {
@@ -683,14 +706,15 @@ static int adav80x_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
-               snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, 0x00);
+               regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask,
+                       0x00);
                break;
        case SND_SOC_BIAS_OFF:
-               snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, mask);
+               regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask,
+                       mask);
                break;
        }
 
-       codec->dapm.bias_level = level;
        return 0;
 }
 
@@ -701,11 +725,11 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = dai->codec;
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-       if (!codec->active || !adav80x->rate)
+       if (!snd_soc_codec_is_active(codec) || !adav80x->rate)
                return 0;
 
-       return snd_pcm_hw_constraint_minmax(substream->runtime,
-                       SNDRV_PCM_HW_PARAM_RATE, adav80x->rate, adav80x->rate);
+       return snd_pcm_hw_constraint_single(substream->runtime,
+                       SNDRV_PCM_HW_PARAM_RATE, adav80x->rate);
 }
 
 static void adav80x_dai_shutdown(struct snd_pcm_substream *substream,
@@ -714,7 +738,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = dai->codec;
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-       if (!codec->active)
+       if (!snd_soc_codec_is_active(codec))
                adav80x->rate = 0;
 }
 
@@ -777,60 +801,39 @@ static struct snd_soc_dai_driver adav80x_dais[] = {
 
 static int adav80x_probe(struct snd_soc_codec *codec)
 {
-       int ret;
+       struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
        struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, adav80x->control_type);
-       if (ret) {
-               dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
-               return ret;
-       }
-
        /* Force PLLs on for SYSCLK output */
-       snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
-       snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
+       snd_soc_dapm_force_enable_pin(dapm, "PLL1");
+       snd_soc_dapm_force_enable_pin(dapm, "PLL2");
 
        /* Power down S/PDIF receiver, since it is currently not supported */
-       snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x20);
+       regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20);
        /* Disable DAC zero flag */
-       snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6);
-
-       return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-}
+       regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6);
 
-static int adav80x_suspend(struct snd_soc_codec *codec)
-{
-       return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
 static int adav80x_resume(struct snd_soc_codec *codec)
 {
-       adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       codec->cache_sync = 1;
-       snd_soc_cache_sync(codec);
+       struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-       return 0;
-}
+       regcache_sync(adav80x->regmap);
 
-static int adav80x_remove(struct snd_soc_codec *codec)
-{
-       return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
 static struct snd_soc_codec_driver adav80x_codec_driver = {
        .probe = adav80x_probe,
-       .remove = adav80x_remove,
-       .suspend = adav80x_suspend,
        .resume = adav80x_resume,
        .set_bias_level = adav80x_set_bias_level,
+       .suspend_bias_off = true,
 
        .set_pll = adav80x_set_pll,
        .set_sysclk = adav80x_set_sysclk,
 
-       .reg_word_size = sizeof(u8),
-       .reg_cache_size = ARRAY_SIZE(adav80x_default_regs),
-       .reg_cache_default = adav80x_default_regs,
-
        .controls = adav80x_controls,
        .num_controls = ARRAY_SIZE(adav80x_controls),
        .dapm_widgets = adav80x_dapm_widgets,
@@ -839,112 +842,37 @@ static struct snd_soc_codec_driver adav80x_codec_driver = {
        .num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
 };
 
-static int adav80x_bus_probe(struct device *dev,
-                            enum snd_soc_control_type control_type)
+int adav80x_bus_probe(struct device *dev, struct regmap *regmap)
 {
        struct adav80x *adav80x;
-       int ret;
 
-       adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
+       adav80x = devm_kzalloc(dev, sizeof(*adav80x), GFP_KERNEL);
        if (!adav80x)
                return -ENOMEM;
 
        dev_set_drvdata(dev, adav80x);
-       adav80x->control_type = control_type;
+       adav80x->regmap = regmap;
 
-       ret = snd_soc_register_codec(dev, &adav80x_codec_driver,
+       return snd_soc_register_codec(dev, &adav80x_codec_driver,
                adav80x_dais, ARRAY_SIZE(adav80x_dais));
-       if (ret)
-               kfree(adav80x);
-
-       return ret;
-}
-
-static int adav80x_bus_remove(struct device *dev)
-{
-       snd_soc_unregister_codec(dev);
-       kfree(dev_get_drvdata(dev));
-       return 0;
-}
-
-#if defined(CONFIG_SPI_MASTER)
-static int adav80x_spi_probe(struct spi_device *spi)
-{
-       return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
-}
-
-static int adav80x_spi_remove(struct spi_device *spi)
-{
-       return adav80x_bus_remove(&spi->dev);
 }
+EXPORT_SYMBOL_GPL(adav80x_bus_probe);
 
-static struct spi_driver adav80x_spi_driver = {
-       .driver = {
-               .name   = "adav801",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = adav80x_spi_probe,
-       .remove         = adav80x_spi_remove,
-};
-#endif
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static const struct i2c_device_id adav80x_id[] = {
-       { "adav803", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, adav80x_id);
-
-static int adav80x_i2c_probe(struct i2c_client *client,
-                            const struct i2c_device_id *id)
-{
-       return adav80x_bus_probe(&client->dev, SND_SOC_I2C);
-}
+const struct regmap_config adav80x_regmap_config = {
+       .val_bits = 8,
+       .pad_bits = 1,
+       .reg_bits = 7,
 
-static int adav80x_i2c_remove(struct i2c_client *client)
-{
-       return adav80x_bus_remove(&client->dev);
-}
+       .max_register = ADAV80X_PLL_OUTE,
 
-static struct i2c_driver adav80x_i2c_driver = {
-       .driver = {
-               .name = "adav803",
-               .owner = THIS_MODULE,
-       },
-       .probe = adav80x_i2c_probe,
-       .remove = adav80x_i2c_remove,
-       .id_table = adav80x_id,
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = adav80x_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
 };
-#endif
-
-static int __init adav80x_init(void)
-{
-       int ret = 0;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       ret = i2c_add_driver(&adav80x_i2c_driver);
-       if (ret)
-               return ret;
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-       ret = spi_register_driver(&adav80x_spi_driver);
-#endif
-
-       return ret;
-}
-module_init(adav80x_init);
-
-static void __exit adav80x_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_driver(&adav80x_i2c_driver);
-#endif
-#if defined(CONFIG_SPI_MASTER)
-       spi_unregister_driver(&adav80x_spi_driver);
-#endif
-}
-module_exit(adav80x_exit);
+EXPORT_SYMBOL_GPL(adav80x_regmap_config);
 
 MODULE_DESCRIPTION("ASoC ADAV80x driver");
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");