1 /* 2 * wm8711.c -- WM8711 ALSA SoC Audio driver 3 * 4 * Copyright 2006 Wolfson Microelectronics 5 * 6 * Author: Mike Arthur <linux@wolfsonmicro.com> 7 * 8 * Based on wm8731.c by Richard Purdie 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15 #include <linux/module.h> 16 #include <linux/moduleparam.h> 17 #include <linux/init.h> 18 #include <linux/delay.h> 19 #include <linux/pm.h> 20 #include <linux/i2c.h> 21 #include <linux/platform_device.h> 22 #include <linux/spi/spi.h> 23 #include <linux/slab.h> 24 #include <sound/core.h> 25 #include <sound/pcm.h> 26 #include <sound/pcm_params.h> 27 #include <sound/soc.h> 28 #include <sound/soc-dapm.h> 29 #include <sound/tlv.h> 30 #include <sound/initval.h> 31 32 #include "wm8711.h" 33 34 /* codec private data */ 35 struct wm8711_priv { 36 enum snd_soc_control_type bus_type; 37 u16 reg_cache[WM8711_CACHEREGNUM]; 38 unsigned int sysclk; 39 }; 40 41 /* 42 * wm8711 register cache 43 * We can't read the WM8711 register space when we are 44 * using 2 wire for device control, so we cache them instead. 45 * There is no point in caching the reset register 46 */ 47 static const u16 wm8711_reg[WM8711_CACHEREGNUM] = { 48 0x0079, 0x0079, 0x000a, 0x0008, 49 0x009f, 0x000a, 0x0000, 0x0000 50 }; 51 52 #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) 53 54 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); 55 56 static const struct snd_kcontrol_new wm8711_snd_controls[] = { 57 58 SOC_DOUBLE_R_TLV("Master Playback Volume", WM8711_LOUT1V, WM8711_ROUT1V, 59 0, 127, 0, out_tlv), 60 SOC_DOUBLE_R("Master Playback ZC Switch", WM8711_LOUT1V, WM8711_ROUT1V, 61 7, 1, 0), 62 63 }; 64 65 /* Output Mixer */ 66 static const struct snd_kcontrol_new wm8711_output_mixer_controls[] = { 67 SOC_DAPM_SINGLE("Line Bypass Switch", WM8711_APANA, 3, 1, 0), 68 SOC_DAPM_SINGLE("HiFi Playback Switch", WM8711_APANA, 4, 1, 0), 69 }; 70 71 static const struct snd_soc_dapm_widget wm8711_dapm_widgets[] = { 72 SND_SOC_DAPM_MIXER("Output Mixer", WM8711_PWR, 4, 1, 73 &wm8711_output_mixer_controls[0], 74 ARRAY_SIZE(wm8711_output_mixer_controls)), 75 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8711_PWR, 3, 1), 76 SND_SOC_DAPM_OUTPUT("LOUT"), 77 SND_SOC_DAPM_OUTPUT("LHPOUT"), 78 SND_SOC_DAPM_OUTPUT("ROUT"), 79 SND_SOC_DAPM_OUTPUT("RHPOUT"), 80 }; 81 82 static const struct snd_soc_dapm_route intercon[] = { 83 /* output mixer */ 84 {"Output Mixer", "Line Bypass Switch", "Line Input"}, 85 {"Output Mixer", "HiFi Playback Switch", "DAC"}, 86 87 /* outputs */ 88 {"RHPOUT", NULL, "Output Mixer"}, 89 {"ROUT", NULL, "Output Mixer"}, 90 {"LHPOUT", NULL, "Output Mixer"}, 91 {"LOUT", NULL, "Output Mixer"}, 92 }; 93 94 static int wm8711_add_widgets(struct snd_soc_codec *codec) 95 { 96 snd_soc_dapm_new_controls(codec, wm8711_dapm_widgets, 97 ARRAY_SIZE(wm8711_dapm_widgets)); 98 99 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 100 101 return 0; 102 } 103 104 struct _coeff_div { 105 u32 mclk; 106 u32 rate; 107 u16 fs; 108 u8 sr:4; 109 u8 bosr:1; 110 u8 usb:1; 111 }; 112 113 /* codec mclk clock divider coefficients */ 114 static const struct _coeff_div coeff_div[] = { 115 /* 48k */ 116 {12288000, 48000, 256, 0x0, 0x0, 0x0}, 117 {18432000, 48000, 384, 0x0, 0x1, 0x0}, 118 {12000000, 48000, 250, 0x0, 0x0, 0x1}, 119 120 /* 32k */ 121 {12288000, 32000, 384, 0x6, 0x0, 0x0}, 122 {18432000, 32000, 576, 0x6, 0x1, 0x0}, 123 {12000000, 32000, 375, 0x6, 0x0, 0x1}, 124 125 /* 8k */ 126 {12288000, 8000, 1536, 0x3, 0x0, 0x0}, 127 {18432000, 8000, 2304, 0x3, 0x1, 0x0}, 128 {11289600, 8000, 1408, 0xb, 0x0, 0x0}, 129 {16934400, 8000, 2112, 0xb, 0x1, 0x0}, 130 {12000000, 8000, 1500, 0x3, 0x0, 0x1}, 131 132 /* 96k */ 133 {12288000, 96000, 128, 0x7, 0x0, 0x0}, 134 {18432000, 96000, 192, 0x7, 0x1, 0x0}, 135 {12000000, 96000, 125, 0x7, 0x0, 0x1}, 136 137 /* 44.1k */ 138 {11289600, 44100, 256, 0x8, 0x0, 0x0}, 139 {16934400, 44100, 384, 0x8, 0x1, 0x0}, 140 {12000000, 44100, 272, 0x8, 0x1, 0x1}, 141 142 /* 88.2k */ 143 {11289600, 88200, 128, 0xf, 0x0, 0x0}, 144 {16934400, 88200, 192, 0xf, 0x1, 0x0}, 145 {12000000, 88200, 136, 0xf, 0x1, 0x1}, 146 }; 147 148 static inline int get_coeff(int mclk, int rate) 149 { 150 int i; 151 152 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { 153 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) 154 return i; 155 } 156 return 0; 157 } 158 159 static int wm8711_hw_params(struct snd_pcm_substream *substream, 160 struct snd_pcm_hw_params *params, 161 struct snd_soc_dai *dai) 162 { 163 struct snd_soc_codec *codec = dai->codec; 164 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); 165 u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; 166 int i = get_coeff(wm8711->sysclk, params_rate(params)); 167 u16 srate = (coeff_div[i].sr << 2) | 168 (coeff_div[i].bosr << 1) | coeff_div[i].usb; 169 170 snd_soc_write(codec, WM8711_SRATE, srate); 171 172 /* bit size */ 173 switch (params_format(params)) { 174 case SNDRV_PCM_FORMAT_S16_LE: 175 break; 176 case SNDRV_PCM_FORMAT_S20_3LE: 177 iface |= 0x0004; 178 break; 179 case SNDRV_PCM_FORMAT_S24_LE: 180 iface |= 0x0008; 181 break; 182 } 183 184 snd_soc_write(codec, WM8711_IFACE, iface); 185 return 0; 186 } 187 188 static int wm8711_pcm_prepare(struct snd_pcm_substream *substream, 189 struct snd_soc_dai *dai) 190 { 191 struct snd_soc_codec *codec = dai->codec; 192 193 /* set active */ 194 snd_soc_write(codec, WM8711_ACTIVE, 0x0001); 195 196 return 0; 197 } 198 199 static void wm8711_shutdown(struct snd_pcm_substream *substream, 200 struct snd_soc_dai *dai) 201 { 202 struct snd_soc_codec *codec = dai->codec; 203 204 /* deactivate */ 205 if (!codec->active) { 206 udelay(50); 207 snd_soc_write(codec, WM8711_ACTIVE, 0x0); 208 } 209 } 210 211 static int wm8711_mute(struct snd_soc_dai *dai, int mute) 212 { 213 struct snd_soc_codec *codec = dai->codec; 214 u16 mute_reg = snd_soc_read(codec, WM8711_APDIGI) & 0xfff7; 215 216 if (mute) 217 snd_soc_write(codec, WM8711_APDIGI, mute_reg | 0x8); 218 else 219 snd_soc_write(codec, WM8711_APDIGI, mute_reg); 220 221 return 0; 222 } 223 224 static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai, 225 int clk_id, unsigned int freq, int dir) 226 { 227 struct snd_soc_codec *codec = codec_dai->codec; 228 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); 229 230 switch (freq) { 231 case 11289600: 232 case 12000000: 233 case 12288000: 234 case 16934400: 235 case 18432000: 236 wm8711->sysclk = freq; 237 return 0; 238 } 239 return -EINVAL; 240 } 241 242 static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, 243 unsigned int fmt) 244 { 245 struct snd_soc_codec *codec = codec_dai->codec; 246 u16 iface = 0; 247 248 /* set master/slave audio interface */ 249 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 250 case SND_SOC_DAIFMT_CBM_CFM: 251 iface |= 0x0040; 252 break; 253 case SND_SOC_DAIFMT_CBS_CFS: 254 break; 255 default: 256 return -EINVAL; 257 } 258 259 /* interface format */ 260 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 261 case SND_SOC_DAIFMT_I2S: 262 iface |= 0x0002; 263 break; 264 case SND_SOC_DAIFMT_RIGHT_J: 265 break; 266 case SND_SOC_DAIFMT_LEFT_J: 267 iface |= 0x0001; 268 break; 269 case SND_SOC_DAIFMT_DSP_A: 270 iface |= 0x0003; 271 break; 272 case SND_SOC_DAIFMT_DSP_B: 273 iface |= 0x0013; 274 break; 275 default: 276 return -EINVAL; 277 } 278 279 /* clock inversion */ 280 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 281 case SND_SOC_DAIFMT_NB_NF: 282 break; 283 case SND_SOC_DAIFMT_IB_IF: 284 iface |= 0x0090; 285 break; 286 case SND_SOC_DAIFMT_IB_NF: 287 iface |= 0x0080; 288 break; 289 case SND_SOC_DAIFMT_NB_IF: 290 iface |= 0x0010; 291 break; 292 default: 293 return -EINVAL; 294 } 295 296 /* set iface */ 297 snd_soc_write(codec, WM8711_IFACE, iface); 298 return 0; 299 } 300 301 302 static int wm8711_set_bias_level(struct snd_soc_codec *codec, 303 enum snd_soc_bias_level level) 304 { 305 u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; 306 307 switch (level) { 308 case SND_SOC_BIAS_ON: 309 snd_soc_write(codec, WM8711_PWR, reg); 310 break; 311 case SND_SOC_BIAS_PREPARE: 312 break; 313 case SND_SOC_BIAS_STANDBY: 314 snd_soc_write(codec, WM8711_PWR, reg | 0x0040); 315 break; 316 case SND_SOC_BIAS_OFF: 317 snd_soc_write(codec, WM8711_ACTIVE, 0x0); 318 snd_soc_write(codec, WM8711_PWR, 0xffff); 319 break; 320 } 321 codec->bias_level = level; 322 return 0; 323 } 324 325 #define WM8711_RATES SNDRV_PCM_RATE_8000_96000 326 327 #define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 328 SNDRV_PCM_FMTBIT_S24_LE) 329 330 static struct snd_soc_dai_ops wm8711_ops = { 331 .prepare = wm8711_pcm_prepare, 332 .hw_params = wm8711_hw_params, 333 .shutdown = wm8711_shutdown, 334 .digital_mute = wm8711_mute, 335 .set_sysclk = wm8711_set_dai_sysclk, 336 .set_fmt = wm8711_set_dai_fmt, 337 }; 338 339 static struct snd_soc_dai_driver wm8711_dai = { 340 .name = "wm8711-hifi", 341 .playback = { 342 .stream_name = "Playback", 343 .channels_min = 1, 344 .channels_max = 2, 345 .rates = WM8711_RATES, 346 .formats = WM8711_FORMATS, 347 }, 348 .ops = &wm8711_ops, 349 }; 350 351 static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state) 352 { 353 snd_soc_write(codec, WM8711_ACTIVE, 0x0); 354 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); 355 return 0; 356 } 357 358 static int wm8711_resume(struct snd_soc_codec *codec) 359 { 360 int i; 361 u8 data[2]; 362 u16 *cache = codec->reg_cache; 363 364 /* Sync reg_cache with the hardware */ 365 for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) { 366 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 367 data[1] = cache[i] & 0x00ff; 368 codec->hw_write(codec->control_data, data, 2); 369 } 370 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 371 372 return 0; 373 } 374 375 static int wm8711_probe(struct snd_soc_codec *codec) 376 { 377 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); 378 int ret, reg; 379 380 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); 381 if (ret < 0) { 382 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 383 return ret; 384 } 385 386 ret = wm8711_reset(codec); 387 if (ret < 0) { 388 dev_err(codec->dev, "Failed to issue reset\n"); 389 return ret; 390 } 391 392 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 393 394 /* Latch the update bits */ 395 reg = snd_soc_read(codec, WM8711_LOUT1V); 396 snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100); 397 reg = snd_soc_read(codec, WM8711_ROUT1V); 398 snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); 399 400 snd_soc_add_controls(codec, wm8711_snd_controls, 401 ARRAY_SIZE(wm8711_snd_controls)); 402 wm8711_add_widgets(codec); 403 404 return ret; 405 406 } 407 408 /* power down chip */ 409 static int wm8711_remove(struct snd_soc_codec *codec) 410 { 411 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); 412 return 0; 413 } 414 415 static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { 416 .probe = wm8711_probe, 417 .remove = wm8711_remove, 418 .suspend = wm8711_suspend, 419 .resume = wm8711_resume, 420 .set_bias_level = wm8711_set_bias_level, 421 .reg_cache_size = ARRAY_SIZE(wm8711_reg), 422 .reg_word_size = sizeof(u16), 423 .reg_cache_default = wm8711_reg, 424 }; 425 426 #if defined(CONFIG_SPI_MASTER) 427 static int __devinit wm8711_spi_probe(struct spi_device *spi) 428 { 429 struct wm8711_priv *wm8711; 430 int ret; 431 432 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); 433 if (wm8711 == NULL) 434 return -ENOMEM; 435 436 spi_set_drvdata(spi, wm8711); 437 wm8711->bus_type = SND_SOC_SPI; 438 439 ret = snd_soc_register_codec(&spi->dev, 440 &soc_codec_dev_wm8711, &wm8711_dai, 1); 441 if (ret < 0) 442 kfree(wm8711); 443 return ret; 444 } 445 446 static int __devexit wm8711_spi_remove(struct spi_device *spi) 447 { 448 snd_soc_unregister_codec(&spi->dev); 449 kfree(spi_get_drvdata(spi)); 450 return 0; 451 } 452 453 static struct spi_driver wm8711_spi_driver = { 454 .driver = { 455 .name = "wm8711-codec", 456 .owner = THIS_MODULE, 457 }, 458 .probe = wm8711_spi_probe, 459 .remove = __devexit_p(wm8711_spi_remove), 460 }; 461 #endif /* CONFIG_SPI_MASTER */ 462 463 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 464 static __devinit int wm8711_i2c_probe(struct i2c_client *client, 465 const struct i2c_device_id *id) 466 { 467 struct wm8711_priv *wm8711; 468 int ret; 469 470 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); 471 if (wm8711 == NULL) 472 return -ENOMEM; 473 474 i2c_set_clientdata(client, wm8711); 475 wm8711->bus_type = SND_SOC_I2C; 476 477 ret = snd_soc_register_codec(&client->dev, 478 &soc_codec_dev_wm8711, &wm8711_dai, 1); 479 if (ret < 0) 480 kfree(wm8711); 481 return ret; 482 } 483 484 static __devexit int wm8711_i2c_remove(struct i2c_client *client) 485 { 486 snd_soc_unregister_codec(&client->dev); 487 kfree(i2c_get_clientdata(client)); 488 return 0; 489 } 490 491 static const struct i2c_device_id wm8711_i2c_id[] = { 492 { "wm8711", 0 }, 493 { } 494 }; 495 MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); 496 497 static struct i2c_driver wm8711_i2c_driver = { 498 .driver = { 499 .name = "wm8711-codec", 500 .owner = THIS_MODULE, 501 }, 502 .probe = wm8711_i2c_probe, 503 .remove = __devexit_p(wm8711_i2c_remove), 504 .id_table = wm8711_i2c_id, 505 }; 506 #endif 507 508 static int __init wm8711_modinit(void) 509 { 510 int ret; 511 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 512 ret = i2c_add_driver(&wm8711_i2c_driver); 513 if (ret != 0) { 514 printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n", 515 ret); 516 } 517 #endif 518 #if defined(CONFIG_SPI_MASTER) 519 ret = spi_register_driver(&wm8711_spi_driver); 520 if (ret != 0) { 521 printk(KERN_ERR "Failed to register WM8711 SPI driver: %d\n", 522 ret); 523 } 524 #endif 525 return 0; 526 } 527 module_init(wm8711_modinit); 528 529 static void __exit wm8711_exit(void) 530 { 531 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 532 i2c_del_driver(&wm8711_i2c_driver); 533 #endif 534 #if defined(CONFIG_SPI_MASTER) 535 spi_unregister_driver(&wm8711_spi_driver); 536 #endif 537 } 538 module_exit(wm8711_exit); 539 540 MODULE_DESCRIPTION("ASoC WM8711 driver"); 541 MODULE_AUTHOR("Mike Arthur"); 542 MODULE_LICENSE("GPL"); 543