aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8776.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8776.c')
-rw-r--r--sound/soc/codecs/wm8776.c67
1 files changed, 32 insertions, 35 deletions
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index 8e7953b1b790..bfdc52370ad0 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -18,6 +18,7 @@
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/of_device.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/spi/spi.h> 23#include <linux/spi/spi.h>
23#include <linux/slab.h> 24#include <linux/slab.h>
@@ -215,8 +216,6 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
215 int ratio_shift, master; 216 int ratio_shift, master;
216 int i; 217 int i;
217 218
218 iface = 0;
219
220 switch (dai->driver->id) { 219 switch (dai->driver->id) {
221 case WM8776_DAI_DAC: 220 case WM8776_DAI_DAC:
222 iface_reg = WM8776_DACIFCTRL; 221 iface_reg = WM8776_DACIFCTRL;
@@ -232,20 +231,23 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
232 return -EINVAL; 231 return -EINVAL;
233 } 232 }
234 233
235
236 /* Set word length */ 234 /* Set word length */
237 switch (params_format(params)) { 235 switch (snd_pcm_format_width(params_format(params))) {
238 case SNDRV_PCM_FORMAT_S16_LE: 236 case 16:
239 break; 237 iface = 0;
240 case SNDRV_PCM_FORMAT_S20_3LE: 238 case 20:
241 iface |= 0x10; 239 iface = 0x10;
242 break; 240 break;
243 case SNDRV_PCM_FORMAT_S24_LE: 241 case 24:
244 iface |= 0x20; 242 iface = 0x20;
245 break; 243 break;
246 case SNDRV_PCM_FORMAT_S32_LE: 244 case 32:
247 iface |= 0x30; 245 iface = 0x30;
248 break; 246 break;
247 default:
248 dev_err(codec->dev, "Unsupported sample size: %i\n",
249 snd_pcm_format_width(params_format(params)));
250 return -EINVAL;
249 } 251 }
250 252
251 /* Only need to set MCLK/LRCLK ratio if we're master */ 253 /* Only need to set MCLK/LRCLK ratio if we're master */
@@ -306,6 +308,8 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
306 break; 308 break;
307 case SND_SOC_BIAS_STANDBY: 309 case SND_SOC_BIAS_STANDBY:
308 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 310 if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
311 snd_soc_cache_sync(codec);
312
309 /* Disable the global powerdown; DAPM does the rest */ 313 /* Disable the global powerdown; DAPM does the rest */
310 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); 314 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
311 } 315 }
@@ -320,11 +324,6 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
320 return 0; 324 return 0;
321} 325}
322 326
323#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
324 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
325 SNDRV_PCM_RATE_96000)
326
327
328#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 327#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
329 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 328 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
330 329
@@ -349,7 +348,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = {
349 .stream_name = "Playback", 348 .stream_name = "Playback",
350 .channels_min = 2, 349 .channels_min = 2,
351 .channels_max = 2, 350 .channels_max = 2,
352 .rates = WM8776_RATES, 351 .rates = SNDRV_PCM_RATE_CONTINUOUS,
352 .rate_min = 32000,
353 .rate_max = 192000,
353 .formats = WM8776_FORMATS, 354 .formats = WM8776_FORMATS,
354 }, 355 },
355 .ops = &wm8776_dac_ops, 356 .ops = &wm8776_dac_ops,
@@ -361,7 +362,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = {
361 .stream_name = "Capture", 362 .stream_name = "Capture",
362 .channels_min = 2, 363 .channels_min = 2,
363 .channels_max = 2, 364 .channels_max = 2,
364 .rates = WM8776_RATES, 365 .rates = SNDRV_PCM_RATE_CONTINUOUS,
366 .rate_min = 32000,
367 .rate_max = 96000,
365 .formats = WM8776_FORMATS, 368 .formats = WM8776_FORMATS,
366 }, 369 },
367 .ops = &wm8776_adc_ops, 370 .ops = &wm8776_adc_ops,
@@ -378,21 +381,7 @@ static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
378 381
379static int wm8776_resume(struct snd_soc_codec *codec) 382static int wm8776_resume(struct snd_soc_codec *codec)
380{ 383{
381 int i;
382 u8 data[2];
383 u16 *cache = codec->reg_cache;
384
385 /* Sync reg_cache with the hardware */
386 for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
387 if (cache[i] == wm8776_reg[i])
388 continue;
389 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
390 data[1] = cache[i] & 0x00ff;
391 codec->hw_write(codec->control_data, data, 2);
392 }
393
394 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 384 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
395
396 return 0; 385 return 0;
397} 386}
398#else 387#else
@@ -452,6 +441,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = {
452 .reg_cache_default = wm8776_reg, 441 .reg_cache_default = wm8776_reg,
453}; 442};
454 443
444static const struct of_device_id wm8776_of_match[] = {
445 { .compatible = "wlf,wm8776", },
446 { }
447};
448MODULE_DEVICE_TABLE(of, wm8776_of_match);
449
455#if defined(CONFIG_SPI_MASTER) 450#if defined(CONFIG_SPI_MASTER)
456static int __devinit wm8776_spi_probe(struct spi_device *spi) 451static int __devinit wm8776_spi_probe(struct spi_device *spi)
457{ 452{
@@ -481,8 +476,9 @@ static int __devexit wm8776_spi_remove(struct spi_device *spi)
481 476
482static struct spi_driver wm8776_spi_driver = { 477static struct spi_driver wm8776_spi_driver = {
483 .driver = { 478 .driver = {
484 .name = "wm8776-codec", 479 .name = "wm8776",
485 .owner = THIS_MODULE, 480 .owner = THIS_MODULE,
481 .of_match_table = wm8776_of_match,
486 }, 482 },
487 .probe = wm8776_spi_probe, 483 .probe = wm8776_spi_probe,
488 .remove = __devexit_p(wm8776_spi_remove), 484 .remove = __devexit_p(wm8776_spi_remove),
@@ -525,8 +521,9 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
525 521
526static struct i2c_driver wm8776_i2c_driver = { 522static struct i2c_driver wm8776_i2c_driver = {
527 .driver = { 523 .driver = {
528 .name = "wm8776-codec", 524 .name = "wm8776",
529 .owner = THIS_MODULE, 525 .owner = THIS_MODULE,
526 .of_match_table = wm8776_of_match,
530 }, 527 },
531 .probe = wm8776_i2c_probe, 528 .probe = wm8776_i2c_probe,
532 .remove = __devexit_p(wm8776_i2c_remove), 529 .remove = __devexit_p(wm8776_i2c_remove),