1b35a28afSMark Brown /* 2b35a28afSMark Brown * wm8955.c -- WM8955 ALSA SoC Audio driver 3b35a28afSMark Brown * 4b35a28afSMark Brown * Copyright 2009 Wolfson Microelectronics plc 5b35a28afSMark Brown * 6b35a28afSMark Brown * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7b35a28afSMark Brown * 8b35a28afSMark Brown * This program is free software; you can redistribute it and/or modify 9b35a28afSMark Brown * it under the terms of the GNU General Public License version 2 as 10b35a28afSMark Brown * published by the Free Software Foundation. 11b35a28afSMark Brown */ 12b35a28afSMark Brown 13b35a28afSMark Brown #include <linux/module.h> 14b35a28afSMark Brown #include <linux/moduleparam.h> 15b35a28afSMark Brown #include <linux/init.h> 16b35a28afSMark Brown #include <linux/delay.h> 17b35a28afSMark Brown #include <linux/pm.h> 18b35a28afSMark Brown #include <linux/i2c.h> 19*95860fdfSMark Brown #include <linux/regmap.h> 20b35a28afSMark Brown #include <linux/regulator/consumer.h> 215a0e3ad6STejun Heo #include <linux/slab.h> 22b35a28afSMark Brown #include <sound/core.h> 23b35a28afSMark Brown #include <sound/pcm.h> 24b35a28afSMark Brown #include <sound/pcm_params.h> 25b35a28afSMark Brown #include <sound/soc.h> 26b35a28afSMark Brown #include <sound/initval.h> 27b35a28afSMark Brown #include <sound/tlv.h> 28b35a28afSMark Brown #include <sound/wm8955.h> 29b35a28afSMark Brown 30b35a28afSMark Brown #include "wm8955.h" 31b35a28afSMark Brown 32b35a28afSMark Brown #define WM8955_NUM_SUPPLIES 4 33b35a28afSMark Brown static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { 34b35a28afSMark Brown "DCVDD", 35b35a28afSMark Brown "DBVDD", 36b35a28afSMark Brown "HPVDD", 37b35a28afSMark Brown "AVDD", 38b35a28afSMark Brown }; 39b35a28afSMark Brown 40b35a28afSMark Brown /* codec private data */ 41b35a28afSMark Brown struct wm8955_priv { 42*95860fdfSMark Brown struct regmap *regmap; 43f0fba2adSLiam Girdwood 44b35a28afSMark Brown unsigned int mclk_rate; 45b35a28afSMark Brown 46b35a28afSMark Brown int deemph; 47b35a28afSMark Brown int fs; 48b35a28afSMark Brown 49b35a28afSMark Brown struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; 50b35a28afSMark Brown }; 51b35a28afSMark Brown 52*95860fdfSMark Brown static const struct reg_default wm8955_reg_defaults[] = { 53*95860fdfSMark Brown { 2, 0x0079 }, /* R2 - LOUT1 volume */ 54*95860fdfSMark Brown { 3, 0x0079 }, /* R3 - ROUT1 volume */ 55*95860fdfSMark Brown { 5, 0x0008 }, /* R5 - DAC Control */ 56*95860fdfSMark Brown { 7, 0x000A }, /* R7 - Audio Interface */ 57*95860fdfSMark Brown { 8, 0x0000 }, /* R8 - Sample Rate */ 58*95860fdfSMark Brown { 10, 0x00FF }, /* R10 - Left DAC volume */ 59*95860fdfSMark Brown { 11, 0x00FF }, /* R11 - Right DAC volume */ 60*95860fdfSMark Brown { 12, 0x000F }, /* R12 - Bass control */ 61*95860fdfSMark Brown { 13, 0x000F }, /* R13 - Treble control */ 62*95860fdfSMark Brown { 23, 0x00C1 }, /* R23 - Additional control (1) */ 63*95860fdfSMark Brown { 24, 0x0000 }, /* R24 - Additional control (2) */ 64*95860fdfSMark Brown { 25, 0x0000 }, /* R25 - Power Management (1) */ 65*95860fdfSMark Brown { 26, 0x0000 }, /* R26 - Power Management (2) */ 66*95860fdfSMark Brown { 27, 0x0000 }, /* R27 - Additional Control (3) */ 67*95860fdfSMark Brown { 34, 0x0050 }, /* R34 - Left out Mix (1) */ 68*95860fdfSMark Brown { 35, 0x0050 }, /* R35 - Left out Mix (2) */ 69*95860fdfSMark Brown { 36, 0x0050 }, /* R36 - Right out Mix (1) */ 70*95860fdfSMark Brown { 37, 0x0050 }, /* R37 - Right Out Mix (2) */ 71*95860fdfSMark Brown { 38, 0x0050 }, /* R38 - Mono out Mix (1) */ 72*95860fdfSMark Brown { 39, 0x0050 }, /* R39 - Mono out Mix (2) */ 73*95860fdfSMark Brown { 40, 0x0079 }, /* R40 - LOUT2 volume */ 74*95860fdfSMark Brown { 41, 0x0079 }, /* R41 - ROUT2 volume */ 75*95860fdfSMark Brown { 42, 0x0079 }, /* R42 - MONOOUT volume */ 76*95860fdfSMark Brown { 43, 0x0000 }, /* R43 - Clocking / PLL */ 77*95860fdfSMark Brown { 44, 0x0103 }, /* R44 - PLL Control 1 */ 78*95860fdfSMark Brown { 45, 0x0024 }, /* R45 - PLL Control 2 */ 79*95860fdfSMark Brown { 46, 0x01BA }, /* R46 - PLL Control 3 */ 80*95860fdfSMark Brown { 59, 0x0000 }, /* R59 - PLL Control 4 */ 81b35a28afSMark Brown }; 82b35a28afSMark Brown 83*95860fdfSMark Brown static bool wm8955_writeable(struct device *dev, unsigned int reg) 84*95860fdfSMark Brown { 85*95860fdfSMark Brown switch (reg) { 86*95860fdfSMark Brown case WM8955_LOUT1_VOLUME: 87*95860fdfSMark Brown case WM8955_ROUT1_VOLUME: 88*95860fdfSMark Brown case WM8955_DAC_CONTROL: 89*95860fdfSMark Brown case WM8955_AUDIO_INTERFACE: 90*95860fdfSMark Brown case WM8955_SAMPLE_RATE: 91*95860fdfSMark Brown case WM8955_LEFT_DAC_VOLUME: 92*95860fdfSMark Brown case WM8955_RIGHT_DAC_VOLUME: 93*95860fdfSMark Brown case WM8955_BASS_CONTROL: 94*95860fdfSMark Brown case WM8955_TREBLE_CONTROL: 95*95860fdfSMark Brown case WM8955_RESET: 96*95860fdfSMark Brown case WM8955_ADDITIONAL_CONTROL_1: 97*95860fdfSMark Brown case WM8955_ADDITIONAL_CONTROL_2: 98*95860fdfSMark Brown case WM8955_POWER_MANAGEMENT_1: 99*95860fdfSMark Brown case WM8955_POWER_MANAGEMENT_2: 100*95860fdfSMark Brown case WM8955_ADDITIONAL_CONTROL_3: 101*95860fdfSMark Brown case WM8955_LEFT_OUT_MIX_1: 102*95860fdfSMark Brown case WM8955_LEFT_OUT_MIX_2: 103*95860fdfSMark Brown case WM8955_RIGHT_OUT_MIX_1: 104*95860fdfSMark Brown case WM8955_RIGHT_OUT_MIX_2: 105*95860fdfSMark Brown case WM8955_MONO_OUT_MIX_1: 106*95860fdfSMark Brown case WM8955_MONO_OUT_MIX_2: 107*95860fdfSMark Brown case WM8955_LOUT2_VOLUME: 108*95860fdfSMark Brown case WM8955_ROUT2_VOLUME: 109*95860fdfSMark Brown case WM8955_MONOOUT_VOLUME: 110*95860fdfSMark Brown case WM8955_CLOCKING_PLL: 111*95860fdfSMark Brown case WM8955_PLL_CONTROL_1: 112*95860fdfSMark Brown case WM8955_PLL_CONTROL_2: 113*95860fdfSMark Brown case WM8955_PLL_CONTROL_3: 114*95860fdfSMark Brown case WM8955_PLL_CONTROL_4: 115*95860fdfSMark Brown return true; 116*95860fdfSMark Brown default: 117*95860fdfSMark Brown return false; 118*95860fdfSMark Brown } 119*95860fdfSMark Brown } 120*95860fdfSMark Brown 121*95860fdfSMark Brown static bool wm8955_volatile(struct device *dev, unsigned int reg) 122*95860fdfSMark Brown { 123*95860fdfSMark Brown switch (reg) { 124*95860fdfSMark Brown case WM8955_RESET: 125*95860fdfSMark Brown return true; 126*95860fdfSMark Brown default: 127*95860fdfSMark Brown return false; 128*95860fdfSMark Brown } 129*95860fdfSMark Brown } 130*95860fdfSMark Brown 131b35a28afSMark Brown static int wm8955_reset(struct snd_soc_codec *codec) 132b35a28afSMark Brown { 133b35a28afSMark Brown return snd_soc_write(codec, WM8955_RESET, 0); 134b35a28afSMark Brown } 135b35a28afSMark Brown 136b35a28afSMark Brown struct pll_factors { 137b35a28afSMark Brown int n; 138b35a28afSMark Brown int k; 139b35a28afSMark Brown int outdiv; 140b35a28afSMark Brown }; 141b35a28afSMark Brown 142b35a28afSMark Brown /* The size in bits of the FLL divide multiplied by 10 143b35a28afSMark Brown * to allow rounding later */ 144b35a28afSMark Brown #define FIXED_FLL_SIZE ((1 << 22) * 10) 145b35a28afSMark Brown 146b35a28afSMark Brown static int wm8995_pll_factors(struct device *dev, 147b35a28afSMark Brown int Fref, int Fout, struct pll_factors *pll) 148b35a28afSMark Brown { 149b35a28afSMark Brown u64 Kpart; 150b35a28afSMark Brown unsigned int K, Ndiv, Nmod, target; 151b35a28afSMark Brown 152b35a28afSMark Brown dev_dbg(dev, "Fref=%u Fout=%u\n", Fref, Fout); 153b35a28afSMark Brown 154b35a28afSMark Brown /* The oscilator should run at should be 90-100MHz, and 155b35a28afSMark Brown * there's a divide by 4 plus an optional divide by 2 in the 156b35a28afSMark Brown * output path to generate the system clock. The clock table 157b35a28afSMark Brown * is sortd so we should always generate a suitable target. */ 158b35a28afSMark Brown target = Fout * 4; 159b35a28afSMark Brown if (target < 90000000) { 160b35a28afSMark Brown pll->outdiv = 1; 161b35a28afSMark Brown target *= 2; 162b35a28afSMark Brown } else { 163b35a28afSMark Brown pll->outdiv = 0; 164b35a28afSMark Brown } 165b35a28afSMark Brown 166b35a28afSMark Brown WARN_ON(target < 90000000 || target > 100000000); 167b35a28afSMark Brown 168b35a28afSMark Brown dev_dbg(dev, "Fvco=%dHz\n", target); 169b35a28afSMark Brown 170b35a28afSMark Brown /* Now, calculate N.K */ 171b35a28afSMark Brown Ndiv = target / Fref; 172b35a28afSMark Brown 173b35a28afSMark Brown pll->n = Ndiv; 174b35a28afSMark Brown Nmod = target % Fref; 175b35a28afSMark Brown dev_dbg(dev, "Nmod=%d\n", Nmod); 176b35a28afSMark Brown 177b35a28afSMark Brown /* Calculate fractional part - scale up so we can round. */ 178b35a28afSMark Brown Kpart = FIXED_FLL_SIZE * (long long)Nmod; 179b35a28afSMark Brown 180b35a28afSMark Brown do_div(Kpart, Fref); 181b35a28afSMark Brown 182b35a28afSMark Brown K = Kpart & 0xFFFFFFFF; 183b35a28afSMark Brown 184b35a28afSMark Brown if ((K % 10) >= 5) 185b35a28afSMark Brown K += 5; 186b35a28afSMark Brown 187b35a28afSMark Brown /* Move down to proper range now rounding is done */ 188b35a28afSMark Brown pll->k = K / 10; 189b35a28afSMark Brown 190b35a28afSMark Brown dev_dbg(dev, "N=%x K=%x OUTDIV=%x\n", pll->n, pll->k, pll->outdiv); 191b35a28afSMark Brown 192b35a28afSMark Brown return 0; 193b35a28afSMark Brown } 194b35a28afSMark Brown 19525985edcSLucas De Marchi /* Lookup table specifying SRATE (table 25 in datasheet); some of the 196b35a28afSMark Brown * output frequencies have been rounded to the standard frequencies 197b35a28afSMark Brown * they are intended to match where the error is slight. */ 198b35a28afSMark Brown static struct { 199b35a28afSMark Brown int mclk; 200b35a28afSMark Brown int fs; 201b35a28afSMark Brown int usb; 202b35a28afSMark Brown int sr; 203b35a28afSMark Brown } clock_cfgs[] = { 204b35a28afSMark Brown { 18432000, 8000, 0, 3, }, 205b35a28afSMark Brown { 18432000, 12000, 0, 9, }, 206b35a28afSMark Brown { 18432000, 16000, 0, 11, }, 207b35a28afSMark Brown { 18432000, 24000, 0, 29, }, 208b35a28afSMark Brown { 18432000, 32000, 0, 13, }, 209b35a28afSMark Brown { 18432000, 48000, 0, 1, }, 210b35a28afSMark Brown { 18432000, 96000, 0, 15, }, 211b35a28afSMark Brown 212b35a28afSMark Brown { 16934400, 8018, 0, 19, }, 213b35a28afSMark Brown { 16934400, 11025, 0, 25, }, 214b35a28afSMark Brown { 16934400, 22050, 0, 27, }, 215b35a28afSMark Brown { 16934400, 44100, 0, 17, }, 216b35a28afSMark Brown { 16934400, 88200, 0, 31, }, 217b35a28afSMark Brown 218b35a28afSMark Brown { 12000000, 8000, 1, 2, }, 219b35a28afSMark Brown { 12000000, 11025, 1, 25, }, 220b35a28afSMark Brown { 12000000, 12000, 1, 8, }, 221b35a28afSMark Brown { 12000000, 16000, 1, 10, }, 222b35a28afSMark Brown { 12000000, 22050, 1, 27, }, 223b35a28afSMark Brown { 12000000, 24000, 1, 28, }, 224b35a28afSMark Brown { 12000000, 32000, 1, 12, }, 225b35a28afSMark Brown { 12000000, 44100, 1, 17, }, 226b35a28afSMark Brown { 12000000, 48000, 1, 0, }, 227b35a28afSMark Brown { 12000000, 88200, 1, 31, }, 228b35a28afSMark Brown { 12000000, 96000, 1, 14, }, 229b35a28afSMark Brown 230b35a28afSMark Brown { 12288000, 8000, 0, 2, }, 231b35a28afSMark Brown { 12288000, 12000, 0, 8, }, 232b35a28afSMark Brown { 12288000, 16000, 0, 10, }, 233b35a28afSMark Brown { 12288000, 24000, 0, 28, }, 234b35a28afSMark Brown { 12288000, 32000, 0, 12, }, 235b35a28afSMark Brown { 12288000, 48000, 0, 0, }, 236b35a28afSMark Brown { 12288000, 96000, 0, 14, }, 237b35a28afSMark Brown 238b35a28afSMark Brown { 12289600, 8018, 0, 18, }, 239b35a28afSMark Brown { 12289600, 11025, 0, 24, }, 240b35a28afSMark Brown { 12289600, 22050, 0, 26, }, 241b35a28afSMark Brown { 11289600, 44100, 0, 16, }, 242b35a28afSMark Brown { 11289600, 88200, 0, 31, }, 243b35a28afSMark Brown }; 244b35a28afSMark Brown 245b35a28afSMark Brown static int wm8955_configure_clocking(struct snd_soc_codec *codec) 246b35a28afSMark Brown { 247b2c812e2SMark Brown struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 248b35a28afSMark Brown int i, ret, val; 249b35a28afSMark Brown int clocking = 0; 250b35a28afSMark Brown int srate = 0; 251b35a28afSMark Brown int sr = -1; 252b35a28afSMark Brown struct pll_factors pll; 253b35a28afSMark Brown 254b35a28afSMark Brown /* If we're not running a sample rate currently just pick one */ 255b35a28afSMark Brown if (wm8955->fs == 0) 256b35a28afSMark Brown wm8955->fs = 8000; 257b35a28afSMark Brown 258b35a28afSMark Brown /* Can we generate an exact output? */ 259b35a28afSMark Brown for (i = 0; i < ARRAY_SIZE(clock_cfgs); i++) { 260b35a28afSMark Brown if (wm8955->fs != clock_cfgs[i].fs) 261b35a28afSMark Brown continue; 262b35a28afSMark Brown sr = i; 263b35a28afSMark Brown 264b35a28afSMark Brown if (wm8955->mclk_rate == clock_cfgs[i].mclk) 265b35a28afSMark Brown break; 266b35a28afSMark Brown } 267b35a28afSMark Brown 268b35a28afSMark Brown /* We should never get here with an unsupported sample rate */ 269b35a28afSMark Brown if (sr == -1) { 270b35a28afSMark Brown dev_err(codec->dev, "Sample rate %dHz unsupported\n", 271b35a28afSMark Brown wm8955->fs); 272b35a28afSMark Brown WARN_ON(sr == -1); 273b35a28afSMark Brown return -EINVAL; 274b35a28afSMark Brown } 275b35a28afSMark Brown 276b35a28afSMark Brown if (i == ARRAY_SIZE(clock_cfgs)) { 277b35a28afSMark Brown /* If we can't generate the right clock from MCLK then 278b35a28afSMark Brown * we should configure the PLL to supply us with an 279b35a28afSMark Brown * appropriate clock. 280b35a28afSMark Brown */ 281b35a28afSMark Brown clocking |= WM8955_MCLKSEL; 282b35a28afSMark Brown 283b35a28afSMark Brown /* Use the last divider configuration we saw for the 284b35a28afSMark Brown * sample rate. */ 285b35a28afSMark Brown ret = wm8995_pll_factors(codec->dev, wm8955->mclk_rate, 286b35a28afSMark Brown clock_cfgs[sr].mclk, &pll); 287b35a28afSMark Brown if (ret != 0) { 288b35a28afSMark Brown dev_err(codec->dev, 289b35a28afSMark Brown "Unable to generate %dHz from %dHz MCLK\n", 290b35a28afSMark Brown wm8955->fs, wm8955->mclk_rate); 291b35a28afSMark Brown return -EINVAL; 292b35a28afSMark Brown } 293b35a28afSMark Brown 294b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_PLL_CONTROL_1, 295b35a28afSMark Brown WM8955_N_MASK | WM8955_K_21_18_MASK, 296b35a28afSMark Brown (pll.n << WM8955_N_SHIFT) | 297b35a28afSMark Brown pll.k >> 18); 298b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, 299b35a28afSMark Brown WM8955_K_17_9_MASK, 300b35a28afSMark Brown (pll.k >> 9) & WM8955_K_17_9_MASK); 301b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_PLL_CONTROL_2, 302b35a28afSMark Brown WM8955_K_8_0_MASK, 303b35a28afSMark Brown pll.k & WM8955_K_8_0_MASK); 304b35a28afSMark Brown if (pll.k) 305b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4, 306b35a28afSMark Brown WM8955_KEN, WM8955_KEN); 307b35a28afSMark Brown else 308b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_PLL_CONTROL_4, 309b35a28afSMark Brown WM8955_KEN, 0); 310b35a28afSMark Brown 311b35a28afSMark Brown if (pll.outdiv) 312b35a28afSMark Brown val = WM8955_PLL_RB | WM8955_PLLOUTDIV2; 313b35a28afSMark Brown else 314b35a28afSMark Brown val = WM8955_PLL_RB; 315b35a28afSMark Brown 316b35a28afSMark Brown /* Now start the PLL running */ 317b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, 318b35a28afSMark Brown WM8955_PLL_RB | WM8955_PLLOUTDIV2, val); 319b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, 320b35a28afSMark Brown WM8955_PLLEN, WM8955_PLLEN); 321b35a28afSMark Brown } 322b35a28afSMark Brown 323b35a28afSMark Brown srate = clock_cfgs[sr].usb | (clock_cfgs[sr].sr << WM8955_SR_SHIFT); 324b35a28afSMark Brown 325b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_SAMPLE_RATE, 326b35a28afSMark Brown WM8955_USB | WM8955_SR_MASK, srate); 327b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, 328b35a28afSMark Brown WM8955_MCLKSEL, clocking); 329b35a28afSMark Brown 330b35a28afSMark Brown return 0; 331b35a28afSMark Brown } 332b35a28afSMark Brown 333b35a28afSMark Brown static int wm8955_sysclk(struct snd_soc_dapm_widget *w, 334b35a28afSMark Brown struct snd_kcontrol *kcontrol, int event) 335b35a28afSMark Brown { 336b35a28afSMark Brown struct snd_soc_codec *codec = w->codec; 337b35a28afSMark Brown int ret = 0; 338b35a28afSMark Brown 339b35a28afSMark Brown /* Always disable the clocks - if we're doing reconfiguration this 340b35a28afSMark Brown * avoids misclocking. 341b35a28afSMark Brown */ 342b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, 343b35a28afSMark Brown WM8955_DIGENB, 0); 344b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, 345b35a28afSMark Brown WM8955_PLL_RB | WM8955_PLLEN, 0); 346b35a28afSMark Brown 347b35a28afSMark Brown switch (event) { 348b35a28afSMark Brown case SND_SOC_DAPM_POST_PMD: 349b35a28afSMark Brown break; 350b35a28afSMark Brown case SND_SOC_DAPM_PRE_PMU: 351b35a28afSMark Brown ret = wm8955_configure_clocking(codec); 352b35a28afSMark Brown break; 353b35a28afSMark Brown default: 354b35a28afSMark Brown ret = -EINVAL; 355b35a28afSMark Brown break; 356b35a28afSMark Brown } 357b35a28afSMark Brown 358b35a28afSMark Brown return ret; 359b35a28afSMark Brown } 360b35a28afSMark Brown 361b35a28afSMark Brown static int deemph_settings[] = { 0, 32000, 44100, 48000 }; 362b35a28afSMark Brown 363b35a28afSMark Brown static int wm8955_set_deemph(struct snd_soc_codec *codec) 364b35a28afSMark Brown { 365b2c812e2SMark Brown struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 366b35a28afSMark Brown int val, i, best; 367b35a28afSMark Brown 368b35a28afSMark Brown /* If we're using deemphasis select the nearest available sample 369b35a28afSMark Brown * rate. 370b35a28afSMark Brown */ 371b35a28afSMark Brown if (wm8955->deemph) { 372b35a28afSMark Brown best = 1; 373b35a28afSMark Brown for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) { 374b35a28afSMark Brown if (abs(deemph_settings[i] - wm8955->fs) < 375b35a28afSMark Brown abs(deemph_settings[best] - wm8955->fs)) 376b35a28afSMark Brown best = i; 377b35a28afSMark Brown } 378b35a28afSMark Brown 379b35a28afSMark Brown val = best << WM8955_DEEMPH_SHIFT; 380b35a28afSMark Brown } else { 381b35a28afSMark Brown val = 0; 382b35a28afSMark Brown } 383b35a28afSMark Brown 384b35a28afSMark Brown dev_dbg(codec->dev, "Set deemphasis %d\n", val); 385b35a28afSMark Brown 386b35a28afSMark Brown return snd_soc_update_bits(codec, WM8955_DAC_CONTROL, 387b35a28afSMark Brown WM8955_DEEMPH_MASK, val); 388b35a28afSMark Brown } 389b35a28afSMark Brown 390b35a28afSMark Brown static int wm8955_get_deemph(struct snd_kcontrol *kcontrol, 391b35a28afSMark Brown struct snd_ctl_elem_value *ucontrol) 392b35a28afSMark Brown { 393b35a28afSMark Brown struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 394b2c812e2SMark Brown struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 395b35a28afSMark Brown 3963f343f85SDmitry Artamonow ucontrol->value.enumerated.item[0] = wm8955->deemph; 3973f343f85SDmitry Artamonow return 0; 398b35a28afSMark Brown } 399b35a28afSMark Brown 400b35a28afSMark Brown static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, 401b35a28afSMark Brown struct snd_ctl_elem_value *ucontrol) 402b35a28afSMark Brown { 403b35a28afSMark Brown struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 404b2c812e2SMark Brown struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 405b35a28afSMark Brown int deemph = ucontrol->value.enumerated.item[0]; 406b35a28afSMark Brown 407b35a28afSMark Brown if (deemph > 1) 408b35a28afSMark Brown return -EINVAL; 409b35a28afSMark Brown 410b35a28afSMark Brown wm8955->deemph = deemph; 411b35a28afSMark Brown 412b35a28afSMark Brown return wm8955_set_deemph(codec); 413b35a28afSMark Brown } 414b35a28afSMark Brown 415b35a28afSMark Brown static const char *bass_mode_text[] = { 416b35a28afSMark Brown "Linear", "Adaptive", 417b35a28afSMark Brown }; 418b35a28afSMark Brown 419b35a28afSMark Brown static const struct soc_enum bass_mode = 420b35a28afSMark Brown SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 7, 2, bass_mode_text); 421b35a28afSMark Brown 422b35a28afSMark Brown static const char *bass_cutoff_text[] = { 423b35a28afSMark Brown "Low", "High" 424b35a28afSMark Brown }; 425b35a28afSMark Brown 426b35a28afSMark Brown static const struct soc_enum bass_cutoff = 427b35a28afSMark Brown SOC_ENUM_SINGLE(WM8955_BASS_CONTROL, 6, 2, bass_cutoff_text); 428b35a28afSMark Brown 429b35a28afSMark Brown static const char *treble_cutoff_text[] = { 430b35a28afSMark Brown "High", "Low" 431b35a28afSMark Brown }; 432b35a28afSMark Brown 433b35a28afSMark Brown static const struct soc_enum treble_cutoff = 434b35a28afSMark Brown SOC_ENUM_SINGLE(WM8955_TREBLE_CONTROL, 6, 2, treble_cutoff_text); 435b35a28afSMark Brown 436b35a28afSMark Brown static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); 437b35a28afSMark Brown static const DECLARE_TLV_DB_SCALE(atten_tlv, -600, 600, 0); 438b35a28afSMark Brown static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0); 439b35a28afSMark Brown static const DECLARE_TLV_DB_SCALE(mono_tlv, -2100, 300, 0); 440b35a28afSMark Brown static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); 441b35a28afSMark Brown static const DECLARE_TLV_DB_SCALE(treble_tlv, -1200, 150, 1); 442b35a28afSMark Brown 443b35a28afSMark Brown static const struct snd_kcontrol_new wm8955_snd_controls[] = { 444b35a28afSMark Brown SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8955_LEFT_DAC_VOLUME, 445b35a28afSMark Brown WM8955_RIGHT_DAC_VOLUME, 0, 255, 0, digital_tlv), 446b35a28afSMark Brown SOC_SINGLE_TLV("Playback Attenuation Volume", WM8955_DAC_CONTROL, 7, 1, 1, 447b35a28afSMark Brown atten_tlv), 448b35a28afSMark Brown SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0, 449b35a28afSMark Brown wm8955_get_deemph, wm8955_put_deemph), 450b35a28afSMark Brown 451b35a28afSMark Brown SOC_ENUM("Bass Mode", bass_mode), 452b35a28afSMark Brown SOC_ENUM("Bass Cutoff", bass_cutoff), 453b35a28afSMark Brown SOC_SINGLE("Bass Volume", WM8955_BASS_CONTROL, 0, 15, 1), 454b35a28afSMark Brown 455b35a28afSMark Brown SOC_ENUM("Treble Cutoff", treble_cutoff), 456b35a28afSMark Brown SOC_SINGLE_TLV("Treble Volume", WM8955_TREBLE_CONTROL, 0, 14, 1, treble_tlv), 457b35a28afSMark Brown 458b35a28afSMark Brown SOC_SINGLE_TLV("Left Bypass Volume", WM8955_LEFT_OUT_MIX_1, 4, 7, 1, 459b35a28afSMark Brown bypass_tlv), 460b35a28afSMark Brown SOC_SINGLE_TLV("Left Mono Volume", WM8955_LEFT_OUT_MIX_2, 4, 7, 1, 461b35a28afSMark Brown bypass_tlv), 462b35a28afSMark Brown 463b35a28afSMark Brown SOC_SINGLE_TLV("Right Mono Volume", WM8955_RIGHT_OUT_MIX_1, 4, 7, 1, 464b35a28afSMark Brown bypass_tlv), 465b35a28afSMark Brown SOC_SINGLE_TLV("Right Bypass Volume", WM8955_RIGHT_OUT_MIX_2, 4, 7, 1, 466b35a28afSMark Brown bypass_tlv), 467b35a28afSMark Brown 468b35a28afSMark Brown /* Not a stereo pair so they line up with the DAPM switches */ 469b35a28afSMark Brown SOC_SINGLE_TLV("Mono Left Bypass Volume", WM8955_MONO_OUT_MIX_1, 4, 7, 1, 470b35a28afSMark Brown mono_tlv), 471b35a28afSMark Brown SOC_SINGLE_TLV("Mono Right Bypass Volume", WM8955_MONO_OUT_MIX_2, 4, 7, 1, 472b35a28afSMark Brown mono_tlv), 473b35a28afSMark Brown 474b35a28afSMark Brown SOC_DOUBLE_R_TLV("Headphone Volume", WM8955_LOUT1_VOLUME, 475b35a28afSMark Brown WM8955_ROUT1_VOLUME, 0, 127, 0, out_tlv), 476b35a28afSMark Brown SOC_DOUBLE_R("Headphone ZC Switch", WM8955_LOUT1_VOLUME, 477b35a28afSMark Brown WM8955_ROUT1_VOLUME, 7, 1, 0), 478b35a28afSMark Brown 479b35a28afSMark Brown SOC_DOUBLE_R_TLV("Speaker Volume", WM8955_LOUT2_VOLUME, 480b35a28afSMark Brown WM8955_ROUT2_VOLUME, 0, 127, 0, out_tlv), 481b35a28afSMark Brown SOC_DOUBLE_R("Speaker ZC Switch", WM8955_LOUT2_VOLUME, 482b35a28afSMark Brown WM8955_ROUT2_VOLUME, 7, 1, 0), 483b35a28afSMark Brown 484b35a28afSMark Brown SOC_SINGLE_TLV("Mono Volume", WM8955_MONOOUT_VOLUME, 0, 127, 0, out_tlv), 485b35a28afSMark Brown SOC_SINGLE("Mono ZC Switch", WM8955_MONOOUT_VOLUME, 7, 1, 0), 486b35a28afSMark Brown }; 487b35a28afSMark Brown 488b35a28afSMark Brown static const struct snd_kcontrol_new lmixer[] = { 489b35a28afSMark Brown SOC_DAPM_SINGLE("Playback Switch", WM8955_LEFT_OUT_MIX_1, 8, 1, 0), 490b35a28afSMark Brown SOC_DAPM_SINGLE("Bypass Switch", WM8955_LEFT_OUT_MIX_1, 7, 1, 0), 491b35a28afSMark Brown SOC_DAPM_SINGLE("Right Playback Switch", WM8955_LEFT_OUT_MIX_2, 8, 1, 0), 492b35a28afSMark Brown SOC_DAPM_SINGLE("Mono Switch", WM8955_LEFT_OUT_MIX_2, 7, 1, 0), 493b35a28afSMark Brown }; 494b35a28afSMark Brown 495b35a28afSMark Brown static const struct snd_kcontrol_new rmixer[] = { 496b35a28afSMark Brown SOC_DAPM_SINGLE("Left Playback Switch", WM8955_RIGHT_OUT_MIX_1, 8, 1, 0), 497b35a28afSMark Brown SOC_DAPM_SINGLE("Mono Switch", WM8955_RIGHT_OUT_MIX_1, 7, 1, 0), 498b35a28afSMark Brown SOC_DAPM_SINGLE("Playback Switch", WM8955_RIGHT_OUT_MIX_2, 8, 1, 0), 499b35a28afSMark Brown SOC_DAPM_SINGLE("Bypass Switch", WM8955_RIGHT_OUT_MIX_2, 7, 1, 0), 500b35a28afSMark Brown }; 501b35a28afSMark Brown 502b35a28afSMark Brown static const struct snd_kcontrol_new mmixer[] = { 503b35a28afSMark Brown SOC_DAPM_SINGLE("Left Playback Switch", WM8955_MONO_OUT_MIX_1, 8, 1, 0), 504b35a28afSMark Brown SOC_DAPM_SINGLE("Left Bypass Switch", WM8955_MONO_OUT_MIX_1, 7, 1, 0), 505b35a28afSMark Brown SOC_DAPM_SINGLE("Right Playback Switch", WM8955_MONO_OUT_MIX_2, 8, 1, 0), 506b35a28afSMark Brown SOC_DAPM_SINGLE("Right Bypass Switch", WM8955_MONO_OUT_MIX_2, 7, 1, 0), 507b35a28afSMark Brown }; 508b35a28afSMark Brown 509b35a28afSMark Brown static const struct snd_soc_dapm_widget wm8955_dapm_widgets[] = { 510b35a28afSMark Brown SND_SOC_DAPM_INPUT("MONOIN-"), 511b35a28afSMark Brown SND_SOC_DAPM_INPUT("MONOIN+"), 512b35a28afSMark Brown SND_SOC_DAPM_INPUT("LINEINR"), 513b35a28afSMark Brown SND_SOC_DAPM_INPUT("LINEINL"), 514b35a28afSMark Brown 515b35a28afSMark Brown SND_SOC_DAPM_PGA("Mono Input", SND_SOC_NOPM, 0, 0, NULL, 0), 516b35a28afSMark Brown 517b35a28afSMark Brown SND_SOC_DAPM_SUPPLY("SYSCLK", WM8955_POWER_MANAGEMENT_1, 0, 1, wm8955_sysclk, 518b35a28afSMark Brown SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 519b35a28afSMark Brown SND_SOC_DAPM_SUPPLY("TSDEN", WM8955_ADDITIONAL_CONTROL_1, 8, 0, NULL, 0), 520b35a28afSMark Brown 521b35a28afSMark Brown SND_SOC_DAPM_DAC("DACL", "Playback", WM8955_POWER_MANAGEMENT_2, 8, 0), 522b35a28afSMark Brown SND_SOC_DAPM_DAC("DACR", "Playback", WM8955_POWER_MANAGEMENT_2, 7, 0), 523b35a28afSMark Brown 524b35a28afSMark Brown SND_SOC_DAPM_PGA("LOUT1 PGA", WM8955_POWER_MANAGEMENT_2, 6, 0, NULL, 0), 525b35a28afSMark Brown SND_SOC_DAPM_PGA("ROUT1 PGA", WM8955_POWER_MANAGEMENT_2, 5, 0, NULL, 0), 526b35a28afSMark Brown SND_SOC_DAPM_PGA("LOUT2 PGA", WM8955_POWER_MANAGEMENT_2, 4, 0, NULL, 0), 527b35a28afSMark Brown SND_SOC_DAPM_PGA("ROUT2 PGA", WM8955_POWER_MANAGEMENT_2, 3, 0, NULL, 0), 528b35a28afSMark Brown SND_SOC_DAPM_PGA("MOUT PGA", WM8955_POWER_MANAGEMENT_2, 2, 0, NULL, 0), 529b35a28afSMark Brown SND_SOC_DAPM_PGA("OUT3 PGA", WM8955_POWER_MANAGEMENT_2, 1, 0, NULL, 0), 530b35a28afSMark Brown 531b35a28afSMark Brown /* The names are chosen to make the control names nice */ 532b35a28afSMark Brown SND_SOC_DAPM_MIXER("Left", SND_SOC_NOPM, 0, 0, 533b35a28afSMark Brown lmixer, ARRAY_SIZE(lmixer)), 534b35a28afSMark Brown SND_SOC_DAPM_MIXER("Right", SND_SOC_NOPM, 0, 0, 535b35a28afSMark Brown rmixer, ARRAY_SIZE(rmixer)), 536b35a28afSMark Brown SND_SOC_DAPM_MIXER("Mono", SND_SOC_NOPM, 0, 0, 537b35a28afSMark Brown mmixer, ARRAY_SIZE(mmixer)), 538b35a28afSMark Brown 539b35a28afSMark Brown SND_SOC_DAPM_OUTPUT("LOUT1"), 540b35a28afSMark Brown SND_SOC_DAPM_OUTPUT("ROUT1"), 541b35a28afSMark Brown SND_SOC_DAPM_OUTPUT("LOUT2"), 542b35a28afSMark Brown SND_SOC_DAPM_OUTPUT("ROUT2"), 543b35a28afSMark Brown SND_SOC_DAPM_OUTPUT("MONOOUT"), 544b35a28afSMark Brown SND_SOC_DAPM_OUTPUT("OUT3"), 545b35a28afSMark Brown }; 546b35a28afSMark Brown 547b35a28afSMark Brown static const struct snd_soc_dapm_route wm8955_intercon[] = { 548b35a28afSMark Brown { "DACL", NULL, "SYSCLK" }, 549b35a28afSMark Brown { "DACR", NULL, "SYSCLK" }, 550b35a28afSMark Brown 551b35a28afSMark Brown { "Mono Input", NULL, "MONOIN-" }, 552b35a28afSMark Brown { "Mono Input", NULL, "MONOIN+" }, 553b35a28afSMark Brown 554b35a28afSMark Brown { "Left", "Playback Switch", "DACL" }, 555b35a28afSMark Brown { "Left", "Right Playback Switch", "DACR" }, 556b35a28afSMark Brown { "Left", "Bypass Switch", "LINEINL" }, 557b35a28afSMark Brown { "Left", "Mono Switch", "Mono Input" }, 558b35a28afSMark Brown 559b35a28afSMark Brown { "Right", "Playback Switch", "DACR" }, 560b35a28afSMark Brown { "Right", "Left Playback Switch", "DACL" }, 561b35a28afSMark Brown { "Right", "Bypass Switch", "LINEINR" }, 562b35a28afSMark Brown { "Right", "Mono Switch", "Mono Input" }, 563b35a28afSMark Brown 564b35a28afSMark Brown { "Mono", "Left Playback Switch", "DACL" }, 565b35a28afSMark Brown { "Mono", "Right Playback Switch", "DACR" }, 566b35a28afSMark Brown { "Mono", "Left Bypass Switch", "LINEINL" }, 567b35a28afSMark Brown { "Mono", "Right Bypass Switch", "LINEINR" }, 568b35a28afSMark Brown 569b35a28afSMark Brown { "LOUT1 PGA", NULL, "Left" }, 570b35a28afSMark Brown { "LOUT1", NULL, "TSDEN" }, 571b35a28afSMark Brown { "LOUT1", NULL, "LOUT1 PGA" }, 572b35a28afSMark Brown 573b35a28afSMark Brown { "ROUT1 PGA", NULL, "Right" }, 574b35a28afSMark Brown { "ROUT1", NULL, "TSDEN" }, 575b35a28afSMark Brown { "ROUT1", NULL, "ROUT1 PGA" }, 576b35a28afSMark Brown 577b35a28afSMark Brown { "LOUT2 PGA", NULL, "Left" }, 578b35a28afSMark Brown { "LOUT2", NULL, "TSDEN" }, 579b35a28afSMark Brown { "LOUT2", NULL, "LOUT2 PGA" }, 580b35a28afSMark Brown 581b35a28afSMark Brown { "ROUT2 PGA", NULL, "Right" }, 582b35a28afSMark Brown { "ROUT2", NULL, "TSDEN" }, 583b35a28afSMark Brown { "ROUT2", NULL, "ROUT2 PGA" }, 584b35a28afSMark Brown 585b35a28afSMark Brown { "MOUT PGA", NULL, "Mono" }, 586b35a28afSMark Brown { "MONOOUT", NULL, "MOUT PGA" }, 587b35a28afSMark Brown 588b35a28afSMark Brown /* OUT3 not currently implemented */ 589b35a28afSMark Brown { "OUT3", NULL, "OUT3 PGA" }, 590b35a28afSMark Brown }; 591b35a28afSMark Brown 592b35a28afSMark Brown static int wm8955_add_widgets(struct snd_soc_codec *codec) 593b35a28afSMark Brown { 594ce6120ccSLiam Girdwood struct snd_soc_dapm_context *dapm = &codec->dapm; 595ce6120ccSLiam Girdwood 596b35a28afSMark Brown snd_soc_add_controls(codec, wm8955_snd_controls, 597b35a28afSMark Brown ARRAY_SIZE(wm8955_snd_controls)); 598b35a28afSMark Brown 599ce6120ccSLiam Girdwood snd_soc_dapm_new_controls(dapm, wm8955_dapm_widgets, 600b35a28afSMark Brown ARRAY_SIZE(wm8955_dapm_widgets)); 601ce6120ccSLiam Girdwood snd_soc_dapm_add_routes(dapm, wm8955_intercon, 602b35a28afSMark Brown ARRAY_SIZE(wm8955_intercon)); 603b35a28afSMark Brown 604b35a28afSMark Brown return 0; 605b35a28afSMark Brown } 606b35a28afSMark Brown 607b35a28afSMark Brown static int wm8955_hw_params(struct snd_pcm_substream *substream, 608b35a28afSMark Brown struct snd_pcm_hw_params *params, 609b35a28afSMark Brown struct snd_soc_dai *dai) 610b35a28afSMark Brown { 611b35a28afSMark Brown struct snd_soc_codec *codec = dai->codec; 612b2c812e2SMark Brown struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 613b35a28afSMark Brown int ret; 614b35a28afSMark Brown int wl; 615b35a28afSMark Brown 616b35a28afSMark Brown switch (params_format(params)) { 617b35a28afSMark Brown case SNDRV_PCM_FORMAT_S16_LE: 618b35a28afSMark Brown wl = 0; 619b35a28afSMark Brown break; 620b35a28afSMark Brown case SNDRV_PCM_FORMAT_S20_3LE: 621b35a28afSMark Brown wl = 0x4; 622b35a28afSMark Brown break; 623b35a28afSMark Brown case SNDRV_PCM_FORMAT_S24_LE: 624b35a28afSMark Brown wl = 0x8; 625b35a28afSMark Brown break; 626b35a28afSMark Brown case SNDRV_PCM_FORMAT_S32_LE: 627b35a28afSMark Brown wl = 0xc; 628b35a28afSMark Brown break; 629b35a28afSMark Brown default: 630b35a28afSMark Brown return -EINVAL; 631b35a28afSMark Brown } 632b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_AUDIO_INTERFACE, 633b35a28afSMark Brown WM8955_WL_MASK, wl); 634b35a28afSMark Brown 635b35a28afSMark Brown wm8955->fs = params_rate(params); 636b35a28afSMark Brown wm8955_set_deemph(codec); 637b35a28afSMark Brown 638b35a28afSMark Brown /* If the chip is clocked then disable the clocks and force a 639b35a28afSMark Brown * reconfiguration, otherwise DAPM will power up the 640b35a28afSMark Brown * clocks for us later. */ 641b35a28afSMark Brown ret = snd_soc_read(codec, WM8955_POWER_MANAGEMENT_1); 642b35a28afSMark Brown if (ret < 0) 643b35a28afSMark Brown return ret; 644b35a28afSMark Brown if (ret & WM8955_DIGENB) { 645b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, 646b35a28afSMark Brown WM8955_DIGENB, 0); 647b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_CLOCKING_PLL, 648b35a28afSMark Brown WM8955_PLL_RB | WM8955_PLLEN, 0); 649b35a28afSMark Brown 650b35a28afSMark Brown wm8955_configure_clocking(codec); 651b35a28afSMark Brown } 652b35a28afSMark Brown 653b35a28afSMark Brown return 0; 654b35a28afSMark Brown } 655b35a28afSMark Brown 656b35a28afSMark Brown 657b35a28afSMark Brown static int wm8955_set_sysclk(struct snd_soc_dai *dai, int clk_id, 658b35a28afSMark Brown unsigned int freq, int dir) 659b35a28afSMark Brown { 660b35a28afSMark Brown struct snd_soc_codec *codec = dai->codec; 661b2c812e2SMark Brown struct wm8955_priv *priv = snd_soc_codec_get_drvdata(codec); 662b35a28afSMark Brown int div; 663b35a28afSMark Brown 664b35a28afSMark Brown switch (clk_id) { 665b35a28afSMark Brown case WM8955_CLK_MCLK: 666b35a28afSMark Brown if (freq > 15000000) { 667b35a28afSMark Brown priv->mclk_rate = freq /= 2; 668b35a28afSMark Brown div = WM8955_MCLKDIV2; 669b35a28afSMark Brown } else { 670b35a28afSMark Brown priv->mclk_rate = freq; 671b35a28afSMark Brown div = 0; 672b35a28afSMark Brown } 673b35a28afSMark Brown 674b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_SAMPLE_RATE, 675b35a28afSMark Brown WM8955_MCLKDIV2, div); 676b35a28afSMark Brown break; 677b35a28afSMark Brown 678b35a28afSMark Brown default: 679b35a28afSMark Brown return -EINVAL; 680b35a28afSMark Brown } 681b35a28afSMark Brown 682b35a28afSMark Brown dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); 683b35a28afSMark Brown 684b35a28afSMark Brown return 0; 685b35a28afSMark Brown } 686b35a28afSMark Brown 687b35a28afSMark Brown static int wm8955_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 688b35a28afSMark Brown { 689b35a28afSMark Brown struct snd_soc_codec *codec = dai->codec; 690b35a28afSMark Brown u16 aif = 0; 691b35a28afSMark Brown 692b35a28afSMark Brown switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 693b35a28afSMark Brown case SND_SOC_DAIFMT_CBS_CFS: 694b35a28afSMark Brown break; 695b35a28afSMark Brown case SND_SOC_DAIFMT_CBM_CFM: 696b35a28afSMark Brown aif |= WM8955_MS; 697b35a28afSMark Brown break; 698b35a28afSMark Brown default: 699b35a28afSMark Brown return -EINVAL; 700b35a28afSMark Brown } 701b35a28afSMark Brown 702b35a28afSMark Brown switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 703b35a28afSMark Brown case SND_SOC_DAIFMT_DSP_B: 704b35a28afSMark Brown aif |= WM8955_LRP; 705b35a28afSMark Brown case SND_SOC_DAIFMT_DSP_A: 706b35a28afSMark Brown aif |= 0x3; 707b35a28afSMark Brown break; 708b35a28afSMark Brown case SND_SOC_DAIFMT_I2S: 709b35a28afSMark Brown aif |= 0x2; 710b35a28afSMark Brown break; 711b35a28afSMark Brown case SND_SOC_DAIFMT_RIGHT_J: 712b35a28afSMark Brown break; 713b35a28afSMark Brown case SND_SOC_DAIFMT_LEFT_J: 714b35a28afSMark Brown aif |= 0x1; 715b35a28afSMark Brown break; 716b35a28afSMark Brown default: 717b35a28afSMark Brown return -EINVAL; 718b35a28afSMark Brown } 719b35a28afSMark Brown 720b35a28afSMark Brown switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 721b35a28afSMark Brown case SND_SOC_DAIFMT_DSP_A: 722b35a28afSMark Brown case SND_SOC_DAIFMT_DSP_B: 723b35a28afSMark Brown /* frame inversion not valid for DSP modes */ 724b35a28afSMark Brown switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 725b35a28afSMark Brown case SND_SOC_DAIFMT_NB_NF: 726b35a28afSMark Brown break; 727b35a28afSMark Brown case SND_SOC_DAIFMT_IB_NF: 728b35a28afSMark Brown aif |= WM8955_BCLKINV; 729b35a28afSMark Brown break; 730b35a28afSMark Brown default: 731b35a28afSMark Brown return -EINVAL; 732b35a28afSMark Brown } 733b35a28afSMark Brown break; 734b35a28afSMark Brown 735b35a28afSMark Brown case SND_SOC_DAIFMT_I2S: 736b35a28afSMark Brown case SND_SOC_DAIFMT_RIGHT_J: 737b35a28afSMark Brown case SND_SOC_DAIFMT_LEFT_J: 738b35a28afSMark Brown switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 739b35a28afSMark Brown case SND_SOC_DAIFMT_NB_NF: 740b35a28afSMark Brown break; 741b35a28afSMark Brown case SND_SOC_DAIFMT_IB_IF: 742b35a28afSMark Brown aif |= WM8955_BCLKINV | WM8955_LRP; 743b35a28afSMark Brown break; 744b35a28afSMark Brown case SND_SOC_DAIFMT_IB_NF: 745b35a28afSMark Brown aif |= WM8955_BCLKINV; 746b35a28afSMark Brown break; 747b35a28afSMark Brown case SND_SOC_DAIFMT_NB_IF: 748b35a28afSMark Brown aif |= WM8955_LRP; 749b35a28afSMark Brown break; 750b35a28afSMark Brown default: 751b35a28afSMark Brown return -EINVAL; 752b35a28afSMark Brown } 753b35a28afSMark Brown break; 754b35a28afSMark Brown default: 755b35a28afSMark Brown return -EINVAL; 756b35a28afSMark Brown } 757b35a28afSMark Brown 758b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_AUDIO_INTERFACE, 759b35a28afSMark Brown WM8955_MS | WM8955_FORMAT_MASK | WM8955_BCLKINV | 760b35a28afSMark Brown WM8955_LRP, aif); 761b35a28afSMark Brown 762b35a28afSMark Brown return 0; 763b35a28afSMark Brown } 764b35a28afSMark Brown 765b35a28afSMark Brown 766b35a28afSMark Brown static int wm8955_digital_mute(struct snd_soc_dai *codec_dai, int mute) 767b35a28afSMark Brown { 768b35a28afSMark Brown struct snd_soc_codec *codec = codec_dai->codec; 769b35a28afSMark Brown int val; 770b35a28afSMark Brown 771b35a28afSMark Brown if (mute) 772b35a28afSMark Brown val = WM8955_DACMU; 773b35a28afSMark Brown else 774b35a28afSMark Brown val = 0; 775b35a28afSMark Brown 776b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_DAC_CONTROL, WM8955_DACMU, val); 777b35a28afSMark Brown 778b35a28afSMark Brown return 0; 779b35a28afSMark Brown } 780b35a28afSMark Brown 781b35a28afSMark Brown static int wm8955_set_bias_level(struct snd_soc_codec *codec, 782b35a28afSMark Brown enum snd_soc_bias_level level) 783b35a28afSMark Brown { 784b2c812e2SMark Brown struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 785*95860fdfSMark Brown int ret; 786b35a28afSMark Brown 787b35a28afSMark Brown switch (level) { 788b35a28afSMark Brown case SND_SOC_BIAS_ON: 789b35a28afSMark Brown break; 790b35a28afSMark Brown 791b35a28afSMark Brown case SND_SOC_BIAS_PREPARE: 792b35a28afSMark Brown /* VMID resistance 2*50k */ 793b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, 794b35a28afSMark Brown WM8955_VMIDSEL_MASK, 795b35a28afSMark Brown 0x1 << WM8955_VMIDSEL_SHIFT); 796b35a28afSMark Brown 797b35a28afSMark Brown /* Default bias current */ 798b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_1, 799b35a28afSMark Brown WM8955_VSEL_MASK, 800b35a28afSMark Brown 0x2 << WM8955_VSEL_SHIFT); 801b35a28afSMark Brown break; 802b35a28afSMark Brown 803b35a28afSMark Brown case SND_SOC_BIAS_STANDBY: 804ce6120ccSLiam Girdwood if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { 805b35a28afSMark Brown ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), 806b35a28afSMark Brown wm8955->supplies); 807b35a28afSMark Brown if (ret != 0) { 808b35a28afSMark Brown dev_err(codec->dev, 809b35a28afSMark Brown "Failed to enable supplies: %d\n", 810b35a28afSMark Brown ret); 811b35a28afSMark Brown return ret; 812b35a28afSMark Brown } 813b35a28afSMark Brown 814*95860fdfSMark Brown regcache_sync(wm8955->regmap); 815b35a28afSMark Brown 816b35a28afSMark Brown /* Enable VREF and VMID */ 817b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, 818b35a28afSMark Brown WM8955_VREF | 819b35a28afSMark Brown WM8955_VMIDSEL_MASK, 820b35a28afSMark Brown WM8955_VREF | 821b35a28afSMark Brown 0x3 << WM8955_VREF_SHIFT); 822b35a28afSMark Brown 823b35a28afSMark Brown /* Let VMID ramp */ 824b35a28afSMark Brown msleep(500); 825b35a28afSMark Brown 826b35a28afSMark Brown /* High resistance VROI to maintain outputs */ 827b35a28afSMark Brown snd_soc_update_bits(codec, 828b35a28afSMark Brown WM8955_ADDITIONAL_CONTROL_3, 829b35a28afSMark Brown WM8955_VROI, WM8955_VROI); 830b35a28afSMark Brown } 831b35a28afSMark Brown 832b35a28afSMark Brown /* Maintain VMID with 2*250k */ 833b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, 834b35a28afSMark Brown WM8955_VMIDSEL_MASK, 835b35a28afSMark Brown 0x2 << WM8955_VMIDSEL_SHIFT); 836b35a28afSMark Brown 837b35a28afSMark Brown /* Minimum bias current */ 838b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_1, 839b35a28afSMark Brown WM8955_VSEL_MASK, 0); 840b35a28afSMark Brown break; 841b35a28afSMark Brown 842b35a28afSMark Brown case SND_SOC_BIAS_OFF: 843b35a28afSMark Brown /* Low resistance VROI to help discharge */ 844b35a28afSMark Brown snd_soc_update_bits(codec, 845b35a28afSMark Brown WM8955_ADDITIONAL_CONTROL_3, 846b35a28afSMark Brown WM8955_VROI, 0); 847b35a28afSMark Brown 848b35a28afSMark Brown /* Turn off VMID and VREF */ 849b35a28afSMark Brown snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, 850b35a28afSMark Brown WM8955_VREF | 851b35a28afSMark Brown WM8955_VMIDSEL_MASK, 0); 852b35a28afSMark Brown 853b35a28afSMark Brown regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), 854b35a28afSMark Brown wm8955->supplies); 855b35a28afSMark Brown break; 856b35a28afSMark Brown } 857ce6120ccSLiam Girdwood codec->dapm.bias_level = level; 858b35a28afSMark Brown return 0; 859b35a28afSMark Brown } 860b35a28afSMark Brown 861b35a28afSMark Brown #define WM8955_RATES SNDRV_PCM_RATE_8000_96000 862b35a28afSMark Brown 863b35a28afSMark Brown #define WM8955_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 864b35a28afSMark Brown SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 865b35a28afSMark Brown 86685e7652dSLars-Peter Clausen static const struct snd_soc_dai_ops wm8955_dai_ops = { 867b35a28afSMark Brown .set_sysclk = wm8955_set_sysclk, 868b35a28afSMark Brown .set_fmt = wm8955_set_fmt, 869b35a28afSMark Brown .hw_params = wm8955_hw_params, 870b35a28afSMark Brown .digital_mute = wm8955_digital_mute, 871b35a28afSMark Brown }; 872b35a28afSMark Brown 873f0fba2adSLiam Girdwood static struct snd_soc_dai_driver wm8955_dai = { 874f0fba2adSLiam Girdwood .name = "wm8955-hifi", 875b35a28afSMark Brown .playback = { 876b35a28afSMark Brown .stream_name = "Playback", 877b35a28afSMark Brown .channels_min = 2, 878b35a28afSMark Brown .channels_max = 2, 879b35a28afSMark Brown .rates = WM8955_RATES, 880b35a28afSMark Brown .formats = WM8955_FORMATS, 881b35a28afSMark Brown }, 882b35a28afSMark Brown .ops = &wm8955_dai_ops, 883b35a28afSMark Brown }; 884b35a28afSMark Brown 885b35a28afSMark Brown #ifdef CONFIG_PM 88684b315eeSLars-Peter Clausen static int wm8955_suspend(struct snd_soc_codec *codec) 887b35a28afSMark Brown { 888*95860fdfSMark Brown struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 889*95860fdfSMark Brown 890b35a28afSMark Brown wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); 891b35a28afSMark Brown 892*95860fdfSMark Brown regcache_mark_dirty(wm8955->regmap); 893*95860fdfSMark Brown 894b35a28afSMark Brown return 0; 895b35a28afSMark Brown } 896b35a28afSMark Brown 897f0fba2adSLiam Girdwood static int wm8955_resume(struct snd_soc_codec *codec) 898b35a28afSMark Brown { 899b35a28afSMark Brown wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 900b35a28afSMark Brown 901b35a28afSMark Brown return 0; 902b35a28afSMark Brown } 903b35a28afSMark Brown #else 904b35a28afSMark Brown #define wm8955_suspend NULL 905b35a28afSMark Brown #define wm8955_resume NULL 906b35a28afSMark Brown #endif 907b35a28afSMark Brown 908f0fba2adSLiam Girdwood static int wm8955_probe(struct snd_soc_codec *codec) 909b35a28afSMark Brown { 910f0fba2adSLiam Girdwood struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 911f0fba2adSLiam Girdwood struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); 912f0fba2adSLiam Girdwood int ret, i; 913b35a28afSMark Brown 914*95860fdfSMark Brown codec->control_data = wm8955->regmap; 915*95860fdfSMark Brown 916*95860fdfSMark Brown ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); 917b35a28afSMark Brown if (ret != 0) { 918b35a28afSMark Brown dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 919f0fba2adSLiam Girdwood return ret; 920b35a28afSMark Brown } 921b35a28afSMark Brown 922b35a28afSMark Brown for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) 923b35a28afSMark Brown wm8955->supplies[i].supply = wm8955_supply_names[i]; 924b35a28afSMark Brown 925b35a28afSMark Brown ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8955->supplies), 926b35a28afSMark Brown wm8955->supplies); 927b35a28afSMark Brown if (ret != 0) { 928b35a28afSMark Brown dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 929f0fba2adSLiam Girdwood return ret; 930b35a28afSMark Brown } 931b35a28afSMark Brown 932b35a28afSMark Brown ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), 933b35a28afSMark Brown wm8955->supplies); 934b35a28afSMark Brown if (ret != 0) { 935b35a28afSMark Brown dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); 936b35a28afSMark Brown goto err_get; 937b35a28afSMark Brown } 938b35a28afSMark Brown 939b35a28afSMark Brown ret = wm8955_reset(codec); 940b35a28afSMark Brown if (ret < 0) { 941b35a28afSMark Brown dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 942b35a28afSMark Brown goto err_enable; 943b35a28afSMark Brown } 944b35a28afSMark Brown 945b35a28afSMark Brown /* Change some default settings - latch VU and enable ZC */ 946a1b3b5eeSMark Brown snd_soc_update_bits(codec, WM8955_LEFT_DAC_VOLUME, 947a1b3b5eeSMark Brown WM8955_LDVU, WM8955_LDVU); 948a1b3b5eeSMark Brown snd_soc_update_bits(codec, WM8955_RIGHT_DAC_VOLUME, 949a1b3b5eeSMark Brown WM8955_RDVU, WM8955_RDVU); 950a1b3b5eeSMark Brown snd_soc_update_bits(codec, WM8955_LOUT1_VOLUME, 951a1b3b5eeSMark Brown WM8955_LO1VU | WM8955_LO1ZC, 952a1b3b5eeSMark Brown WM8955_LO1VU | WM8955_LO1ZC); 953a1b3b5eeSMark Brown snd_soc_update_bits(codec, WM8955_ROUT1_VOLUME, 954a1b3b5eeSMark Brown WM8955_RO1VU | WM8955_RO1ZC, 955a1b3b5eeSMark Brown WM8955_RO1VU | WM8955_RO1ZC); 956a1b3b5eeSMark Brown snd_soc_update_bits(codec, WM8955_LOUT2_VOLUME, 957a1b3b5eeSMark Brown WM8955_LO2VU | WM8955_LO2ZC, 958a1b3b5eeSMark Brown WM8955_LO2VU | WM8955_LO2ZC); 959a1b3b5eeSMark Brown snd_soc_update_bits(codec, WM8955_ROUT2_VOLUME, 960a1b3b5eeSMark Brown WM8955_RO2VU | WM8955_RO2ZC, 961a1b3b5eeSMark Brown WM8955_RO2VU | WM8955_RO2ZC); 962a1b3b5eeSMark Brown snd_soc_update_bits(codec, WM8955_MONOOUT_VOLUME, 963a1b3b5eeSMark Brown WM8955_MOZC, WM8955_MOZC); 964b35a28afSMark Brown 965b35a28afSMark Brown /* Also enable adaptive bass boost by default */ 966a1b3b5eeSMark Brown snd_soc_update_bits(codec, WM8955_BASS_CONTROL, WM8955_BB, WM8955_BB); 967b35a28afSMark Brown 968b35a28afSMark Brown /* Set platform data values */ 969f0fba2adSLiam Girdwood if (pdata) { 970f0fba2adSLiam Girdwood if (pdata->out2_speaker) 971*95860fdfSMark Brown snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2, 972*95860fdfSMark Brown WM8955_ROUT2INV, WM8955_ROUT2INV); 973b35a28afSMark Brown 974f0fba2adSLiam Girdwood if (pdata->monoin_diff) 975*95860fdfSMark Brown snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1, 976*95860fdfSMark Brown WM8955_DMEN, WM8955_DMEN); 977b35a28afSMark Brown } 978b35a28afSMark Brown 979b35a28afSMark Brown wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 980b35a28afSMark Brown 981b35a28afSMark Brown /* Bias level configuration will have done an extra enable */ 982b35a28afSMark Brown regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 983b35a28afSMark Brown 984f0fba2adSLiam Girdwood wm8955_add_widgets(codec); 985b35a28afSMark Brown return 0; 986b35a28afSMark Brown 987b35a28afSMark Brown err_enable: 988b35a28afSMark Brown regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 989b35a28afSMark Brown err_get: 990b35a28afSMark Brown regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 991b35a28afSMark Brown return ret; 992b35a28afSMark Brown } 993b35a28afSMark Brown 994f0fba2adSLiam Girdwood static int wm8955_remove(struct snd_soc_codec *codec) 995b35a28afSMark Brown { 996f0fba2adSLiam Girdwood struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 997f0fba2adSLiam Girdwood 998f0fba2adSLiam Girdwood wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); 999b35a28afSMark Brown regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 1000f0fba2adSLiam Girdwood return 0; 1001b35a28afSMark Brown } 1002b35a28afSMark Brown 1003f0fba2adSLiam Girdwood static struct snd_soc_codec_driver soc_codec_dev_wm8955 = { 1004f0fba2adSLiam Girdwood .probe = wm8955_probe, 1005f0fba2adSLiam Girdwood .remove = wm8955_remove, 1006f0fba2adSLiam Girdwood .suspend = wm8955_suspend, 1007f0fba2adSLiam Girdwood .resume = wm8955_resume, 1008f0fba2adSLiam Girdwood .set_bias_level = wm8955_set_bias_level, 1009*95860fdfSMark Brown }; 1010*95860fdfSMark Brown 1011*95860fdfSMark Brown static const struct regmap_config wm8955_regmap = { 1012*95860fdfSMark Brown .reg_bits = 7, 1013*95860fdfSMark Brown .val_bits = 9, 1014*95860fdfSMark Brown 1015*95860fdfSMark Brown .max_register = WM8955_MAX_REGISTER, 1016*95860fdfSMark Brown .volatile_reg = wm8955_volatile, 1017*95860fdfSMark Brown .writeable_reg = wm8955_writeable, 1018*95860fdfSMark Brown 1019*95860fdfSMark Brown .cache_type = REGCACHE_RBTREE, 1020*95860fdfSMark Brown .reg_defaults = wm8955_reg_defaults, 1021*95860fdfSMark Brown .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults), 1022f0fba2adSLiam Girdwood }; 1023f0fba2adSLiam Girdwood 1024b35a28afSMark Brown static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, 1025b35a28afSMark Brown const struct i2c_device_id *id) 1026b35a28afSMark Brown { 1027b35a28afSMark Brown struct wm8955_priv *wm8955; 1028f0fba2adSLiam Girdwood int ret; 1029b35a28afSMark Brown 1030ba5c88d0SMark Brown wm8955 = devm_kzalloc(&i2c->dev, sizeof(struct wm8955_priv), 1031ba5c88d0SMark Brown GFP_KERNEL); 1032b35a28afSMark Brown if (wm8955 == NULL) 1033b35a28afSMark Brown return -ENOMEM; 1034b35a28afSMark Brown 1035*95860fdfSMark Brown wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap); 1036*95860fdfSMark Brown if (IS_ERR(wm8955->regmap)) { 1037*95860fdfSMark Brown ret = PTR_ERR(wm8955->regmap); 1038*95860fdfSMark Brown dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 1039*95860fdfSMark Brown ret); 1040*95860fdfSMark Brown return ret; 1041*95860fdfSMark Brown } 1042*95860fdfSMark Brown 1043b35a28afSMark Brown i2c_set_clientdata(i2c, wm8955); 1044b35a28afSMark Brown 1045f0fba2adSLiam Girdwood ret = snd_soc_register_codec(&i2c->dev, 1046f0fba2adSLiam Girdwood &soc_codec_dev_wm8955, &wm8955_dai, 1); 1047*95860fdfSMark Brown if (ret != 0) 1048*95860fdfSMark Brown goto err; 1049ba5c88d0SMark Brown 1050f0fba2adSLiam Girdwood return ret; 1051*95860fdfSMark Brown 1052*95860fdfSMark Brown err: 1053*95860fdfSMark Brown regmap_exit(wm8955->regmap); 1054*95860fdfSMark Brown return ret; 1055b35a28afSMark Brown } 1056b35a28afSMark Brown 1057b35a28afSMark Brown static __devexit int wm8955_i2c_remove(struct i2c_client *client) 1058b35a28afSMark Brown { 1059*95860fdfSMark Brown struct wm8955_priv *wm8955 = i2c_get_clientdata(client); 1060*95860fdfSMark Brown 1061f0fba2adSLiam Girdwood snd_soc_unregister_codec(&client->dev); 1062*95860fdfSMark Brown regmap_exit(wm8955->regmap); 1063*95860fdfSMark Brown 1064b35a28afSMark Brown return 0; 1065b35a28afSMark Brown } 1066b35a28afSMark Brown 1067b35a28afSMark Brown static const struct i2c_device_id wm8955_i2c_id[] = { 1068b35a28afSMark Brown { "wm8955", 0 }, 1069b35a28afSMark Brown { } 1070b35a28afSMark Brown }; 1071b35a28afSMark Brown MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); 1072b35a28afSMark Brown 1073b35a28afSMark Brown static struct i2c_driver wm8955_i2c_driver = { 1074b35a28afSMark Brown .driver = { 1075091edccfSMark Brown .name = "wm8955", 1076b35a28afSMark Brown .owner = THIS_MODULE, 1077b35a28afSMark Brown }, 1078b35a28afSMark Brown .probe = wm8955_i2c_probe, 1079b35a28afSMark Brown .remove = __devexit_p(wm8955_i2c_remove), 1080b35a28afSMark Brown .id_table = wm8955_i2c_id, 1081b35a28afSMark Brown }; 1082b35a28afSMark Brown 1083b35a28afSMark Brown static int __init wm8955_modinit(void) 1084b35a28afSMark Brown { 1085f0fba2adSLiam Girdwood int ret = 0; 1086b35a28afSMark Brown ret = i2c_add_driver(&wm8955_i2c_driver); 1087b35a28afSMark Brown if (ret != 0) { 1088b35a28afSMark Brown printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n", 1089b35a28afSMark Brown ret); 1090b35a28afSMark Brown } 1091f0fba2adSLiam Girdwood return ret; 1092b35a28afSMark Brown } 1093b35a28afSMark Brown module_init(wm8955_modinit); 1094b35a28afSMark Brown 1095b35a28afSMark Brown static void __exit wm8955_exit(void) 1096b35a28afSMark Brown { 1097b35a28afSMark Brown i2c_del_driver(&wm8955_i2c_driver); 1098b35a28afSMark Brown } 1099b35a28afSMark Brown module_exit(wm8955_exit); 1100b35a28afSMark Brown 1101b35a28afSMark Brown MODULE_DESCRIPTION("ASoC WM8955 driver"); 1102b35a28afSMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 1103b35a28afSMark Brown MODULE_LICENSE("GPL"); 1104