X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=sound%2Fsoc%2Fcodecs%2Fwm8974.c;fp=sound%2Fsoc%2Fcodecs%2Fwm8974.c;h=eff29331235bb3b210f8249c76866e758690e962;hp=f30f86b3bda05a8276ed21de4771c7b9684c26be;hb=4c0bccbe66ffe34f7bc88d29c345f9a7888656eb;hpb=c36b2fc73a6c0e7b185b17d594b38398ce1f7fff;ds=sidebyside diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index f30f86b3bda0..eff29331235b 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -57,55 +56,7 @@ struct wm8974_priv { static struct snd_soc_codec *wm8974_codec; -/* - * read wm8974 register cache - */ -static inline unsigned int wm8974_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg == WM8974_RESET) - return 0; - if (reg >= WM8974_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write wm8974 register cache - */ -static inline void wm8974_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg >= WM8974_CACHEREGNUM) - return; - cache[reg] = value; -} - -/* - * write to the WM8974 register space - */ -static int wm8974_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8974 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8974_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8974_reset(c) wm8974_write(c, WM8974_RESET, 0) +#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; static const char *wm8974_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" }; @@ -379,8 +330,8 @@ static void pll_factors(struct pll_ *pll_div, pll_div->k = K; } -static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, - int pll_id, unsigned int freq_in, unsigned int freq_out) +static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) { struct snd_soc_codec *codec = codec_dai->codec; struct pll_ pll_div; @@ -388,27 +339,27 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = wm8974_read_reg_cache(codec, WM8974_CLOCK); - wm8974_write(codec, WM8974_CLOCK, reg & 0x0ff); + reg = snd_soc_read(codec, WM8974_CLOCK); + snd_soc_write(codec, WM8974_CLOCK, reg & 0x0ff); /* Turn off PLL */ - reg = wm8974_read_reg_cache(codec, WM8974_POWER1); - wm8974_write(codec, WM8974_POWER1, reg & 0x1df); + reg = snd_soc_read(codec, WM8974_POWER1); + snd_soc_write(codec, WM8974_POWER1, reg & 0x1df); return 0; } pll_factors(&pll_div, freq_out, freq_in); - wm8974_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); - wm8974_write(codec, WM8974_PLLK1, pll_div.k >> 18); - wm8974_write(codec, WM8974_PLLK2, (pll_div.k >> 9) & 0x1ff); - wm8974_write(codec, WM8974_PLLK3, pll_div.k & 0x1ff); - reg = wm8974_read_reg_cache(codec, WM8974_POWER1); - wm8974_write(codec, WM8974_POWER1, reg | 0x020); + snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); + snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18); + snd_soc_write(codec, WM8974_PLLK2, (pll_div.k >> 9) & 0x1ff); + snd_soc_write(codec, WM8974_PLLK3, pll_div.k & 0x1ff); + reg = snd_soc_read(codec, WM8974_POWER1); + snd_soc_write(codec, WM8974_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = wm8974_read_reg_cache(codec, WM8974_CLOCK); - wm8974_write(codec, WM8974_CLOCK, reg | 0x100); + reg = snd_soc_read(codec, WM8974_CLOCK); + snd_soc_write(codec, WM8974_CLOCK, reg | 0x100); return 0; } @@ -424,24 +375,24 @@ static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8974_OPCLKDIV: - reg = wm8974_read_reg_cache(codec, WM8974_GPIO) & 0x1cf; - wm8974_write(codec, WM8974_GPIO, reg | div); + reg = snd_soc_read(codec, WM8974_GPIO) & 0x1cf; + snd_soc_write(codec, WM8974_GPIO, reg | div); break; case WM8974_MCLKDIV: - reg = wm8974_read_reg_cache(codec, WM8974_CLOCK) & 0x11f; - wm8974_write(codec, WM8974_CLOCK, reg | div); + reg = snd_soc_read(codec, WM8974_CLOCK) & 0x11f; + snd_soc_write(codec, WM8974_CLOCK, reg | div); break; case WM8974_ADCCLK: - reg = wm8974_read_reg_cache(codec, WM8974_ADC) & 0x1f7; - wm8974_write(codec, WM8974_ADC, reg | div); + reg = snd_soc_read(codec, WM8974_ADC) & 0x1f7; + snd_soc_write(codec, WM8974_ADC, reg | div); break; case WM8974_DACCLK: - reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0x1f7; - wm8974_write(codec, WM8974_DAC, reg | div); + reg = snd_soc_read(codec, WM8974_DAC) & 0x1f7; + snd_soc_write(codec, WM8974_DAC, reg | div); break; case WM8974_BCLKDIV: - reg = wm8974_read_reg_cache(codec, WM8974_CLOCK) & 0x1e3; - wm8974_write(codec, WM8974_CLOCK, reg | div); + reg = snd_soc_read(codec, WM8974_CLOCK) & 0x1e3; + snd_soc_write(codec, WM8974_CLOCK, reg | div); break; default: return -EINVAL; @@ -455,7 +406,7 @@ static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; u16 iface = 0; - u16 clk = wm8974_read_reg_cache(codec, WM8974_CLOCK) & 0x1fe; + u16 clk = snd_soc_read(codec, WM8974_CLOCK) & 0x1fe; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -502,8 +453,8 @@ static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8974_write(codec, WM8974_IFACE, iface); - wm8974_write(codec, WM8974_CLOCK, clk); + snd_soc_write(codec, WM8974_IFACE, iface); + snd_soc_write(codec, WM8974_CLOCK, clk); return 0; } @@ -512,8 +463,8 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; - u16 iface = wm8974_read_reg_cache(codec, WM8974_IFACE) & 0x19f; - u16 adn = wm8974_read_reg_cache(codec, WM8974_ADD) & 0x1f1; + u16 iface = snd_soc_read(codec, WM8974_IFACE) & 0x19f; + u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1; /* bit size */ switch (params_format(params)) { @@ -552,20 +503,20 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, break; } - wm8974_write(codec, WM8974_IFACE, iface); - wm8974_write(codec, WM8974_ADD, adn); + snd_soc_write(codec, WM8974_IFACE, iface); + snd_soc_write(codec, WM8974_ADD, adn); return 0; } static int wm8974_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf; + u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf; if (mute) - wm8974_write(codec, WM8974_DAC, mute_reg | 0x40); + snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40); else - wm8974_write(codec, WM8974_DAC, mute_reg); + snd_soc_write(codec, WM8974_DAC, mute_reg); return 0; } @@ -573,13 +524,13 @@ static int wm8974_mute(struct snd_soc_dai *dai, int mute) static int wm8974_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 power1 = wm8974_read_reg_cache(codec, WM8974_POWER1) & ~0x3; + u16 power1 = snd_soc_read(codec, WM8974_POWER1) & ~0x3; switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: power1 |= 0x1; /* VMID 50k */ - wm8974_write(codec, WM8974_POWER1, power1); + snd_soc_write(codec, WM8974_POWER1, power1); break; case SND_SOC_BIAS_STANDBY: @@ -587,18 +538,18 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec, if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Initial cap charge at VMID 5k */ - wm8974_write(codec, WM8974_POWER1, power1 | 0x3); + snd_soc_write(codec, WM8974_POWER1, power1 | 0x3); mdelay(100); } power1 |= 0x2; /* VMID 500k */ - wm8974_write(codec, WM8974_POWER1, power1); + snd_soc_write(codec, WM8974_POWER1, power1); break; case SND_SOC_BIAS_OFF: - wm8974_write(codec, WM8974_POWER1, 0); - wm8974_write(codec, WM8974_POWER2, 0); - wm8974_write(codec, WM8974_POWER3, 0); + snd_soc_write(codec, WM8974_POWER1, 0); + snd_soc_write(codec, WM8974_POWER2, 0); + snd_soc_write(codec, WM8974_POWER3, 0); break; } @@ -741,8 +692,6 @@ static __devinit int wm8974_register(struct wm8974_priv *wm8974) codec->private_data = wm8974; codec->name = "WM8974"; codec->owner = THIS_MODULE; - codec->read = wm8974_read_reg_cache; - codec->write = wm8974_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8974_set_bias_level; codec->dai = &wm8974_dai; @@ -750,12 +699,18 @@ static __devinit int wm8974_register(struct wm8974_priv *wm8974) codec->reg_cache_size = WM8974_CACHEREGNUM; codec->reg_cache = &wm8974->reg_cache; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); + if (ret < 0) { + dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); + goto err; + } + memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg)); ret = wm8974_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - return ret; + goto err; } wm8974_dai.dev = codec->dev; @@ -767,17 +722,22 @@ static __devinit int wm8974_register(struct wm8974_priv *wm8974) ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - return ret; + goto err; } ret = snd_soc_register_dai(&wm8974_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - return ret; + goto err_codec; } return 0; + +err_codec: + snd_soc_unregister_codec(codec); +err: + kfree(wm8974); + return ret; } static __devexit void wm8974_unregister(struct wm8974_priv *wm8974)