diff options
Diffstat (limited to 'sound/soc/codecs/wm8753.c')
| -rw-r--r-- | sound/soc/codecs/wm8753.c | 773 | 
1 files changed, 356 insertions, 417 deletions
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 8f679a13f2b..53e57b4049a 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1,7 +1,7 @@  /*   * wm8753.c  --  WM8753 ALSA Soc Audio driver   * - * Copyright 2003 Wolfson Microelectronics PLC. + * Copyright 2003-11 Wolfson Microelectronics PLC.   * Author: Liam Girdwood <lrg@slimlogic.co.uk>   *   *  This program is free software; you can redistribute  it and/or modify it @@ -38,14 +38,14 @@  #include <linux/delay.h>  #include <linux/pm.h>  #include <linux/i2c.h> -#include <linux/platform_device.h> +#include <linux/of_device.h> +#include <linux/regmap.h>  #include <linux/spi/spi.h>  #include <linux/slab.h>  #include <sound/core.h>  #include <sound/pcm.h>  #include <sound/pcm_params.h>  #include <sound/soc.h> -#include <sound/soc-dapm.h>  #include <sound/initval.h>  #include <sound/tlv.h>  #include <asm/div64.h> @@ -56,89 +56,106 @@ static int caps_charge = 2000;  module_param(caps_charge, int, 0);  MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); -static void wm8753_set_dai_mode(struct snd_soc_codec *codec, -		struct snd_soc_dai *dai, unsigned int hifi); +static int wm8753_hifi_write_dai_fmt(struct snd_soc_codec *codec, +		unsigned int fmt); +static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec, +		unsigned int fmt);  /*   * wm8753 register cache   * We can't read the WM8753 register space when we   * are using 2 wire for device control, so we cache them instead.   */ -static const u16 wm8753_reg[] = { -	0x0008, 0x0000, 0x000a, 0x000a, -	0x0033, 0x0000, 0x0007, 0x00ff, -	0x00ff, 0x000f, 0x000f, 0x007b, -	0x0000, 0x0032, 0x0000, 0x00c3, -	0x00c3, 0x00c0, 0x0000, 0x0000, -	0x0000, 0x0000, 0x0000, 0x0000, -	0x0000, 0x0000, 0x0000, 0x0000, -	0x0000, 0x0000, 0x0000, 0x0055, -	0x0005, 0x0050, 0x0055, 0x0050, -	0x0055, 0x0050, 0x0055, 0x0079, -	0x0079, 0x0079, 0x0079, 0x0079, -	0x0000, 0x0000, 0x0000, 0x0000, -	0x0097, 0x0097, 0x0000, 0x0004, -	0x0000, 0x0083, 0x0024, 0x01ba, -	0x0000, 0x0083, 0x0024, 0x01ba, -	0x0000, 0x0000, 0x0000 +static const struct reg_default wm8753_reg_defaults[] = { +	{ 0x00, 0x0000 }, +	{ 0x01, 0x0008 }, +	{ 0x02, 0x0000 }, +	{ 0x03, 0x000a }, +	{ 0x04, 0x000a }, +	{ 0x05, 0x0033 }, +	{ 0x06, 0x0000 }, +	{ 0x07, 0x0007 }, +	{ 0x08, 0x00ff }, +	{ 0x09, 0x00ff }, +	{ 0x0a, 0x000f }, +	{ 0x0b, 0x000f }, +	{ 0x0c, 0x007b }, +	{ 0x0d, 0x0000 }, +	{ 0x0e, 0x0032 }, +	{ 0x0f, 0x0000 }, +	{ 0x10, 0x00c3 }, +	{ 0x11, 0x00c3 }, +	{ 0x12, 0x00c0 }, +	{ 0x13, 0x0000 }, +	{ 0x14, 0x0000 }, +	{ 0x15, 0x0000 }, +	{ 0x16, 0x0000 }, +	{ 0x17, 0x0000 }, +	{ 0x18, 0x0000 }, +	{ 0x19, 0x0000 }, +	{ 0x1a, 0x0000 }, +	{ 0x1b, 0x0000 }, +	{ 0x1c, 0x0000 }, +	{ 0x1d, 0x0000 }, +	{ 0x1e, 0x0000 }, +	{ 0x1f, 0x0000 }, +	{ 0x20, 0x0055 }, +	{ 0x21, 0x0005 }, +	{ 0x22, 0x0050 }, +	{ 0x23, 0x0055 }, +	{ 0x24, 0x0050 }, +	{ 0x25, 0x0055 }, +	{ 0x26, 0x0050 }, +	{ 0x27, 0x0055 }, +	{ 0x28, 0x0079 }, +	{ 0x29, 0x0079 }, +	{ 0x2a, 0x0079 }, +	{ 0x2b, 0x0079 }, +	{ 0x2c, 0x0079 }, +	{ 0x2d, 0x0000 }, +	{ 0x2e, 0x0000 }, +	{ 0x2f, 0x0000 }, +	{ 0x30, 0x0000 }, +	{ 0x31, 0x0097 }, +	{ 0x32, 0x0097 }, +	{ 0x33, 0x0000 }, +	{ 0x34, 0x0004 }, +	{ 0x35, 0x0000 }, +	{ 0x36, 0x0083 }, +	{ 0x37, 0x0024 }, +	{ 0x38, 0x01ba }, +	{ 0x39, 0x0000 }, +	{ 0x3a, 0x0083 }, +	{ 0x3b, 0x0024 }, +	{ 0x3c, 0x01ba }, +	{ 0x3d, 0x0000 }, +	{ 0x3e, 0x0000 }, +	{ 0x3f, 0x0000 },  }; -/* codec private data */ -struct wm8753_priv { -	enum snd_soc_control_type control_type; -	unsigned int sysclk; -	unsigned int pcmclk; -	u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; -	int dai_func; -}; - -/* - * read wm8753 register cache - */ -static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec, -	unsigned int reg) +static bool wm8753_volatile(struct device *dev, unsigned int reg)  { -	u16 *cache = codec->reg_cache; -	if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) -		return -1; -	return cache[reg - 1]; +	return reg == WM8753_RESET;  } -/* - * write wm8753 register cache - */ -static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec, -	unsigned int reg, unsigned int value) +static bool wm8753_writeable(struct device *dev, unsigned int reg)  { -	u16 *cache = codec->reg_cache; -	if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) -		return; -	cache[reg - 1] = value; +	return reg <= WM8753_ADCTL2;  } -/* - * write to the WM8753 register space - */ -static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg, -	unsigned int value) -{ -	u8 data[2]; +/* codec private data */ +struct wm8753_priv { +	struct regmap *regmap; +	unsigned int sysclk; +	unsigned int pcmclk; -	/* data is -	 *   D15..D9 WM8753 register offset -	 *   D8...D0 register data -	 */ -	data[0] = (reg << 1) | ((value >> 8) & 0x0001); -	data[1] = value & 0x00ff; +	unsigned int voice_fmt; +	unsigned int hifi_fmt; -	wm8753_write_reg_cache(codec, reg, value); -	if (codec->hw_write(codec->control_data, data, 2) == 2) -		return 0; -	else -		return -EIO; -} +	int dai_func; +}; -#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0) +#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)  /*   * WM8753 Controls @@ -217,27 +234,40 @@ SOC_ENUM_SINGLE(WM8753_OUTCTL, 2, 2, wm8753_rout2_phase),  static int wm8753_get_dai(struct snd_kcontrol *kcontrol,  	struct snd_ctl_elem_value *ucontrol)  { -	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol); -	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); +	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); -	ucontrol->value.integer.value[0] = (mode & 0xc) >> 2; +	ucontrol->value.integer.value[0] = wm8753->dai_func;  	return 0;  }  static int wm8753_set_dai(struct snd_kcontrol *kcontrol,  	struct snd_ctl_elem_value *ucontrol)  { -	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol); -	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); +	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); +	u16 ioctl; -	if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) +	if (wm8753->dai_func == ucontrol->value.integer.value[0])  		return 0; -	mode &= 0xfff3; -	mode |= (ucontrol->value.integer.value[0] << 2); +	if (snd_soc_codec_is_active(codec)) +		return -EBUSY; + +	ioctl = snd_soc_read(codec, WM8753_IOCTL); + +	wm8753->dai_func = ucontrol->value.integer.value[0]; + +	if (((ioctl >> 2) & 0x3) == wm8753->dai_func) +		return 1; + +	ioctl = (ioctl & 0x1f3) | (wm8753->dai_func << 2); +	snd_soc_write(codec, WM8753_IOCTL, ioctl); + + +	wm8753_hifi_write_dai_fmt(codec, wm8753->hifi_fmt); +	wm8753_voice_write_dai_fmt(codec, wm8753->voice_fmt); -	wm8753->dai_func =  ucontrol->value.integer.value[0];  	return 1;  } @@ -514,7 +544,7 @@ SND_SOC_DAPM_INPUT("MIC2"),  SND_SOC_DAPM_VMID("VREF"),  }; -static const struct snd_soc_dapm_route audio_map[] = { +static const struct snd_soc_dapm_route wm8753_dapm_routes[] = {  	/* left mixer */  	{"Left Mixer", "Left Playback Switch", "Left DAC"},  	{"Left Mixer", "Voice Playback Switch", "Voice DAC"}, @@ -668,16 +698,6 @@ static const struct snd_soc_dapm_route audio_map[] = {  	{"ACOP", NULL, "ALC Mixer"},  }; -static int wm8753_add_widgets(struct snd_soc_codec *codec) -{ -	snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets, -				  ARRAY_SIZE(wm8753_dapm_widgets)); - -	snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - -	return 0; -} -  /* PLL divisors */  struct _pll_div {  	u32 div2:1; @@ -738,17 +758,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,  	if (pll_id == WM8753_PLL1) {  		offset = 0;  		enable = 0x10; -		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef; +		reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef;  	} else {  		offset = 4;  		enable = 0x8; -		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7; +		reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7;  	}  	if (!freq_in || !freq_out) {  		/* disable PLL  */ -		wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); -		wm8753_write(codec, WM8753_CLOCK, reg); +		snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); +		snd_soc_write(codec, WM8753_CLOCK, reg);  		return 0;  	} else {  		u16 value = 0; @@ -759,20 +779,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,  		/* set up N and K PLL divisor ratios */  		/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */  		value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); -		wm8753_write(codec, WM8753_PLL1CTL2 + offset, value); +		snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value);  		/* bits 8:0 = PLL_K[17:9] */  		value = (pll_div.k & 0x03fe00) >> 9; -		wm8753_write(codec, WM8753_PLL1CTL3 + offset, value); +		snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value);  		/* bits 8:0 = PLL_K[8:0] */  		value = pll_div.k & 0x0001ff; -		wm8753_write(codec, WM8753_PLL1CTL4 + offset, value); +		snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value);  		/* set PLL as input and enable */ -		wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | +		snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |  			(pll_div.div2 << 3)); -		wm8753_write(codec, WM8753_CLOCK, reg | enable); +		snd_soc_write(codec, WM8753_CLOCK, reg | enable);  	}  	return 0;  } @@ -875,11 +895,10 @@ static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai,  /*   * Set's ADC and Voice DAC format.   */ -static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec *codec,  		unsigned int fmt)  { -	struct snd_soc_codec *codec = codec_dai->codec; -	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec; +	u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec;  	/* interface format */  	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -901,14 +920,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	wm8753_write(codec, WM8753_PCM, voice); -	return 0; -} - -static int wm8753_pcm_startup(struct snd_pcm_substream *substream, -				struct snd_soc_dai *dai) -{ -	wm8753_set_dai_mode(dai->codec, dai, 0); +	snd_soc_write(codec, WM8753_PCM, voice);  	return 0;  } @@ -919,11 +931,10 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,  				struct snd_pcm_hw_params *params,  				struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->codec; +	struct snd_soc_codec *codec = dai->codec;  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); -	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; -	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; +	u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3; +	u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;  	/* bit size */  	switch (params_format(params)) { @@ -943,23 +954,22 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,  	/* sample rate */  	if (params_rate(params) * 384 == wm8753->pcmclk)  		srate |= 0x80; -	wm8753_write(codec, WM8753_SRATE1, srate); +	snd_soc_write(codec, WM8753_SRATE1, srate); -	wm8753_write(codec, WM8753_PCM, voice); +	snd_soc_write(codec, WM8753_PCM, voice);  	return 0;  }  /*   * Set's PCM dai fmt and BCLK.   */ -static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec *codec,  		unsigned int fmt)  { -	struct snd_soc_codec *codec = codec_dai->codec;  	u16 voice, ioctl; -	voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f; -	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d; +	voice = snd_soc_read(codec, WM8753_PCM) & 0x011f; +	ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d;  	/* set master/slave audio interface */  	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1013,8 +1023,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	wm8753_write(codec, WM8753_PCM, voice); -	wm8753_write(codec, WM8753_IOCTL, ioctl); +	snd_soc_write(codec, WM8753_PCM, voice); +	snd_soc_write(codec, WM8753_IOCTL, ioctl);  	return 0;  } @@ -1026,16 +1036,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,  	switch (div_id) {  	case WM8753_PCMDIV: -		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f; -		wm8753_write(codec, WM8753_CLOCK, reg | div); +		reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f; +		snd_soc_write(codec, WM8753_CLOCK, reg | div);  		break;  	case WM8753_BCLKDIV: -		reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7; -		wm8753_write(codec, WM8753_SRATE2, reg | div); +		reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7; +		snd_soc_write(codec, WM8753_SRATE2, reg | div);  		break;  	case WM8753_VXCLKDIV: -		reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f; -		wm8753_write(codec, WM8753_SRATE2, reg | div); +		reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f; +		snd_soc_write(codec, WM8753_SRATE2, reg | div);  		break;  	default:  		return -EINVAL; @@ -1046,11 +1056,10 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,  /*   * Set's HiFi DAC format.   */ -static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec *codec,  		unsigned int fmt)  { -	struct snd_soc_codec *codec = codec_dai->codec; -	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0; +	u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0;  	/* interface format */  	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -1072,21 +1081,20 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	wm8753_write(codec, WM8753_HIFI, hifi); +	snd_soc_write(codec, WM8753_HIFI, hifi);  	return 0;  }  /*   * Set's I2S DAI format.   */ -static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec *codec,  		unsigned int fmt)  { -	struct snd_soc_codec *codec = codec_dai->codec;  	u16 ioctl, hifi; -	hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f; -	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae; +	hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f; +	ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae;  	/* set master/slave audio interface */  	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1140,15 +1148,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,  		return -EINVAL;  	} -	wm8753_write(codec, WM8753_HIFI, hifi); -	wm8753_write(codec, WM8753_IOCTL, ioctl); -	return 0; -} - -static int wm8753_i2s_startup(struct snd_pcm_substream *substream, -				struct snd_soc_dai *dai) -{ -	wm8753_set_dai_mode(dai->codec, dai, 1); +	snd_soc_write(codec, WM8753_HIFI, hifi); +	snd_soc_write(codec, WM8753_IOCTL, ioctl);  	return 0;  } @@ -1159,11 +1160,10 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,  				struct snd_pcm_hw_params *params,  				struct snd_soc_dai *dai)  { -	struct snd_soc_pcm_runtime *rtd = substream->private_data; -	struct snd_soc_codec *codec = rtd->codec; +	struct snd_soc_codec *codec = dai->codec;  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); -	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; -	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; +	u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0; +	u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3;  	int coeff;  	/* is digital filter coefficient valid ? */ @@ -1172,7 +1172,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,  		printk(KERN_ERR "wm8753 invalid MCLK or rate\n");  		return coeff;  	} -	wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | +	snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |  		coeff_div[coeff].usb);  	/* bit size */ @@ -1190,81 +1190,137 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,  		break;  	} -	wm8753_write(codec, WM8753_HIFI, hifi); +	snd_soc_write(codec, WM8753_HIFI, hifi);  	return 0;  } -static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec *codec,  		unsigned int fmt)  { -	struct snd_soc_codec *codec = codec_dai->codec;  	u16 clock;  	/* set clk source as pcmclk */ -	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; -	wm8753_write(codec, WM8753_CLOCK, clock); +	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; +	snd_soc_write(codec, WM8753_CLOCK, clock); -	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) -		return -EINVAL; -	return wm8753_pcm_set_dai_fmt(codec_dai, fmt); +	return wm8753_vdac_adc_set_dai_fmt(codec, fmt);  } -static int wm8753_mode1h_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec *codec,  		unsigned int fmt)  { -	if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) -		return -EINVAL; -	return wm8753_i2s_set_dai_fmt(codec_dai, fmt); +	return wm8753_hdac_set_dai_fmt(codec, fmt);  } -static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec *codec,  		unsigned int fmt)  { -	struct snd_soc_codec *codec = codec_dai->codec;  	u16 clock;  	/* set clk source as pcmclk */ -	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; -	wm8753_write(codec, WM8753_CLOCK, clock); +	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; +	snd_soc_write(codec, WM8753_CLOCK, clock); -	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) -		return -EINVAL; -	return wm8753_i2s_set_dai_fmt(codec_dai, fmt); +	return wm8753_vdac_adc_set_dai_fmt(codec, fmt);  } -static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, +static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec *codec,  		unsigned int fmt)  { -	struct snd_soc_codec *codec = codec_dai->codec;  	u16 clock;  	/* set clk source as mclk */ -	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; -	wm8753_write(codec, WM8753_CLOCK, clock | 0x4); +	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; +	snd_soc_write(codec, WM8753_CLOCK, clock | 0x4); -	if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) +	if (wm8753_hdac_set_dai_fmt(codec, fmt) < 0)  		return -EINVAL; -	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) -		return -EINVAL; -	return wm8753_i2s_set_dai_fmt(codec_dai, fmt); +	return wm8753_vdac_adc_set_dai_fmt(codec, fmt);  } +static int wm8753_hifi_write_dai_fmt(struct snd_soc_codec *codec, +		unsigned int fmt) +{ +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); +	int ret = 0; + +	switch (wm8753->dai_func) { +	case 0: +		ret = wm8753_mode1h_set_dai_fmt(codec, fmt); +		break; +	case 1: +		ret = wm8753_mode2_set_dai_fmt(codec, fmt); +		break; +	case 2: +	case 3: +		ret = wm8753_mode3_4_set_dai_fmt(codec, fmt); +		break; +	default: +		 break; +	} +	if (ret) +		return ret; + +	return wm8753_i2s_set_dai_fmt(codec, fmt); +} + +static int wm8753_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai, +		unsigned int fmt) +{ +	struct snd_soc_codec *codec = codec_dai->codec; +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); + +	wm8753->hifi_fmt = fmt; + +	return wm8753_hifi_write_dai_fmt(codec, fmt); +}; + +static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec, +		unsigned int fmt) +{ +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); +	int ret = 0; + +	if (wm8753->dai_func != 0) +		return 0; + +	ret = wm8753_mode1v_set_dai_fmt(codec, fmt); +	if (ret) +		return ret; +	ret = wm8753_pcm_set_dai_fmt(codec, fmt); +	if (ret) +		return ret; + +	return 0; +}; + +static int wm8753_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, +		unsigned int fmt) +{ +	struct snd_soc_codec *codec = codec_dai->codec; +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); + +	wm8753->voice_fmt = fmt; + +	return wm8753_voice_write_dai_fmt(codec, fmt); +}; +  static int wm8753_mute(struct snd_soc_dai *dai, int mute)  {  	struct snd_soc_codec *codec = dai->codec; -	u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; +	u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7;  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);  	/* the digital mute covers the HiFi and Voice DAC's on the WM8753.  	 * make sure we check if they are not both active when we mute */  	if (mute && wm8753->dai_func == 1) { -		if (!codec->active) -			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); +		if (!snd_soc_codec_is_active(codec)) +			snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);  	} else {  		if (mute) -			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); +			snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);  		else -			wm8753_write(codec, WM8753_DAC, mute_reg); +			snd_soc_write(codec, WM8753_DAC, mute_reg);  	}  	return 0; @@ -1273,26 +1329,26 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)  static int wm8753_set_bias_level(struct snd_soc_codec *codec,  				 enum snd_soc_bias_level level)  { -	u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; +	u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;  	switch (level) {  	case SND_SOC_BIAS_ON:  		/* set vmid to 50k and unmute dac */ -		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); +		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);  		break;  	case SND_SOC_BIAS_PREPARE:  		/* set vmid to 5k for quick power up */ -		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); +		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);  		break;  	case SND_SOC_BIAS_STANDBY:  		/* mute dac and set vmid to 500k, enable VREF */ -		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); +		snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);  		break;  	case SND_SOC_BIAS_OFF: -		wm8753_write(codec, WM8753_PWR1, 0x0001); +		snd_soc_write(codec, WM8753_PWR1, 0x0001);  		break;  	} -	codec->bias_level = level; +	codec->dapm.bias_level = level;  	return 0;  } @@ -1305,7 +1361,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,  	SNDRV_PCM_FMTBIT_S24_LE)  /* - * The WM8753 supports upto 4 different and mutually exclusive DAI + * The WM8753 supports up to 4 different and mutually exclusive DAI   * configurations. This gives 2 PCM's available for use, hifi and voice.   * NOTE: The Voice PCM cannot play or capture audio to the CPU as it's DAI   * is connected between the wm8753 and a BT codec or GSM modem. @@ -1315,57 +1371,25 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,   * 3. Voice disabled - HIFI over HIFI   * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture   */ -static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { -	.startup = wm8753_i2s_startup, +static const struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {  	.hw_params	= wm8753_i2s_hw_params,  	.digital_mute	= wm8753_mute, -	.set_fmt	= wm8753_mode1h_set_dai_fmt, +	.set_fmt	= wm8753_hifi_set_dai_fmt,  	.set_clkdiv	= wm8753_set_dai_clkdiv,  	.set_pll	= wm8753_set_dai_pll,  	.set_sysclk	= wm8753_set_dai_sysclk,  }; -static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { -	.startup = wm8753_pcm_startup, +static const struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = {  	.hw_params	= wm8753_pcm_hw_params,  	.digital_mute	= wm8753_mute, -	.set_fmt	= wm8753_mode1v_set_dai_fmt, +	.set_fmt	= wm8753_voice_set_dai_fmt,  	.set_clkdiv	= wm8753_set_dai_clkdiv,  	.set_pll	= wm8753_set_dai_pll,  	.set_sysclk	= wm8753_set_dai_sysclk,  }; -static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { -	.startup = wm8753_pcm_startup, -	.hw_params	= wm8753_pcm_hw_params, -	.digital_mute	= wm8753_mute, -	.set_fmt	= wm8753_mode2_set_dai_fmt, -	.set_clkdiv	= wm8753_set_dai_clkdiv, -	.set_pll	= wm8753_set_dai_pll, -	.set_sysclk	= wm8753_set_dai_sysclk, -}; - -static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3	= { -	.startup = wm8753_i2s_startup, -	.hw_params	= wm8753_i2s_hw_params, -	.digital_mute	= wm8753_mute, -	.set_fmt	= wm8753_mode3_4_set_dai_fmt, -	.set_clkdiv	= wm8753_set_dai_clkdiv, -	.set_pll	= wm8753_set_dai_pll, -	.set_sysclk	= wm8753_set_dai_sysclk, -}; - -static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4	= { -	.startup = wm8753_i2s_startup, -	.hw_params	= wm8753_i2s_hw_params, -	.digital_mute	= wm8753_mute, -	.set_fmt	= wm8753_mode3_4_set_dai_fmt, -	.set_clkdiv	= wm8753_set_dai_clkdiv, -	.set_pll	= wm8753_set_dai_pll, -	.set_sysclk	= wm8753_set_dai_sysclk, -}; - -static struct snd_soc_dai_driver wm8753_all_dai[] = { +static struct snd_soc_dai_driver wm8753_dai[] = {  /* DAI HiFi mode 1 */  {	.name = "wm8753-hifi",  	.playback = { @@ -1373,14 +1397,16 @@ static struct snd_soc_dai_driver wm8753_all_dai[] = {  		.channels_min = 1,  		.channels_max = 2,  		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS}, +		.formats = WM8753_FORMATS +	},  	.capture = { /* dummy for fast DAI switching */  		.stream_name = "Capture",  		.channels_min = 1,  		.channels_max = 2,  		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS}, -	.ops = &wm8753_dai_ops_hifi_mode1, +		.formats = WM8753_FORMATS +	}, +	.ops = &wm8753_dai_ops_hifi_mode,  },  /* DAI Voice mode 1 */  {	.name = "wm8753-voice", @@ -1389,105 +1415,29 @@ static struct snd_soc_dai_driver wm8753_all_dai[] = {  		.channels_min = 1,  		.channels_max = 1,  		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS,}, -	.capture = { -		.stream_name = "Capture", -		.channels_min = 1, -		.channels_max = 2, -		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS,}, -	.ops = &wm8753_dai_ops_voice_mode1, -}, -/* DAI HiFi mode 2 - dummy */ -{	.name = "wm8753-hifi", -}, -/* DAI Voice mode 2 */ -{	.name = "wm8753-voice", -	.playback = { -		.stream_name = "Voice Playback", -		.channels_min = 1, -		.channels_max = 1, -		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS,}, -	.capture = { -		.stream_name = "Capture", -		.channels_min = 1, -		.channels_max = 2, -		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS,}, -	.ops = &wm8753_dai_ops_voice_mode2, -}, -/* DAI HiFi mode 3 */ -{	.name = "wm8753-hifi", -	.playback = { -		.stream_name = "HiFi Playback", -		.channels_min = 1, -		.channels_max = 2, -		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS,}, -	.capture = { -		.stream_name = "Capture", -		.channels_min = 1, -		.channels_max = 2, -		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS,}, -	.ops = &wm8753_dai_ops_hifi_mode3, -}, -/* DAI Voice mode 3 - dummy */ -{	.name = "wm8753-voice", -}, -/* DAI HiFi mode 4 */ -{	.name = "wm8753-hifi", -	.playback = { -		.stream_name = "HiFi Playback", -		.channels_min = 1, -		.channels_max = 2, -		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS,}, +		.formats = WM8753_FORMATS, +	},  	.capture = {  		.stream_name = "Capture",  		.channels_min = 1,  		.channels_max = 2,  		.rates = WM8753_RATES, -		.formats = WM8753_FORMATS,}, -	.ops = &wm8753_dai_ops_hifi_mode4, -}, -/* DAI Voice mode 4 - dummy */ -{	.name = "wm8753-voice", -}, -}; - -static struct snd_soc_dai_driver wm8753_dai[] = { -	{ -		.name = "wm8753-aif0", -	}, -	{ -		.name = "wm8753-aif1", +		.formats = WM8753_FORMATS,  	}, +	.ops = &wm8753_dai_ops_voice_mode, +},  }; -static void wm8753_set_dai_mode(struct snd_soc_codec *codec, -		struct snd_soc_dai *dai, unsigned int hifi) -{ -	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - -	if (wm8753->dai_func < 4) { -		if (hifi) -			dai->driver = &wm8753_all_dai[wm8753->dai_func << 1]; -		else -			dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; -	} -	wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); -} -  static void wm8753_work(struct work_struct *work)  { -	struct snd_soc_codec *codec = -		container_of(work, struct snd_soc_codec, delayed_work.work); -	wm8753_set_bias_level(codec, codec->bias_level); +	struct snd_soc_dapm_context *dapm = +		container_of(work, struct snd_soc_dapm_context, +			     delayed_work.work); +	struct snd_soc_codec *codec = dapm->codec; +	wm8753_set_bias_level(codec, dapm->bias_level);  } -static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) +static int wm8753_suspend(struct snd_soc_codec *codec)  {  	wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0; @@ -1495,68 +1445,30 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)  static int wm8753_resume(struct snd_soc_codec *codec)  { -	int i; -	u8 data[2]; -	u16 *cache = codec->reg_cache; - -	/* Sync reg_cache with the hardware */ -	for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { -		if (i + 1 == WM8753_RESET) -			continue; - -		/* No point in writing hardware default values back */ -		if (cache[i] == wm8753_reg[i]) -			continue; +	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); -		data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); -		data[1] = cache[i] & 0x00ff; -		codec->hw_write(codec->control_data, data, 2); -	} +	regcache_sync(wm8753->regmap);  	wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	/* charge wm8753 caps */ -	if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { +	if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {  		wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); -		codec->bias_level = SND_SOC_BIAS_ON; -		schedule_delayed_work(&codec->delayed_work, -			msecs_to_jiffies(caps_charge)); +		codec->dapm.bias_level = SND_SOC_BIAS_ON; +		queue_delayed_work(system_power_efficient_wq, +				   &codec->dapm.delayed_work, +				   msecs_to_jiffies(caps_charge));  	}  	return 0;  } -/* - * This function forces any delayed work to be queued and run. - */ -static int run_delayed_work(struct delayed_work *dwork) -{ -	int ret; - -	/* cancel any work waiting to be queued. */ -	ret = cancel_delayed_work(dwork); - -	/* if there was any work waiting then we run it now and -	 * wait for it's completion */ -	if (ret) { -		schedule_delayed_work(dwork, 0); -		flush_scheduled_work(); -	} -	return ret; -} -  static int wm8753_probe(struct snd_soc_codec *codec)  {  	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); -	int ret = 0, reg; - -	INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); +	int ret; -	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type); -	if (ret < 0) { -		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); -		return ret; -	} +	INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);  	ret = wm8753_reset(codec);  	if (ret < 0) { @@ -1569,34 +1481,20 @@ static int wm8753_probe(struct snd_soc_codec *codec)  	/* charge output caps */  	wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); -	schedule_delayed_work(&codec->delayed_work, +	schedule_delayed_work(&codec->dapm.delayed_work,  			      msecs_to_jiffies(caps_charge));  	/* set the update bits */ -	reg = wm8753_read_reg_cache(codec, WM8753_LDAC); -	wm8753_write(codec, WM8753_LDAC, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_RDAC); -	wm8753_write(codec, WM8753_RDAC, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_LADC); -	wm8753_write(codec, WM8753_LADC, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_RADC); -	wm8753_write(codec, WM8753_RADC, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V); -	wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V); -	wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V); -	wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V); -	wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_LINVOL); -	wm8753_write(codec, WM8753_LINVOL, reg | 0x0100); -	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); -	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); - -	snd_soc_add_controls(codec, wm8753_snd_controls, -			     ARRAY_SIZE(wm8753_snd_controls)); -	wm8753_add_widgets(codec); +	snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_LADC, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_RADC, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100); +	snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);  	return 0;  } @@ -1604,7 +1502,7 @@ static int wm8753_probe(struct snd_soc_codec *codec)  /* power down chip */  static int wm8753_remove(struct snd_soc_codec *codec)  { -	run_delayed_work(&codec->delayed_work); +	flush_delayed_work(&codec->dapm.delayed_work);  	wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);  	return 0; @@ -1616,73 +1514,113 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {  	.suspend =	wm8753_suspend,  	.resume =	wm8753_resume,  	.set_bias_level = wm8753_set_bias_level, -	.reg_cache_size = ARRAY_SIZE(wm8753_reg), -	.reg_word_size = sizeof(u16), -	.reg_cache_default = wm8753_reg, + +	.controls = wm8753_snd_controls, +	.num_controls = ARRAY_SIZE(wm8753_snd_controls), +	.dapm_widgets = wm8753_dapm_widgets, +	.num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets), +	.dapm_routes = wm8753_dapm_routes, +	.num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes), +}; + +static const struct of_device_id wm8753_of_match[] = { +	{ .compatible = "wlf,wm8753", }, +	{ } +}; +MODULE_DEVICE_TABLE(of, wm8753_of_match); + +static const struct regmap_config wm8753_regmap = { +	.reg_bits = 7, +	.val_bits = 9, + +	.max_register = WM8753_ADCTL2, +	.writeable_reg = wm8753_writeable, +	.volatile_reg = wm8753_volatile, + +	.cache_type = REGCACHE_RBTREE, +	.reg_defaults = wm8753_reg_defaults, +	.num_reg_defaults = ARRAY_SIZE(wm8753_reg_defaults),  };  #if defined(CONFIG_SPI_MASTER) -static int __devinit wm8753_spi_probe(struct spi_device *spi) +static int wm8753_spi_probe(struct spi_device *spi)  {  	struct wm8753_priv *wm8753;  	int ret; -	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); +	wm8753 = devm_kzalloc(&spi->dev, sizeof(struct wm8753_priv), +			      GFP_KERNEL);  	if (wm8753 == NULL)  		return -ENOMEM; -	wm8753->control_type = SND_SOC_SPI;  	spi_set_drvdata(spi, wm8753); -	ret = snd_soc_register_codec(&spi->dev, -			&soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); -	if (ret < 0) -		kfree(wm8753); +	wm8753->regmap = devm_regmap_init_spi(spi, &wm8753_regmap); +	if (IS_ERR(wm8753->regmap)) { +		ret = PTR_ERR(wm8753->regmap); +		dev_err(&spi->dev, "Failed to allocate register map: %d\n", +			ret); +		return ret; +	} + +	ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753, +				     wm8753_dai, ARRAY_SIZE(wm8753_dai)); +	if (ret != 0) +		dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret); +  	return ret;  } -static int __devexit wm8753_spi_remove(struct spi_device *spi) +static int wm8753_spi_remove(struct spi_device *spi)  {  	snd_soc_unregister_codec(&spi->dev); -	kfree(spi_get_drvdata(spi));  	return 0;  }  static struct spi_driver wm8753_spi_driver = {  	.driver = { -		.name	= "wm8753-codec", +		.name	= "wm8753",  		.owner	= THIS_MODULE, +		.of_match_table = wm8753_of_match,  	},  	.probe		= wm8753_spi_probe, -	.remove		= __devexit_p(wm8753_spi_remove), +	.remove		= wm8753_spi_remove,  };  #endif /* CONFIG_SPI_MASTER */ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8753_i2c_probe(struct i2c_client *i2c, -				      const struct i2c_device_id *id) +#if IS_ENABLED(CONFIG_I2C) +static int wm8753_i2c_probe(struct i2c_client *i2c, +			    const struct i2c_device_id *id)  {  	struct wm8753_priv *wm8753;  	int ret; -	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); +	wm8753 = devm_kzalloc(&i2c->dev, sizeof(struct wm8753_priv), +			      GFP_KERNEL);  	if (wm8753 == NULL)  		return -ENOMEM;  	i2c_set_clientdata(i2c, wm8753); -	wm8753->control_type = SND_SOC_I2C; -	ret =  snd_soc_register_codec(&i2c->dev, -			&soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); -	if (ret < 0) -		kfree(wm8753); +	wm8753->regmap = devm_regmap_init_i2c(i2c, &wm8753_regmap); +	if (IS_ERR(wm8753->regmap)) { +		ret = PTR_ERR(wm8753->regmap); +		dev_err(&i2c->dev, "Failed to allocate register map: %d\n", +			ret); +		return ret; +	} + +	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753, +				     wm8753_dai, ARRAY_SIZE(wm8753_dai)); +	if (ret != 0) +		dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); +  	return ret;  } -static __devexit int wm8753_i2c_remove(struct i2c_client *client) +static int wm8753_i2c_remove(struct i2c_client *client)  {  	snd_soc_unregister_codec(&client->dev); -	kfree(i2c_get_clientdata(client));  	return 0;  } @@ -1694,11 +1632,12 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);  static struct i2c_driver wm8753_i2c_driver = {  	.driver = { -		.name = "wm8753-codec", +		.name = "wm8753",  		.owner = THIS_MODULE, +		.of_match_table = wm8753_of_match,  	},  	.probe =    wm8753_i2c_probe, -	.remove =   __devexit_p(wm8753_i2c_remove), +	.remove =   wm8753_i2c_remove,  	.id_table = wm8753_i2c_id,  };  #endif @@ -1706,7 +1645,7 @@ static struct i2c_driver wm8753_i2c_driver = {  static int __init wm8753_modinit(void)  {  	int ret = 0; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C)  	ret = i2c_add_driver(&wm8753_i2c_driver);  	if (ret != 0) {  		printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n", @@ -1726,7 +1665,7 @@ module_init(wm8753_modinit);  static void __exit wm8753_exit(void)  { -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +#if IS_ENABLED(CONFIG_I2C)  	i2c_del_driver(&wm8753_i2c_driver);  #endif  #if defined(CONFIG_SPI_MASTER)  | 
