diff options
Diffstat (limited to 'sound/soc/codecs/wm8776.c')
-rw-r--r-- | sound/soc/codecs/wm8776.c | 67 |
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 | ||
379 | static int wm8776_resume(struct snd_soc_codec *codec) | 382 | static 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 | ||
444 | static const struct of_device_id wm8776_of_match[] = { | ||
445 | { .compatible = "wlf,wm8776", }, | ||
446 | { } | ||
447 | }; | ||
448 | MODULE_DEVICE_TABLE(of, wm8776_of_match); | ||
449 | |||
455 | #if defined(CONFIG_SPI_MASTER) | 450 | #if defined(CONFIG_SPI_MASTER) |
456 | static int __devinit wm8776_spi_probe(struct spi_device *spi) | 451 | static 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 | ||
482 | static struct spi_driver wm8776_spi_driver = { | 477 | static 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 | ||
526 | static struct i2c_driver wm8776_i2c_driver = { | 522 | static 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), |