Commit 86ed3669f068b514ab85ffd548456a342b3fb8d3

Authored by Mark Brown
1 parent b4852b793a

ASoC: WM9081 mono DAC with integrated 2.6W class AB/D amplifier driver

The WM9081 is designed to provide high power output at low distortion
levels in space-constrained portable applications.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

Showing 5 changed files with 2350 additions and 0 deletions Side-by-side Diff

include/sound/wm9081.h
  1 +/*
  2 + * linux/sound/wm9081.h -- Platform data for WM9081
  3 + *
  4 + * Copyright 2009 Wolfson Microelectronics. PLC.
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License version 2 as
  8 + * published by the Free Software Foundation.
  9 + */
  10 +
  11 +#ifndef __LINUX_SND_WM_9081_H
  12 +#define __LINUX_SND_WM_9081_H
  13 +
  14 +struct wm9081_retune_mobile_setting {
  15 + const char *name;
  16 + unsigned int rate;
  17 + u16 config[20];
  18 +};
  19 +
  20 +struct wm9081_retune_mobile_config {
  21 + struct wm9081_retune_mobile_setting *configs;
  22 + int num_configs;
  23 +};
  24 +
  25 +#endif
sound/soc/codecs/Kconfig
... ... @@ -40,6 +40,7 @@
40 40 select SND_SOC_WM8971 if I2C
41 41 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
42 42 select SND_SOC_WM8990 if I2C
  43 + select SND_SOC_WM9081 if I2C
43 44 select SND_SOC_WM9705 if SND_SOC_AC97_BUS
44 45 select SND_SOC_WM9712 if SND_SOC_AC97_BUS
45 46 select SND_SOC_WM9713 if SND_SOC_AC97_BUS
... ... @@ -154,6 +155,9 @@
154 155 tristate
155 156  
156 157 config SND_SOC_WM8990
  158 + tristate
  159 +
  160 +config SND_SOC_WM9081
157 161 tristate
158 162  
159 163 config SND_SOC_WM9705
sound/soc/codecs/Makefile
... ... @@ -28,6 +28,7 @@
28 28 snd-soc-wm8971-objs := wm8971.o
29 29 snd-soc-wm8988-objs := wm8988.o
30 30 snd-soc-wm8990-objs := wm8990.o
  31 +snd-soc-wm9081-objs := wm9081.o
31 32 snd-soc-wm9705-objs := wm9705.o
32 33 snd-soc-wm9712-objs := wm9712.o
33 34 snd-soc-wm9713-objs := wm9713.o
... ... @@ -62,6 +63,7 @@
62 63 obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
63 64 obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
64 65 obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
  66 +obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
65 67 obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
66 68 obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
67 69 obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
sound/soc/codecs/wm9081.c
Changes suppressed. Click to show
  1 +/*
  2 + * wm9081.c -- WM9081 ALSA SoC Audio driver
  3 + *
  4 + * Author: Mark Brown
  5 + *
  6 + * Copyright 2009 Wolfson Microelectronics plc
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + *
  12 + */
  13 +
  14 +#include <linux/module.h>
  15 +#include <linux/moduleparam.h>
  16 +#include <linux/init.h>
  17 +#include <linux/delay.h>
  18 +#include <linux/pm.h>
  19 +#include <linux/i2c.h>
  20 +#include <linux/platform_device.h>
  21 +#include <sound/core.h>
  22 +#include <sound/pcm.h>
  23 +#include <sound/pcm_params.h>
  24 +#include <sound/soc.h>
  25 +#include <sound/soc-dapm.h>
  26 +#include <sound/initval.h>
  27 +#include <sound/tlv.h>
  28 +
  29 +#include <sound/wm9081.h>
  30 +#include "wm9081.h"
  31 +
  32 +static u16 wm9081_reg_defaults[] = {
  33 + 0x0000, /* R0 - Software Reset */
  34 + 0x0000, /* R1 */
  35 + 0x00B9, /* R2 - Analogue Lineout */
  36 + 0x00B9, /* R3 - Analogue Speaker PGA */
  37 + 0x0001, /* R4 - VMID Control */
  38 + 0x0068, /* R5 - Bias Control 1 */
  39 + 0x0000, /* R6 */
  40 + 0x0000, /* R7 - Analogue Mixer */
  41 + 0x0000, /* R8 - Anti Pop Control */
  42 + 0x01DB, /* R9 - Analogue Speaker 1 */
  43 + 0x0018, /* R10 - Analogue Speaker 2 */
  44 + 0x0180, /* R11 - Power Management */
  45 + 0x0000, /* R12 - Clock Control 1 */
  46 + 0x0038, /* R13 - Clock Control 2 */
  47 + 0x4000, /* R14 - Clock Control 3 */
  48 + 0x0000, /* R15 */
  49 + 0x0000, /* R16 - FLL Control 1 */
  50 + 0x0200, /* R17 - FLL Control 2 */
  51 + 0x0000, /* R18 - FLL Control 3 */
  52 + 0x0204, /* R19 - FLL Control 4 */
  53 + 0x0000, /* R20 - FLL Control 5 */
  54 + 0x0000, /* R21 */
  55 + 0x0000, /* R22 - Audio Interface 1 */
  56 + 0x0002, /* R23 - Audio Interface 2 */
  57 + 0x0008, /* R24 - Audio Interface 3 */
  58 + 0x0022, /* R25 - Audio Interface 4 */
  59 + 0x0000, /* R26 - Interrupt Status */
  60 + 0x0006, /* R27 - Interrupt Status Mask */
  61 + 0x0000, /* R28 - Interrupt Polarity */
  62 + 0x0000, /* R29 - Interrupt Control */
  63 + 0x00C0, /* R30 - DAC Digital 1 */
  64 + 0x0008, /* R31 - DAC Digital 2 */
  65 + 0x09AF, /* R32 - DRC 1 */
  66 + 0x4201, /* R33 - DRC 2 */
  67 + 0x0000, /* R34 - DRC 3 */
  68 + 0x0000, /* R35 - DRC 4 */
  69 + 0x0000, /* R36 */
  70 + 0x0000, /* R37 */
  71 + 0x0000, /* R38 - Write Sequencer 1 */
  72 + 0x0000, /* R39 - Write Sequencer 2 */
  73 + 0x0002, /* R40 - MW Slave 1 */
  74 + 0x0000, /* R41 */
  75 + 0x0000, /* R42 - EQ 1 */
  76 + 0x0000, /* R43 - EQ 2 */
  77 + 0x0FCA, /* R44 - EQ 3 */
  78 + 0x0400, /* R45 - EQ 4 */
  79 + 0x00B8, /* R46 - EQ 5 */
  80 + 0x1EB5, /* R47 - EQ 6 */
  81 + 0xF145, /* R48 - EQ 7 */
  82 + 0x0B75, /* R49 - EQ 8 */
  83 + 0x01C5, /* R50 - EQ 9 */
  84 + 0x169E, /* R51 - EQ 10 */
  85 + 0xF829, /* R52 - EQ 11 */
  86 + 0x07AD, /* R53 - EQ 12 */
  87 + 0x1103, /* R54 - EQ 13 */
  88 + 0x1C58, /* R55 - EQ 14 */
  89 + 0xF373, /* R56 - EQ 15 */
  90 + 0x0A54, /* R57 - EQ 16 */
  91 + 0x0558, /* R58 - EQ 17 */
  92 + 0x0564, /* R59 - EQ 18 */
  93 + 0x0559, /* R60 - EQ 19 */
  94 + 0x4000, /* R61 - EQ 20 */
  95 +};
  96 +
  97 +static struct {
  98 + int ratio;
  99 + int clk_sys_rate;
  100 +} clk_sys_rates[] = {
  101 + { 64, 0 },
  102 + { 128, 1 },
  103 + { 192, 2 },
  104 + { 256, 3 },
  105 + { 384, 4 },
  106 + { 512, 5 },
  107 + { 768, 6 },
  108 + { 1024, 7 },
  109 + { 1408, 8 },
  110 + { 1536, 9 },
  111 +};
  112 +
  113 +static struct {
  114 + int rate;
  115 + int sample_rate;
  116 +} sample_rates[] = {
  117 + { 8000, 0 },
  118 + { 11025, 1 },
  119 + { 12000, 2 },
  120 + { 16000, 3 },
  121 + { 22050, 4 },
  122 + { 24000, 5 },
  123 + { 32000, 6 },
  124 + { 44100, 7 },
  125 + { 48000, 8 },
  126 + { 88200, 9 },
  127 + { 96000, 10 },
  128 +};
  129 +
  130 +static struct {
  131 + int div; /* *10 due to .5s */
  132 + int bclk_div;
  133 +} bclk_divs[] = {
  134 + { 10, 0 },
  135 + { 15, 1 },
  136 + { 20, 2 },
  137 + { 30, 3 },
  138 + { 40, 4 },
  139 + { 50, 5 },
  140 + { 55, 6 },
  141 + { 60, 7 },
  142 + { 80, 8 },
  143 + { 100, 9 },
  144 + { 110, 10 },
  145 + { 120, 11 },
  146 + { 160, 12 },
  147 + { 200, 13 },
  148 + { 220, 14 },
  149 + { 240, 15 },
  150 + { 250, 16 },
  151 + { 300, 17 },
  152 + { 320, 18 },
  153 + { 440, 19 },
  154 + { 480, 20 },
  155 +};
  156 +
  157 +struct wm9081_priv {
  158 + struct snd_soc_codec codec;
  159 + u16 reg_cache[WM9081_MAX_REGISTER + 1];
  160 + int sysclk_source;
  161 + int mclk_rate;
  162 + int sysclk_rate;
  163 + int fs;
  164 + int bclk;
  165 + int master;
  166 + int fll_fref;
  167 + int fll_fout;
  168 + struct wm9081_retune_mobile_config *retune;
  169 +};
  170 +
  171 +static int wm9081_reg_is_volatile(int reg)
  172 +{
  173 + switch (reg) {
  174 + default:
  175 + return 0;
  176 + }
  177 +}
  178 +
  179 +static unsigned int wm9081_read_reg_cache(struct snd_soc_codec *codec,
  180 + unsigned int reg)
  181 +{
  182 + u16 *cache = codec->reg_cache;
  183 + BUG_ON(reg > WM9081_MAX_REGISTER);
  184 + return cache[reg];
  185 +}
  186 +
  187 +static unsigned int wm9081_read_hw(struct snd_soc_codec *codec, u8 reg)
  188 +{
  189 + struct i2c_msg xfer[2];
  190 + u16 data;
  191 + int ret;
  192 + struct i2c_client *client = codec->control_data;
  193 +
  194 + BUG_ON(reg > WM9081_MAX_REGISTER);
  195 +
  196 + /* Write register */
  197 + xfer[0].addr = client->addr;
  198 + xfer[0].flags = 0;
  199 + xfer[0].len = 1;
  200 + xfer[0].buf = &reg;
  201 +
  202 + /* Read data */
  203 + xfer[1].addr = client->addr;
  204 + xfer[1].flags = I2C_M_RD;
  205 + xfer[1].len = 2;
  206 + xfer[1].buf = (u8 *)&data;
  207 +
  208 + ret = i2c_transfer(client->adapter, xfer, 2);
  209 + if (ret != 2) {
  210 + dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
  211 + return 0;
  212 + }
  213 +
  214 + return (data >> 8) | ((data & 0xff) << 8);
  215 +}
  216 +
  217 +static unsigned int wm9081_read(struct snd_soc_codec *codec, unsigned int reg)
  218 +{
  219 + if (wm9081_reg_is_volatile(reg))
  220 + return wm9081_read_hw(codec, reg);
  221 + else
  222 + return wm9081_read_reg_cache(codec, reg);
  223 +}
  224 +
  225 +static int wm9081_write(struct snd_soc_codec *codec, unsigned int reg,
  226 + unsigned int value)
  227 +{
  228 + u16 *cache = codec->reg_cache;
  229 + u8 data[3];
  230 +
  231 + BUG_ON(reg > WM9081_MAX_REGISTER);
  232 +
  233 + if (!wm9081_reg_is_volatile(reg))
  234 + cache[reg] = value;
  235 +
  236 + data[0] = reg;
  237 + data[1] = value >> 8;
  238 + data[2] = value & 0x00ff;
  239 +
  240 + if (codec->hw_write(codec->control_data, data, 3) == 3)
  241 + return 0;
  242 + else
  243 + return -EIO;
  244 +}
  245 +
  246 +static int wm9081_reset(struct snd_soc_codec *codec)
  247 +{
  248 + return wm9081_write(codec, WM9081_SOFTWARE_RESET, 0);
  249 +}
  250 +
  251 +static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
  252 +static const DECLARE_TLV_DB_SCALE(drc_out_tlv, -2250, 75, 0);
  253 +static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
  254 +static unsigned int drc_max_tlv[] = {
  255 + TLV_DB_RANGE_HEAD(4),
  256 + 0, 0, TLV_DB_SCALE_ITEM(1200, 0, 0),
  257 + 1, 1, TLV_DB_SCALE_ITEM(1800, 0, 0),
  258 + 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
  259 + 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
  260 +};
  261 +static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
  262 +static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -300, 50, 0);
  263 +
  264 +static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
  265 +
  266 +static const DECLARE_TLV_DB_SCALE(in_tlv, -600, 600, 0);
  267 +static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
  268 +static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
  269 +
  270 +static const char *drc_high_text[] = {
  271 + "1",
  272 + "1/2",
  273 + "1/4",
  274 + "1/8",
  275 + "1/16",
  276 + "0",
  277 +};
  278 +
  279 +static const struct soc_enum drc_high =
  280 + SOC_ENUM_SINGLE(WM9081_DRC_3, 3, 6, drc_high_text);
  281 +
  282 +static const char *drc_low_text[] = {
  283 + "1",
  284 + "1/2",
  285 + "1/4",
  286 + "1/8",
  287 + "0",
  288 +};
  289 +
  290 +static const struct soc_enum drc_low =
  291 + SOC_ENUM_SINGLE(WM9081_DRC_3, 0, 5, drc_low_text);
  292 +
  293 +static const char *drc_atk_text[] = {
  294 + "181us",
  295 + "181us",
  296 + "363us",
  297 + "726us",
  298 + "1.45ms",
  299 + "2.9ms",
  300 + "5.8ms",
  301 + "11.6ms",
  302 + "23.2ms",
  303 + "46.4ms",
  304 + "92.8ms",
  305 + "185.6ms",
  306 +};
  307 +
  308 +static const struct soc_enum drc_atk =
  309 + SOC_ENUM_SINGLE(WM9081_DRC_2, 12, 12, drc_atk_text);
  310 +
  311 +static const char *drc_dcy_text[] = {
  312 + "186ms",
  313 + "372ms",
  314 + "743ms",
  315 + "1.49s",
  316 + "2.97s",
  317 + "5.94s",
  318 + "11.89s",
  319 + "23.78s",
  320 + "47.56s",
  321 +};
  322 +
  323 +static const struct soc_enum drc_dcy =
  324 + SOC_ENUM_SINGLE(WM9081_DRC_2, 8, 9, drc_dcy_text);
  325 +
  326 +static const char *drc_qr_dcy_text[] = {
  327 + "0.725ms",
  328 + "1.45ms",
  329 + "5.8ms",
  330 +};
  331 +
  332 +static const struct soc_enum drc_qr_dcy =
  333 + SOC_ENUM_SINGLE(WM9081_DRC_2, 4, 3, drc_qr_dcy_text);
  334 +
  335 +static const char *dac_deemph_text[] = {
  336 + "None",
  337 + "32kHz",
  338 + "44.1kHz",
  339 + "48kHz",
  340 +};
  341 +
  342 +static const struct soc_enum dac_deemph =
  343 + SOC_ENUM_SINGLE(WM9081_DAC_DIGITAL_2, 1, 4, dac_deemph_text);
  344 +
  345 +static const char *speaker_mode_text[] = {
  346 + "Class D",
  347 + "Class AB",
  348 +};
  349 +
  350 +static const struct soc_enum speaker_mode =
  351 + SOC_ENUM_SINGLE(WM9081_ANALOGUE_SPEAKER_2, 6, 2, speaker_mode_text);
  352 +
  353 +static int speaker_mode_get(struct snd_kcontrol *kcontrol,
  354 + struct snd_ctl_elem_value *ucontrol)
  355 +{
  356 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  357 + unsigned int reg;
  358 +
  359 + reg = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_2);
  360 + if (reg & WM9081_SPK_MODE)
  361 + ucontrol->value.integer.value[0] = 1;
  362 + else
  363 + ucontrol->value.integer.value[0] = 0;
  364 +
  365 + return 0;
  366 +}
  367 +
  368 +/*
  369 + * Stop any attempts to change speaker mode while the speaker is enabled.
  370 + *
  371 + * We also have some special anti-pop controls dependant on speaker
  372 + * mode which must be changed along with the mode.
  373 + */
  374 +static int speaker_mode_put(struct snd_kcontrol *kcontrol,
  375 + struct snd_ctl_elem_value *ucontrol)
  376 +{
  377 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
  378 + unsigned int reg_pwr = wm9081_read(codec, WM9081_POWER_MANAGEMENT);
  379 + unsigned int reg2 = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_2);
  380 +
  381 + /* Are we changing anything? */
  382 + if (ucontrol->value.integer.value[0] ==
  383 + ((reg2 & WM9081_SPK_MODE) != 0))
  384 + return 0;
  385 +
  386 + /* Don't try to change modes while enabled */
  387 + if (reg_pwr & WM9081_SPK_ENA)
  388 + return -EINVAL;
  389 +
  390 + if (ucontrol->value.integer.value[0]) {
  391 + /* Class AB */
  392 + reg2 &= ~(WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL);
  393 + reg2 |= WM9081_SPK_MODE;
  394 + } else {
  395 + /* Class D */
  396 + reg2 |= WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL;
  397 + reg2 &= ~WM9081_SPK_MODE;
  398 + }
  399 +
  400 + wm9081_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2);
  401 +
  402 + return 0;
  403 +}
  404 +
  405 +static const struct snd_kcontrol_new wm9081_snd_controls[] = {
  406 +SOC_SINGLE_TLV("IN1 Volume", WM9081_ANALOGUE_MIXER, 1, 1, 1, in_tlv),
  407 +SOC_SINGLE_TLV("IN2 Volume", WM9081_ANALOGUE_MIXER, 3, 1, 1, in_tlv),
  408 +
  409 +SOC_SINGLE_TLV("Playback Volume", WM9081_DAC_DIGITAL_1, 1, 96, 0, dac_tlv),
  410 +
  411 +SOC_SINGLE("LINEOUT Switch", WM9081_ANALOGUE_LINEOUT, 7, 1, 1),
  412 +SOC_SINGLE("LINEOUT ZC Switch", WM9081_ANALOGUE_LINEOUT, 6, 1, 0),
  413 +SOC_SINGLE_TLV("LINEOUT Volume", WM9081_ANALOGUE_LINEOUT, 0, 63, 0, out_tlv),
  414 +
  415 +SOC_SINGLE("DRC Switch", WM9081_DRC_1, 15, 1, 0),
  416 +SOC_ENUM("DRC High Slope", drc_high),
  417 +SOC_ENUM("DRC Low Slope", drc_low),
  418 +SOC_SINGLE_TLV("DRC Input Volume", WM9081_DRC_4, 5, 60, 1, drc_in_tlv),
  419 +SOC_SINGLE_TLV("DRC Output Volume", WM9081_DRC_4, 0, 30, 1, drc_out_tlv),
  420 +SOC_SINGLE_TLV("DRC Minimum Volume", WM9081_DRC_2, 2, 3, 1, drc_min_tlv),
  421 +SOC_SINGLE_TLV("DRC Maximum Volume", WM9081_DRC_2, 0, 3, 0, drc_max_tlv),
  422 +SOC_ENUM("DRC Attack", drc_atk),
  423 +SOC_ENUM("DRC Decay", drc_dcy),
  424 +SOC_SINGLE("DRC Quick Release Switch", WM9081_DRC_1, 2, 1, 0),
  425 +SOC_SINGLE_TLV("DRC Quick Release Volume", WM9081_DRC_2, 6, 3, 0, drc_qr_tlv),
  426 +SOC_ENUM("DRC Quick Release Decay", drc_qr_dcy),
  427 +SOC_SINGLE_TLV("DRC Startup Volume", WM9081_DRC_1, 6, 18, 0, drc_startup_tlv),
  428 +
  429 +SOC_SINGLE("EQ Switch", WM9081_EQ_1, 0, 1, 0),
  430 +
  431 +SOC_SINGLE("Speaker DC Volume", WM9081_ANALOGUE_SPEAKER_1, 3, 5, 0),
  432 +SOC_SINGLE("Speaker AC Volume", WM9081_ANALOGUE_SPEAKER_1, 0, 5, 0),
  433 +SOC_SINGLE("Speaker Switch", WM9081_ANALOGUE_SPEAKER_PGA, 7, 1, 1),
  434 +SOC_SINGLE("Speaker ZC Switch", WM9081_ANALOGUE_SPEAKER_PGA, 6, 1, 0),
  435 +SOC_SINGLE_TLV("Speaker Volume", WM9081_ANALOGUE_SPEAKER_PGA, 0, 63, 0,
  436 + out_tlv),
  437 +SOC_ENUM("DAC Deemphasis", dac_deemph),
  438 +SOC_ENUM_EXT("Speaker Mode", speaker_mode, speaker_mode_get, speaker_mode_put),
  439 +};
  440 +
  441 +static const struct snd_kcontrol_new wm9081_eq_controls[] = {
  442 +SOC_SINGLE_TLV("EQ1 Volume", WM9081_EQ_1, 11, 24, 0, eq_tlv),
  443 +SOC_SINGLE_TLV("EQ2 Volume", WM9081_EQ_1, 6, 24, 0, eq_tlv),
  444 +SOC_SINGLE_TLV("EQ3 Volume", WM9081_EQ_1, 1, 24, 0, eq_tlv),
  445 +SOC_SINGLE_TLV("EQ4 Volume", WM9081_EQ_2, 11, 24, 0, eq_tlv),
  446 +SOC_SINGLE_TLV("EQ5 Volume", WM9081_EQ_2, 6, 24, 0, eq_tlv),
  447 +};
  448 +
  449 +static const struct snd_kcontrol_new mixer[] = {
  450 +SOC_DAPM_SINGLE("IN1 Switch", WM9081_ANALOGUE_MIXER, 0, 1, 0),
  451 +SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0),
  452 +SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0),
  453 +};
  454 +
  455 +static int speaker_event(struct snd_soc_dapm_widget *w,
  456 + struct snd_kcontrol *kcontrol, int event)
  457 +{
  458 + struct snd_soc_codec *codec = w->codec;
  459 + unsigned int reg = wm9081_read(codec, WM9081_POWER_MANAGEMENT);
  460 +
  461 + switch (event) {
  462 + case SND_SOC_DAPM_POST_PMU:
  463 + reg |= WM9081_SPK_ENA;
  464 + break;
  465 +
  466 + case SND_SOC_DAPM_PRE_PMD:
  467 + reg &= ~WM9081_SPK_ENA;
  468 + break;
  469 + }
  470 +
  471 + wm9081_write(codec, WM9081_POWER_MANAGEMENT, reg);
  472 +
  473 + return 0;
  474 +}
  475 +
  476 +struct _fll_div {
  477 + u16 fll_fratio;
  478 + u16 fll_outdiv;
  479 + u16 fll_clk_ref_div;
  480 + u16 n;
  481 + u16 k;
  482 +};
  483 +
  484 +/* The size in bits of the FLL divide multiplied by 10
  485 + * to allow rounding later */
  486 +#define FIXED_FLL_SIZE ((1 << 16) * 10)
  487 +
  488 +static struct {
  489 + unsigned int min;
  490 + unsigned int max;
  491 + u16 fll_fratio;
  492 + int ratio;
  493 +} fll_fratios[] = {
  494 + { 0, 64000, 4, 16 },
  495 + { 64000, 128000, 3, 8 },
  496 + { 128000, 256000, 2, 4 },
  497 + { 256000, 1000000, 1, 2 },
  498 + { 1000000, 13500000, 0, 1 },
  499 +};
  500 +
  501 +static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
  502 + unsigned int Fout)
  503 +{
  504 + u64 Kpart;
  505 + unsigned int K, Ndiv, Nmod, target;
  506 + unsigned int div;
  507 + int i;
  508 +
  509 + /* Fref must be <=13.5MHz */
  510 + div = 1;
  511 + while ((Fref / div) > 13500000) {
  512 + div *= 2;
  513 +
  514 + if (div > 8) {
  515 + pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
  516 + Fref);
  517 + return -EINVAL;
  518 + }
  519 + }
  520 + fll_div->fll_clk_ref_div = div / 2;
  521 +
  522 + pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
  523 +
  524 + /* Apply the division for our remaining calculations */
  525 + Fref /= div;
  526 +
  527 + /* Fvco should be 90-100MHz; don't check the upper bound */
  528 + div = 0;
  529 + target = Fout * 2;
  530 + while (target < 90000000) {
  531 + div++;
  532 + target *= 2;
  533 + if (div > 7) {
  534 + pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
  535 + Fout);
  536 + return -EINVAL;
  537 + }
  538 + }
  539 + fll_div->fll_outdiv = div;
  540 +
  541 + pr_debug("Fvco=%dHz\n", target);
  542 +
  543 + /* Find an appropraite FLL_FRATIO and factor it out of the target */
  544 + for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
  545 + if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
  546 + fll_div->fll_fratio = fll_fratios[i].fll_fratio;
  547 + target /= fll_fratios[i].ratio;
  548 + break;
  549 + }
  550 + }
  551 + if (i == ARRAY_SIZE(fll_fratios)) {
  552 + pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
  553 + return -EINVAL;
  554 + }
  555 +
  556 + /* Now, calculate N.K */
  557 + Ndiv = target / Fref;
  558 +
  559 + fll_div->n = Ndiv;
  560 + Nmod = target % Fref;
  561 + pr_debug("Nmod=%d\n", Nmod);
  562 +
  563 + /* Calculate fractional part - scale up so we can round. */
  564 + Kpart = FIXED_FLL_SIZE * (long long)Nmod;
  565 +
  566 + do_div(Kpart, Fref);
  567 +
  568 + K = Kpart & 0xFFFFFFFF;
  569 +
  570 + if ((K % 10) >= 5)
  571 + K += 5;
  572 +
  573 + /* Move down to proper range now rounding is done */
  574 + fll_div->k = K / 10;
  575 +
  576 + pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
  577 + fll_div->n, fll_div->k,
  578 + fll_div->fll_fratio, fll_div->fll_outdiv,
  579 + fll_div->fll_clk_ref_div);
  580 +
  581 + return 0;
  582 +}
  583 +
  584 +static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id,
  585 + unsigned int Fref, unsigned int Fout)
  586 +{
  587 + struct wm9081_priv *wm9081 = codec->private_data;
  588 + u16 reg1, reg4, reg5;
  589 + struct _fll_div fll_div;
  590 + int ret;
  591 + int clk_sys_reg;
  592 +
  593 + /* Any change? */
  594 + if (Fref == wm9081->fll_fref && Fout == wm9081->fll_fout)
  595 + return 0;
  596 +
  597 + /* Disable the FLL */
  598 + if (Fout == 0) {
  599 + dev_dbg(codec->dev, "FLL disabled\n");
  600 + wm9081->fll_fref = 0;
  601 + wm9081->fll_fout = 0;
  602 +
  603 + return 0;
  604 + }
  605 +
  606 + ret = fll_factors(&fll_div, Fref, Fout);
  607 + if (ret != 0)
  608 + return ret;
  609 +
  610 + reg5 = wm9081_read(codec, WM9081_FLL_CONTROL_5);
  611 + reg5 &= ~WM9081_FLL_CLK_SRC_MASK;
  612 +
  613 + switch (fll_id) {
  614 + case WM9081_SYSCLK_FLL_MCLK:
  615 + reg5 |= 0x1;
  616 + break;
  617 +
  618 + default:
  619 + dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id);
  620 + return -EINVAL;
  621 + }
  622 +
  623 + /* Disable CLK_SYS while we reconfigure */
  624 + clk_sys_reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_3);
  625 + if (clk_sys_reg & WM9081_CLK_SYS_ENA)
  626 + wm9081_write(codec, WM9081_CLOCK_CONTROL_3,
  627 + clk_sys_reg & ~WM9081_CLK_SYS_ENA);
  628 +
  629 + /* Any FLL configuration change requires that the FLL be
  630 + * disabled first. */
  631 + reg1 = wm9081_read(codec, WM9081_FLL_CONTROL_1);
  632 + reg1 &= ~WM9081_FLL_ENA;
  633 + wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1);
  634 +
  635 + /* Apply the configuration */
  636 + if (fll_div.k)
  637 + reg1 |= WM9081_FLL_FRAC_MASK;
  638 + else
  639 + reg1 &= ~WM9081_FLL_FRAC_MASK;
  640 + wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1);
  641 +
  642 + wm9081_write(codec, WM9081_FLL_CONTROL_2,
  643 + (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) |
  644 + (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT));
  645 + wm9081_write(codec, WM9081_FLL_CONTROL_3, fll_div.k);
  646 +
  647 + reg4 = wm9081_read(codec, WM9081_FLL_CONTROL_4);
  648 + reg4 &= ~WM9081_FLL_N_MASK;
  649 + reg4 |= fll_div.n << WM9081_FLL_N_SHIFT;
  650 + wm9081_write(codec, WM9081_FLL_CONTROL_4, reg4);
  651 +
  652 + reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK;
  653 + reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT;
  654 + wm9081_write(codec, WM9081_FLL_CONTROL_5, reg5);
  655 +
  656 + /* Enable the FLL */
  657 + wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA);
  658 +
  659 + /* Then bring CLK_SYS up again if it was disabled */
  660 + if (clk_sys_reg & WM9081_CLK_SYS_ENA)
  661 + wm9081_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg);
  662 +
  663 + dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
  664 +
  665 + wm9081->fll_fref = Fref;
  666 + wm9081->fll_fout = Fout;
  667 +
  668 + return 0;
  669 +}
  670 +
  671 +static int configure_clock(struct snd_soc_codec *codec)
  672 +{
  673 + struct wm9081_priv *wm9081 = codec->private_data;
  674 + int new_sysclk, i, target;
  675 + unsigned int reg;
  676 + int ret = 0;
  677 + int mclkdiv = 0;
  678 + int fll = 0;
  679 +
  680 + switch (wm9081->sysclk_source) {
  681 + case WM9081_SYSCLK_MCLK:
  682 + if (wm9081->mclk_rate > 12225000) {
  683 + mclkdiv = 1;
  684 + wm9081->sysclk_rate = wm9081->mclk_rate / 2;
  685 + } else {
  686 + wm9081->sysclk_rate = wm9081->mclk_rate;
  687 + }
  688 + wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK, 0, 0);
  689 + break;
  690 +
  691 + case WM9081_SYSCLK_FLL_MCLK:
  692 + /* If we have a sample rate calculate a CLK_SYS that
  693 + * gives us a suitable DAC configuration, plus BCLK.
  694 + * Ideally we would check to see if we can clock
  695 + * directly from MCLK and only use the FLL if this is
  696 + * not the case, though care must be taken with free
  697 + * running mode.
  698 + */
  699 + if (wm9081->master && wm9081->bclk) {
  700 + /* Make sure we can generate CLK_SYS and BCLK
  701 + * and that we've got 3MHz for optimal
  702 + * performance. */
  703 + for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
  704 + target = wm9081->fs * clk_sys_rates[i].ratio;
  705 + if (target >= wm9081->bclk &&
  706 + target > 3000000)
  707 + new_sysclk = target;
  708 + }
  709 + } else if (wm9081->fs) {
  710 + for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
  711 + new_sysclk = clk_sys_rates[i].ratio
  712 + * wm9081->fs;
  713 + if (new_sysclk > 3000000)
  714 + break;
  715 + }
  716 + } else {
  717 + new_sysclk = 12288000;
  718 + }
  719 +
  720 + ret = wm9081_set_fll(codec, WM9081_SYSCLK_FLL_MCLK,
  721 + wm9081->mclk_rate, new_sysclk);
  722 + if (ret == 0) {
  723 + wm9081->sysclk_rate = new_sysclk;
  724 +
  725 + /* Switch SYSCLK over to FLL */
  726 + fll = 1;
  727 + } else {
  728 + wm9081->sysclk_rate = wm9081->mclk_rate;
  729 + }
  730 + break;
  731 +
  732 + default:
  733 + return -EINVAL;
  734 + }
  735 +
  736 + reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_1);
  737 + if (mclkdiv)
  738 + reg |= WM9081_MCLKDIV2;
  739 + else
  740 + reg &= ~WM9081_MCLKDIV2;
  741 + wm9081_write(codec, WM9081_CLOCK_CONTROL_1, reg);
  742 +
  743 + reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_3);
  744 + if (fll)
  745 + reg |= WM9081_CLK_SRC_SEL;
  746 + else
  747 + reg &= ~WM9081_CLK_SRC_SEL;
  748 + wm9081_write(codec, WM9081_CLOCK_CONTROL_3, reg);
  749 +
  750 + dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate);
  751 +
  752 + return ret;
  753 +}
  754 +
  755 +static int clk_sys_event(struct snd_soc_dapm_widget *w,
  756 + struct snd_kcontrol *kcontrol, int event)
  757 +{
  758 + struct snd_soc_codec *codec = w->codec;
  759 + struct wm9081_priv *wm9081 = codec->private_data;
  760 +
  761 + /* This should be done on init() for bypass paths */
  762 + switch (wm9081->sysclk_source) {
  763 + case WM9081_SYSCLK_MCLK:
  764 + dev_dbg(codec->dev, "Using %dHz MCLK\n", wm9081->mclk_rate);
  765 + break;
  766 + case WM9081_SYSCLK_FLL_MCLK:
  767 + dev_dbg(codec->dev, "Using %dHz MCLK with FLL\n",
  768 + wm9081->mclk_rate);
  769 + break;
  770 + default:
  771 + dev_err(codec->dev, "System clock not configured\n");
  772 + return -EINVAL;
  773 + }
  774 +
  775 + switch (event) {
  776 + case SND_SOC_DAPM_PRE_PMU:
  777 + configure_clock(codec);
  778 + break;
  779 +
  780 + case SND_SOC_DAPM_POST_PMD:
  781 + /* Disable the FLL if it's running */
  782 + wm9081_set_fll(codec, 0, 0, 0);
  783 + break;
  784 + }
  785 +
  786 + return 0;
  787 +}
  788 +
  789 +static const struct snd_soc_dapm_widget wm9081_dapm_widgets[] = {
  790 +SND_SOC_DAPM_INPUT("IN1"),
  791 +SND_SOC_DAPM_INPUT("IN2"),
  792 +
  793 +SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM9081_POWER_MANAGEMENT, 0, 0),
  794 +
  795 +SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0,
  796 + mixer, ARRAY_SIZE(mixer)),
  797 +
  798 +SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0),
  799 +
  800 +SND_SOC_DAPM_PGA_E("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0,
  801 + speaker_event,
  802 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
  803 +
  804 +SND_SOC_DAPM_OUTPUT("LINEOUT"),
  805 +SND_SOC_DAPM_OUTPUT("SPKN"),
  806 +SND_SOC_DAPM_OUTPUT("SPKP"),
  807 +
  808 +SND_SOC_DAPM_SUPPLY("CLK_SYS", WM9081_CLOCK_CONTROL_3, 0, 0, clk_sys_event,
  809 + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
  810 +SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0),
  811 +SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
  812 +};
  813 +
  814 +
  815 +static const struct snd_soc_dapm_route audio_paths[] = {
  816 + { "DAC", NULL, "CLK_SYS" },
  817 + { "DAC", NULL, "CLK_DSP" },
  818 +
  819 + { "Mixer", "IN1 Switch", "IN1" },
  820 + { "Mixer", "IN2 Switch", "IN2" },
  821 + { "Mixer", "Playback Switch", "DAC" },
  822 +
  823 + { "LINEOUT PGA", NULL, "Mixer" },
  824 + { "LINEOUT PGA", NULL, "TOCLK" },
  825 + { "LINEOUT PGA", NULL, "CLK_SYS" },
  826 +
  827 + { "LINEOUT", NULL, "LINEOUT PGA" },
  828 +
  829 + { "Speaker PGA", NULL, "Mixer" },
  830 + { "Speaker PGA", NULL, "TOCLK" },
  831 + { "Speaker PGA", NULL, "CLK_SYS" },
  832 +
  833 + { "SPKN", NULL, "Speaker PGA" },
  834 + { "SPKP", NULL, "Speaker PGA" },
  835 +};
  836 +
  837 +static int wm9081_set_bias_level(struct snd_soc_codec *codec,
  838 + enum snd_soc_bias_level level)
  839 +{
  840 + u16 reg;
  841 +
  842 + switch (level) {
  843 + case SND_SOC_BIAS_ON:
  844 + break;
  845 +
  846 + case SND_SOC_BIAS_PREPARE:
  847 + /* VMID=2*40k */
  848 + reg = wm9081_read(codec, WM9081_VMID_CONTROL);
  849 + reg &= ~WM9081_VMID_SEL_MASK;
  850 + reg |= 0x2;
  851 + wm9081_write(codec, WM9081_VMID_CONTROL, reg);
  852 +
  853 + /* Normal bias current */
  854 + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
  855 + reg &= ~WM9081_STBY_BIAS_ENA;
  856 + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
  857 + break;
  858 +
  859 + case SND_SOC_BIAS_STANDBY:
  860 + /* Initial cold start */
  861 + if (codec->bias_level == SND_SOC_BIAS_OFF) {
  862 + /* Disable LINEOUT discharge */
  863 + reg = wm9081_read(codec, WM9081_ANTI_POP_CONTROL);
  864 + reg &= ~WM9081_LINEOUT_DISCH;
  865 + wm9081_write(codec, WM9081_ANTI_POP_CONTROL, reg);
  866 +
  867 + /* Select startup bias source */
  868 + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
  869 + reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
  870 + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
  871 +
  872 + /* VMID 2*4k; Soft VMID ramp enable */
  873 + reg = wm9081_read(codec, WM9081_VMID_CONTROL);
  874 + reg |= WM9081_VMID_RAMP | 0x6;
  875 + wm9081_write(codec, WM9081_VMID_CONTROL, reg);
  876 +
  877 + mdelay(100);
  878 +
  879 + /* Normal bias enable & soft start off */
  880 + reg |= WM9081_BIAS_ENA;
  881 + reg &= ~WM9081_VMID_RAMP;
  882 + wm9081_write(codec, WM9081_VMID_CONTROL, reg);
  883 +
  884 + /* Standard bias source */
  885 + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
  886 + reg &= ~WM9081_BIAS_SRC;
  887 + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
  888 + }
  889 +
  890 + /* VMID 2*240k */
  891 + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
  892 + reg &= ~WM9081_VMID_SEL_MASK;
  893 + reg |= 0x40;
  894 + wm9081_write(codec, WM9081_VMID_CONTROL, reg);
  895 +
  896 + /* Standby bias current on */
  897 + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
  898 + reg |= WM9081_STBY_BIAS_ENA;
  899 + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
  900 + break;
  901 +
  902 + case SND_SOC_BIAS_OFF:
  903 + /* Startup bias source */
  904 + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
  905 + reg |= WM9081_BIAS_SRC;
  906 + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
  907 +
  908 + /* Disable VMID and biases with soft ramping */
  909 + reg = wm9081_read(codec, WM9081_VMID_CONTROL);
  910 + reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
  911 + reg |= WM9081_VMID_RAMP;
  912 + wm9081_write(codec, WM9081_VMID_CONTROL, reg);
  913 +
  914 + /* Actively discharge LINEOUT */
  915 + reg = wm9081_read(codec, WM9081_ANTI_POP_CONTROL);
  916 + reg |= WM9081_LINEOUT_DISCH;
  917 + wm9081_write(codec, WM9081_ANTI_POP_CONTROL, reg);
  918 + break;
  919 + }
  920 +
  921 + codec->bias_level = level;
  922 +
  923 + return 0;
  924 +}
  925 +
  926 +static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
  927 + unsigned int fmt)
  928 +{
  929 + struct snd_soc_codec *codec = dai->codec;
  930 + struct wm9081_priv *wm9081 = codec->private_data;
  931 + unsigned int aif2 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_2);
  932 +
  933 + aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV |
  934 + WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK);
  935 +
  936 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  937 + case SND_SOC_DAIFMT_CBS_CFS:
  938 + wm9081->master = 0;
  939 + break;
  940 + case SND_SOC_DAIFMT_CBS_CFM:
  941 + aif2 |= WM9081_LRCLK_DIR;
  942 + wm9081->master = 1;
  943 + break;
  944 + case SND_SOC_DAIFMT_CBM_CFS:
  945 + aif2 |= WM9081_BCLK_DIR;
  946 + wm9081->master = 1;
  947 + break;
  948 + case SND_SOC_DAIFMT_CBM_CFM:
  949 + aif2 |= WM9081_LRCLK_DIR | WM9081_BCLK_DIR;
  950 + wm9081->master = 1;
  951 + break;
  952 + default:
  953 + return -EINVAL;
  954 + }
  955 +
  956 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  957 + case SND_SOC_DAIFMT_DSP_B:
  958 + aif2 |= WM9081_AIF_LRCLK_INV;
  959 + case SND_SOC_DAIFMT_DSP_A:
  960 + aif2 |= 0x3;
  961 + break;
  962 + case SND_SOC_DAIFMT_I2S:
  963 + aif2 |= 0x2;
  964 + break;
  965 + case SND_SOC_DAIFMT_RIGHT_J:
  966 + break;
  967 + case SND_SOC_DAIFMT_LEFT_J:
  968 + aif2 |= 0x1;
  969 + break;
  970 + default:
  971 + return -EINVAL;
  972 + }
  973 +
  974 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  975 + case SND_SOC_DAIFMT_DSP_A:
  976 + case SND_SOC_DAIFMT_DSP_B:
  977 + /* frame inversion not valid for DSP modes */
  978 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  979 + case SND_SOC_DAIFMT_NB_NF:
  980 + break;
  981 + case SND_SOC_DAIFMT_IB_NF:
  982 + aif2 |= WM9081_AIF_BCLK_INV;
  983 + break;
  984 + default:
  985 + return -EINVAL;
  986 + }
  987 + break;
  988 +
  989 + case SND_SOC_DAIFMT_I2S:
  990 + case SND_SOC_DAIFMT_RIGHT_J:
  991 + case SND_SOC_DAIFMT_LEFT_J:
  992 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  993 + case SND_SOC_DAIFMT_NB_NF:
  994 + break;
  995 + case SND_SOC_DAIFMT_IB_IF:
  996 + aif2 |= WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV;
  997 + break;
  998 + case SND_SOC_DAIFMT_IB_NF:
  999 + aif2 |= WM9081_AIF_BCLK_INV;
  1000 + break;
  1001 + case SND_SOC_DAIFMT_NB_IF:
  1002 + aif2 |= WM9081_AIF_LRCLK_INV;
  1003 + break;
  1004 + default:
  1005 + return -EINVAL;
  1006 + }
  1007 + break;
  1008 + default:
  1009 + return -EINVAL;
  1010 + }
  1011 +
  1012 + wm9081_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
  1013 +
  1014 + return 0;
  1015 +}
  1016 +
  1017 +static int wm9081_hw_params(struct snd_pcm_substream *substream,
  1018 + struct snd_pcm_hw_params *params,
  1019 + struct snd_soc_dai *dai)
  1020 +{
  1021 + struct snd_soc_codec *codec = dai->codec;
  1022 + struct wm9081_priv *wm9081 = codec->private_data;
  1023 + int ret, i, best, best_val, cur_val;
  1024 + unsigned int clk_ctrl2, aif1, aif2, aif3, aif4;
  1025 +
  1026 + clk_ctrl2 = wm9081_read(codec, WM9081_CLOCK_CONTROL_2);
  1027 + clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK);
  1028 +
  1029 + aif1 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_1);
  1030 +
  1031 + aif2 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_2);
  1032 + aif2 &= ~WM9081_AIF_WL_MASK;
  1033 +
  1034 + aif3 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_3);
  1035 + aif3 &= ~WM9081_BCLK_DIV_MASK;
  1036 +
  1037 + aif4 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_4);
  1038 + aif4 &= ~WM9081_LRCLK_RATE_MASK;
  1039 +
  1040 + /* What BCLK do we need? */
  1041 + wm9081->fs = params_rate(params);
  1042 + wm9081->bclk = 2 * wm9081->fs;
  1043 + switch (params_format(params)) {
  1044 + case SNDRV_PCM_FORMAT_S16_LE:
  1045 + wm9081->bclk *= 16;
  1046 + break;
  1047 + case SNDRV_PCM_FORMAT_S20_3LE:
  1048 + wm9081->bclk *= 20;
  1049 + aif2 |= 0x4;
  1050 + break;
  1051 + case SNDRV_PCM_FORMAT_S24_LE:
  1052 + wm9081->bclk *= 24;
  1053 + aif2 |= 0x8;
  1054 + break;
  1055 + case SNDRV_PCM_FORMAT_S32_LE:
  1056 + wm9081->bclk *= 32;
  1057 + aif2 |= 0xc;
  1058 + break;
  1059 + default:
  1060 + return -EINVAL;
  1061 + }
  1062 +
  1063 + if (aif1 & WM9081_AIFDAC_TDM_MODE_MASK) {
  1064 + int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >>
  1065 + WM9081_AIFDAC_TDM_MODE_SHIFT) + 1;
  1066 + wm9081->bclk *= slots;
  1067 + }
  1068 +
  1069 + dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk);
  1070 +
  1071 + ret = configure_clock(codec);
  1072 + if (ret != 0)
  1073 + return ret;
  1074 +
  1075 + /* Select nearest CLK_SYS_RATE */
  1076 + best = 0;
  1077 + best_val = abs((wm9081->sysclk_rate / clk_sys_rates[0].ratio)
  1078 + - wm9081->fs);
  1079 + for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
  1080 + cur_val = abs((wm9081->sysclk_rate /
  1081 + clk_sys_rates[i].ratio) - wm9081->fs);;
  1082 + if (cur_val < best_val) {
  1083 + best = i;
  1084 + best_val = cur_val;
  1085 + }
  1086 + }
  1087 + dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
  1088 + clk_sys_rates[best].ratio);
  1089 + clk_ctrl2 |= (clk_sys_rates[best].clk_sys_rate
  1090 + << WM9081_CLK_SYS_RATE_SHIFT);
  1091 +
  1092 + /* SAMPLE_RATE */
  1093 + best = 0;
  1094 + best_val = abs(wm9081->fs - sample_rates[0].rate);
  1095 + for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
  1096 + /* Closest match */
  1097 + cur_val = abs(wm9081->fs - sample_rates[i].rate);
  1098 + if (cur_val < best_val) {
  1099 + best = i;
  1100 + best_val = cur_val;
  1101 + }
  1102 + }
  1103 + dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
  1104 + sample_rates[best].rate);
  1105 + clk_ctrl2 |= (sample_rates[i].sample_rate << WM9081_SAMPLE_RATE_SHIFT);
  1106 +
  1107 + /* BCLK_DIV */
  1108 + best = 0;
  1109 + best_val = INT_MAX;
  1110 + for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
  1111 + cur_val = ((wm9081->sysclk_rate * 10) / bclk_divs[i].div)
  1112 + - wm9081->bclk;
  1113 + if (cur_val < 0) /* Table is sorted */
  1114 + break;
  1115 + if (cur_val < best_val) {
  1116 + best = i;
  1117 + best_val = cur_val;
  1118 + }
  1119 + }
  1120 + wm9081->bclk = (wm9081->sysclk_rate * 10) / bclk_divs[best].div;
  1121 + dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
  1122 + bclk_divs[best].div, wm9081->bclk);
  1123 + aif3 |= bclk_divs[best].bclk_div;
  1124 +
  1125 + /* LRCLK is a simple fraction of BCLK */
  1126 + dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm9081->bclk / wm9081->fs);
  1127 + aif4 |= wm9081->bclk / wm9081->fs;
  1128 +
  1129 + /* Apply a ReTune Mobile configuration if it's in use */
  1130 + if (wm9081->retune) {
  1131 + struct wm9081_retune_mobile_config *retune = wm9081->retune;
  1132 + struct wm9081_retune_mobile_setting *s;
  1133 + int eq1;
  1134 +
  1135 + best = 0;
  1136 + best_val = abs(retune->configs[0].rate - wm9081->fs);
  1137 + for (i = 0; i < retune->num_configs; i++) {
  1138 + cur_val = abs(retune->configs[i].rate - wm9081->fs);
  1139 + if (cur_val < best_val) {
  1140 + best_val = cur_val;
  1141 + best = i;
  1142 + }
  1143 + }
  1144 + s = &retune->configs[best];
  1145 +
  1146 + dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
  1147 + s->name, s->rate);
  1148 +
  1149 + /* If the EQ is enabled then disable it while we write out */
  1150 + eq1 = wm9081_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA;
  1151 + if (eq1 & WM9081_EQ_ENA)
  1152 + wm9081_write(codec, WM9081_EQ_1, 0);
  1153 +
  1154 + /* Write out the other values */
  1155 + for (i = 1; i < ARRAY_SIZE(s->config); i++)
  1156 + wm9081_write(codec, WM9081_EQ_1 + i, s->config[i]);
  1157 +
  1158 + eq1 |= (s->config[0] & ~WM9081_EQ_ENA);
  1159 + wm9081_write(codec, WM9081_EQ_1, eq1);
  1160 + }
  1161 +
  1162 + wm9081_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2);
  1163 + wm9081_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
  1164 + wm9081_write(codec, WM9081_AUDIO_INTERFACE_3, aif3);
  1165 + wm9081_write(codec, WM9081_AUDIO_INTERFACE_4, aif4);
  1166 +
  1167 + return 0;
  1168 +}
  1169 +
  1170 +static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
  1171 +{
  1172 + struct snd_soc_codec *codec = codec_dai->codec;
  1173 + unsigned int reg;
  1174 +
  1175 + reg = wm9081_read(codec, WM9081_DAC_DIGITAL_2);
  1176 +
  1177 + if (mute)
  1178 + reg |= WM9081_DAC_MUTE;
  1179 + else
  1180 + reg &= ~WM9081_DAC_MUTE;
  1181 +
  1182 + wm9081_write(codec, WM9081_DAC_DIGITAL_2, reg);
  1183 +
  1184 + return 0;
  1185 +}
  1186 +
  1187 +static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai,
  1188 + int clk_id, unsigned int freq, int dir)
  1189 +{
  1190 + struct snd_soc_codec *codec = codec_dai->codec;
  1191 + struct wm9081_priv *wm9081 = codec->private_data;
  1192 +
  1193 + switch (clk_id) {
  1194 + case WM9081_SYSCLK_MCLK:
  1195 + case WM9081_SYSCLK_FLL_MCLK:
  1196 + wm9081->sysclk_source = clk_id;
  1197 + wm9081->mclk_rate = freq;
  1198 + break;
  1199 +
  1200 + default:
  1201 + return -EINVAL;
  1202 + }
  1203 +
  1204 + return 0;
  1205 +}
  1206 +
  1207 +static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
  1208 + unsigned int mask, int slots)
  1209 +{
  1210 + struct snd_soc_codec *codec = dai->codec;
  1211 + unsigned int aif1 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_1);
  1212 +
  1213 + aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK);
  1214 +
  1215 + if (slots < 1 || slots > 4)
  1216 + return -EINVAL;
  1217 +
  1218 + aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT;
  1219 +
  1220 + switch (mask) {
  1221 + case 1:
  1222 + break;
  1223 + case 2:
  1224 + aif1 |= 0x10;
  1225 + break;
  1226 + case 4:
  1227 + aif1 |= 0x20;
  1228 + break;
  1229 + case 8:
  1230 + aif1 |= 0x30;
  1231 + break;
  1232 + default:
  1233 + return -EINVAL;
  1234 + }
  1235 +
  1236 + wm9081_write(codec, WM9081_AUDIO_INTERFACE_1, aif1);
  1237 +
  1238 + return 0;
  1239 +}
  1240 +
  1241 +#define WM9081_RATES SNDRV_PCM_RATE_8000_96000
  1242 +
  1243 +#define WM9081_FORMATS \
  1244 + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
  1245 + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
  1246 +
  1247 +static struct snd_soc_dai_ops wm9081_dai_ops = {
  1248 + .hw_params = wm9081_hw_params,
  1249 + .set_sysclk = wm9081_set_sysclk,
  1250 + .set_fmt = wm9081_set_dai_fmt,
  1251 + .digital_mute = wm9081_digital_mute,
  1252 + .set_tdm_slot = wm9081_set_tdm_slot,
  1253 +};
  1254 +
  1255 +/* We report two channels because the CODEC processes a stereo signal, even
  1256 + * though it is only capable of handling a mono output.
  1257 + */
  1258 +struct snd_soc_dai wm9081_dai = {
  1259 + .name = "WM9081",
  1260 + .playback = {
  1261 + .stream_name = "HiFi Playback",
  1262 + .channels_min = 1,
  1263 + .channels_max = 2,
  1264 + .rates = WM9081_RATES,
  1265 + .formats = WM9081_FORMATS,
  1266 + },
  1267 + .ops = &wm9081_dai_ops,
  1268 +};
  1269 +EXPORT_SYMBOL_GPL(wm9081_dai);
  1270 +
  1271 +
  1272 +static struct snd_soc_codec *wm9081_codec;
  1273 +
  1274 +static int wm9081_probe(struct platform_device *pdev)
  1275 +{
  1276 + struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  1277 + struct snd_soc_codec *codec;
  1278 + struct wm9081_priv *wm9081;
  1279 + int ret = 0;
  1280 +
  1281 + if (wm9081_codec == NULL) {
  1282 + dev_err(&pdev->dev, "Codec device not registered\n");
  1283 + return -ENODEV;
  1284 + }
  1285 +
  1286 + socdev->card->codec = wm9081_codec;
  1287 + codec = wm9081_codec;
  1288 + wm9081 = codec->private_data;
  1289 +
  1290 + /* register pcms */
  1291 + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
  1292 + if (ret < 0) {
  1293 + dev_err(codec->dev, "failed to create pcms: %d\n", ret);
  1294 + goto pcm_err;
  1295 + }
  1296 +
  1297 + snd_soc_add_controls(codec, wm9081_snd_controls,
  1298 + ARRAY_SIZE(wm9081_snd_controls));
  1299 + if (!wm9081->retune) {
  1300 + dev_dbg(codec->dev,
  1301 + "No ReTune Mobile data, using normal EQ\n");
  1302 + snd_soc_add_controls(codec, wm9081_eq_controls,
  1303 + ARRAY_SIZE(wm9081_eq_controls));
  1304 + }
  1305 +
  1306 + snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets,
  1307 + ARRAY_SIZE(wm9081_dapm_widgets));
  1308 + snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
  1309 + snd_soc_dapm_new_widgets(codec);
  1310 +
  1311 + ret = snd_soc_init_card(socdev);
  1312 + if (ret < 0) {
  1313 + dev_err(codec->dev, "failed to register card: %d\n", ret);
  1314 + goto card_err;
  1315 + }
  1316 +
  1317 + return ret;
  1318 +
  1319 +card_err:
  1320 + snd_soc_free_pcms(socdev);
  1321 + snd_soc_dapm_free(socdev);
  1322 +pcm_err:
  1323 + return ret;
  1324 +}
  1325 +
  1326 +static int wm9081_remove(struct platform_device *pdev)
  1327 +{
  1328 + struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  1329 +
  1330 + snd_soc_free_pcms(socdev);
  1331 + snd_soc_dapm_free(socdev);
  1332 +
  1333 + return 0;
  1334 +}
  1335 +
  1336 +#ifdef CONFIG_PM
  1337 +static int wm9081_suspend(struct platform_device *pdev, pm_message_t state)
  1338 +{
  1339 + struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  1340 + struct snd_soc_codec *codec = socdev->card->codec;
  1341 +
  1342 + wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
  1343 +
  1344 + return 0;
  1345 +}
  1346 +
  1347 +static int wm9081_resume(struct platform_device *pdev)
  1348 +{
  1349 + struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  1350 + struct snd_soc_codec *codec = socdev->card->codec;
  1351 + u16 *reg_cache = codec->reg_cache;
  1352 + int i;
  1353 +
  1354 + for (i = 0; i < codec->reg_cache_size; i++) {
  1355 + if (i == WM9081_SOFTWARE_RESET)
  1356 + continue;
  1357 +
  1358 + wm9081_write(codec, i, reg_cache[i]);
  1359 + }
  1360 +
  1361 + wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  1362 +
  1363 + return 0;
  1364 +}
  1365 +#else
  1366 +#define wm9081_suspend NULL
  1367 +#define wm9081_resume NULL
  1368 +#endif
  1369 +
  1370 +struct snd_soc_codec_device soc_codec_dev_wm9081 = {
  1371 + .probe = wm9081_probe,
  1372 + .remove = wm9081_remove,
  1373 + .suspend = wm9081_suspend,
  1374 + .resume = wm9081_resume,
  1375 +};
  1376 +EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081);
  1377 +
  1378 +static int wm9081_register(struct wm9081_priv *wm9081)
  1379 +{
  1380 + struct snd_soc_codec *codec = &wm9081->codec;
  1381 + int ret;
  1382 + u16 reg;
  1383 +
  1384 + if (wm9081_codec) {
  1385 + dev_err(codec->dev, "Another WM9081 is registered\n");
  1386 + ret = -EINVAL;
  1387 + goto err;
  1388 + }
  1389 +
  1390 + mutex_init(&codec->mutex);
  1391 + INIT_LIST_HEAD(&codec->dapm_widgets);
  1392 + INIT_LIST_HEAD(&codec->dapm_paths);
  1393 +
  1394 + codec->private_data = wm9081;
  1395 + codec->name = "WM9081";
  1396 + codec->owner = THIS_MODULE;
  1397 + codec->read = wm9081_read;
  1398 + codec->write = wm9081_write;
  1399 + codec->dai = &wm9081_dai;
  1400 + codec->num_dai = 1;
  1401 + codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache);
  1402 + codec->reg_cache = &wm9081->reg_cache;
  1403 + codec->bias_level = SND_SOC_BIAS_OFF;
  1404 + codec->set_bias_level = wm9081_set_bias_level;
  1405 +
  1406 + memcpy(codec->reg_cache, wm9081_reg_defaults,
  1407 + sizeof(wm9081_reg_defaults));
  1408 +
  1409 + reg = wm9081_read_hw(codec, WM9081_SOFTWARE_RESET);
  1410 + if (reg != 0x9081) {
  1411 + dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
  1412 + ret = -EINVAL;
  1413 + goto err;
  1414 + }
  1415 +
  1416 + ret = wm9081_reset(codec);
  1417 + if (ret < 0) {
  1418 + dev_err(codec->dev, "Failed to issue reset\n");
  1419 + return ret;
  1420 + }
  1421 +
  1422 + wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
  1423 +
  1424 + /* Enable zero cross by default */
  1425 + reg = wm9081_read(codec, WM9081_ANALOGUE_LINEOUT);
  1426 + wm9081_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
  1427 + reg = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
  1428 + wm9081_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
  1429 + reg | WM9081_SPKPGAZC);
  1430 +
  1431 + wm9081_dai.dev = codec->dev;
  1432 +
  1433 + wm9081_codec = codec;
  1434 +
  1435 + ret = snd_soc_register_codec(codec);
  1436 + if (ret != 0) {
  1437 + dev_err(codec->dev, "Failed to register codec: %d\n", ret);
  1438 + return ret;
  1439 + }
  1440 +
  1441 + ret = snd_soc_register_dai(&wm9081_dai);
  1442 + if (ret != 0) {
  1443 + dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
  1444 + snd_soc_unregister_codec(codec);
  1445 + return ret;
  1446 + }
  1447 +
  1448 + return 0;
  1449 +
  1450 +err:
  1451 + kfree(wm9081);
  1452 + return ret;
  1453 +}
  1454 +
  1455 +static void wm9081_unregister(struct wm9081_priv *wm9081)
  1456 +{
  1457 + wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF);
  1458 + snd_soc_unregister_dai(&wm9081_dai);
  1459 + snd_soc_unregister_codec(&wm9081->codec);
  1460 + kfree(wm9081);
  1461 + wm9081_codec = NULL;
  1462 +}
  1463 +
  1464 +static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
  1465 + const struct i2c_device_id *id)
  1466 +{
  1467 + struct wm9081_priv *wm9081;
  1468 + struct snd_soc_codec *codec;
  1469 +
  1470 + wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
  1471 + if (wm9081 == NULL)
  1472 + return -ENOMEM;
  1473 +
  1474 + codec = &wm9081->codec;
  1475 + codec->hw_write = (hw_write_t)i2c_master_send;
  1476 + wm9081->retune = i2c->dev.platform_data;
  1477 +
  1478 + i2c_set_clientdata(i2c, wm9081);
  1479 + codec->control_data = i2c;
  1480 +
  1481 + codec->dev = &i2c->dev;
  1482 +
  1483 + return wm9081_register(wm9081);
  1484 +}
  1485 +
  1486 +static __devexit int wm9081_i2c_remove(struct i2c_client *client)
  1487 +{
  1488 + struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
  1489 + wm9081_unregister(wm9081);
  1490 + return 0;
  1491 +}
  1492 +
  1493 +static const struct i2c_device_id wm9081_i2c_id[] = {
  1494 + { "wm9081", 0 },
  1495 + { }
  1496 +};
  1497 +MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
  1498 +
  1499 +static struct i2c_driver wm9081_i2c_driver = {
  1500 + .driver = {
  1501 + .name = "wm9081",
  1502 + .owner = THIS_MODULE,
  1503 + },
  1504 + .probe = wm9081_i2c_probe,
  1505 + .remove = __devexit_p(wm9081_i2c_remove),
  1506 + .id_table = wm9081_i2c_id,
  1507 +};
  1508 +
  1509 +static int __init wm9081_modinit(void)
  1510 +{
  1511 + int ret;
  1512 +
  1513 + ret = i2c_add_driver(&wm9081_i2c_driver);
  1514 + if (ret != 0) {
  1515 + printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
  1516 + ret);
  1517 + }
  1518 +
  1519 + return ret;
  1520 +}
  1521 +module_init(wm9081_modinit);
  1522 +
  1523 +static void __exit wm9081_exit(void)
  1524 +{
  1525 + i2c_del_driver(&wm9081_i2c_driver);
  1526 +}
  1527 +module_exit(wm9081_exit);
  1528 +
  1529 +
  1530 +MODULE_DESCRIPTION("ASoC WM9081 driver");
  1531 +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
  1532 +MODULE_LICENSE("GPL");
sound/soc/codecs/wm9081.h
  1 +#ifndef WM9081_H
  2 +#define WM9081_H
  3 +
  4 +/*
  5 + * wm9081.c -- WM9081 ALSA SoC Audio driver
  6 + *
  7 + * Author: Mark Brown
  8 + *
  9 + * Copyright 2009 Wolfson Microelectronics plc
  10 + *
  11 + * This program is free software; you can redistribute it and/or modify
  12 + * it under the terms of the GNU General Public License version 2 as
  13 + * published by the Free Software Foundation.
  14 + */
  15 +
  16 +#include <sound/soc.h>
  17 +
  18 +extern struct snd_soc_dai wm9081_dai;
  19 +extern struct snd_soc_codec_device soc_codec_dev_wm9081;
  20 +
  21 +/*
  22 + * SYSCLK sources
  23 + */
  24 +#define WM9081_SYSCLK_MCLK 1 /* Use MCLK without FLL */
  25 +#define WM9081_SYSCLK_FLL_MCLK 2 /* Use MCLK, enabling FLL if required */
  26 +
  27 +/*
  28 + * Register values.
  29 + */
  30 +#define WM9081_SOFTWARE_RESET 0x00
  31 +#define WM9081_ANALOGUE_LINEOUT 0x02
  32 +#define WM9081_ANALOGUE_SPEAKER_PGA 0x03
  33 +#define WM9081_VMID_CONTROL 0x04
  34 +#define WM9081_BIAS_CONTROL_1 0x05
  35 +#define WM9081_ANALOGUE_MIXER 0x07
  36 +#define WM9081_ANTI_POP_CONTROL 0x08
  37 +#define WM9081_ANALOGUE_SPEAKER_1 0x09
  38 +#define WM9081_ANALOGUE_SPEAKER_2 0x0A
  39 +#define WM9081_POWER_MANAGEMENT 0x0B
  40 +#define WM9081_CLOCK_CONTROL_1 0x0C
  41 +#define WM9081_CLOCK_CONTROL_2 0x0D
  42 +#define WM9081_CLOCK_CONTROL_3 0x0E
  43 +#define WM9081_FLL_CONTROL_1 0x10
  44 +#define WM9081_FLL_CONTROL_2 0x11
  45 +#define WM9081_FLL_CONTROL_3 0x12
  46 +#define WM9081_FLL_CONTROL_4 0x13
  47 +#define WM9081_FLL_CONTROL_5 0x14
  48 +#define WM9081_AUDIO_INTERFACE_1 0x16
  49 +#define WM9081_AUDIO_INTERFACE_2 0x17
  50 +#define WM9081_AUDIO_INTERFACE_3 0x18
  51 +#define WM9081_AUDIO_INTERFACE_4 0x19
  52 +#define WM9081_INTERRUPT_STATUS 0x1A
  53 +#define WM9081_INTERRUPT_STATUS_MASK 0x1B
  54 +#define WM9081_INTERRUPT_POLARITY 0x1C
  55 +#define WM9081_INTERRUPT_CONTROL 0x1D
  56 +#define WM9081_DAC_DIGITAL_1 0x1E
  57 +#define WM9081_DAC_DIGITAL_2 0x1F
  58 +#define WM9081_DRC_1 0x20
  59 +#define WM9081_DRC_2 0x21
  60 +#define WM9081_DRC_3 0x22
  61 +#define WM9081_DRC_4 0x23
  62 +#define WM9081_WRITE_SEQUENCER_1 0x26
  63 +#define WM9081_WRITE_SEQUENCER_2 0x27
  64 +#define WM9081_MW_SLAVE_1 0x28
  65 +#define WM9081_EQ_1 0x2A
  66 +#define WM9081_EQ_2 0x2B
  67 +#define WM9081_EQ_3 0x2C
  68 +#define WM9081_EQ_4 0x2D
  69 +#define WM9081_EQ_5 0x2E
  70 +#define WM9081_EQ_6 0x2F
  71 +#define WM9081_EQ_7 0x30
  72 +#define WM9081_EQ_8 0x31
  73 +#define WM9081_EQ_9 0x32
  74 +#define WM9081_EQ_10 0x33
  75 +#define WM9081_EQ_11 0x34
  76 +#define WM9081_EQ_12 0x35
  77 +#define WM9081_EQ_13 0x36
  78 +#define WM9081_EQ_14 0x37
  79 +#define WM9081_EQ_15 0x38
  80 +#define WM9081_EQ_16 0x39
  81 +#define WM9081_EQ_17 0x3A
  82 +#define WM9081_EQ_18 0x3B
  83 +#define WM9081_EQ_19 0x3C
  84 +#define WM9081_EQ_20 0x3D
  85 +
  86 +#define WM9081_REGISTER_COUNT 55
  87 +#define WM9081_MAX_REGISTER 0x3D
  88 +
  89 +/*
  90 + * Field Definitions.
  91 + */
  92 +
  93 +/*
  94 + * R0 (0x00) - Software Reset
  95 + */
  96 +#define WM9081_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */
  97 +#define WM9081_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */
  98 +#define WM9081_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */
  99 +
  100 +/*
  101 + * R2 (0x02) - Analogue Lineout
  102 + */
  103 +#define WM9081_LINEOUT_MUTE 0x0080 /* LINEOUT_MUTE */
  104 +#define WM9081_LINEOUT_MUTE_MASK 0x0080 /* LINEOUT_MUTE */
  105 +#define WM9081_LINEOUT_MUTE_SHIFT 7 /* LINEOUT_MUTE */
  106 +#define WM9081_LINEOUT_MUTE_WIDTH 1 /* LINEOUT_MUTE */
  107 +#define WM9081_LINEOUTZC 0x0040 /* LINEOUTZC */
  108 +#define WM9081_LINEOUTZC_MASK 0x0040 /* LINEOUTZC */
  109 +#define WM9081_LINEOUTZC_SHIFT 6 /* LINEOUTZC */
  110 +#define WM9081_LINEOUTZC_WIDTH 1 /* LINEOUTZC */
  111 +#define WM9081_LINEOUT_VOL_MASK 0x003F /* LINEOUT_VOL - [5:0] */
  112 +#define WM9081_LINEOUT_VOL_SHIFT 0 /* LINEOUT_VOL - [5:0] */
  113 +#define WM9081_LINEOUT_VOL_WIDTH 6 /* LINEOUT_VOL - [5:0] */
  114 +
  115 +/*
  116 + * R3 (0x03) - Analogue Speaker PGA
  117 + */
  118 +#define WM9081_SPKPGA_MUTE 0x0080 /* SPKPGA_MUTE */
  119 +#define WM9081_SPKPGA_MUTE_MASK 0x0080 /* SPKPGA_MUTE */
  120 +#define WM9081_SPKPGA_MUTE_SHIFT 7 /* SPKPGA_MUTE */
  121 +#define WM9081_SPKPGA_MUTE_WIDTH 1 /* SPKPGA_MUTE */
  122 +#define WM9081_SPKPGAZC 0x0040 /* SPKPGAZC */
  123 +#define WM9081_SPKPGAZC_MASK 0x0040 /* SPKPGAZC */
  124 +#define WM9081_SPKPGAZC_SHIFT 6 /* SPKPGAZC */
  125 +#define WM9081_SPKPGAZC_WIDTH 1 /* SPKPGAZC */
  126 +#define WM9081_SPKPGA_VOL_MASK 0x003F /* SPKPGA_VOL - [5:0] */
  127 +#define WM9081_SPKPGA_VOL_SHIFT 0 /* SPKPGA_VOL - [5:0] */
  128 +#define WM9081_SPKPGA_VOL_WIDTH 6 /* SPKPGA_VOL - [5:0] */
  129 +
  130 +/*
  131 + * R4 (0x04) - VMID Control
  132 + */
  133 +#define WM9081_VMID_BUF_ENA 0x0020 /* VMID_BUF_ENA */
  134 +#define WM9081_VMID_BUF_ENA_MASK 0x0020 /* VMID_BUF_ENA */
  135 +#define WM9081_VMID_BUF_ENA_SHIFT 5 /* VMID_BUF_ENA */
  136 +#define WM9081_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
  137 +#define WM9081_VMID_RAMP 0x0008 /* VMID_RAMP */
  138 +#define WM9081_VMID_RAMP_MASK 0x0008 /* VMID_RAMP */
  139 +#define WM9081_VMID_RAMP_SHIFT 3 /* VMID_RAMP */
  140 +#define WM9081_VMID_RAMP_WIDTH 1 /* VMID_RAMP */
  141 +#define WM9081_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */
  142 +#define WM9081_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */
  143 +#define WM9081_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */
  144 +#define WM9081_VMID_FAST_ST 0x0001 /* VMID_FAST_ST */
  145 +#define WM9081_VMID_FAST_ST_MASK 0x0001 /* VMID_FAST_ST */
  146 +#define WM9081_VMID_FAST_ST_SHIFT 0 /* VMID_FAST_ST */
  147 +#define WM9081_VMID_FAST_ST_WIDTH 1 /* VMID_FAST_ST */
  148 +
  149 +/*
  150 + * R5 (0x05) - Bias Control 1
  151 + */
  152 +#define WM9081_BIAS_SRC 0x0040 /* BIAS_SRC */
  153 +#define WM9081_BIAS_SRC_MASK 0x0040 /* BIAS_SRC */
  154 +#define WM9081_BIAS_SRC_SHIFT 6 /* BIAS_SRC */
  155 +#define WM9081_BIAS_SRC_WIDTH 1 /* BIAS_SRC */
  156 +#define WM9081_STBY_BIAS_LVL 0x0020 /* STBY_BIAS_LVL */
  157 +#define WM9081_STBY_BIAS_LVL_MASK 0x0020 /* STBY_BIAS_LVL */
  158 +#define WM9081_STBY_BIAS_LVL_SHIFT 5 /* STBY_BIAS_LVL */
  159 +#define WM9081_STBY_BIAS_LVL_WIDTH 1 /* STBY_BIAS_LVL */
  160 +#define WM9081_STBY_BIAS_ENA 0x0010 /* STBY_BIAS_ENA */
  161 +#define WM9081_STBY_BIAS_ENA_MASK 0x0010 /* STBY_BIAS_ENA */
  162 +#define WM9081_STBY_BIAS_ENA_SHIFT 4 /* STBY_BIAS_ENA */
  163 +#define WM9081_STBY_BIAS_ENA_WIDTH 1 /* STBY_BIAS_ENA */
  164 +#define WM9081_BIAS_LVL_MASK 0x000C /* BIAS_LVL - [3:2] */
  165 +#define WM9081_BIAS_LVL_SHIFT 2 /* BIAS_LVL - [3:2] */
  166 +#define WM9081_BIAS_LVL_WIDTH 2 /* BIAS_LVL - [3:2] */
  167 +#define WM9081_BIAS_ENA 0x0002 /* BIAS_ENA */
  168 +#define WM9081_BIAS_ENA_MASK 0x0002 /* BIAS_ENA */
  169 +#define WM9081_BIAS_ENA_SHIFT 1 /* BIAS_ENA */
  170 +#define WM9081_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
  171 +#define WM9081_STARTUP_BIAS_ENA 0x0001 /* STARTUP_BIAS_ENA */
  172 +#define WM9081_STARTUP_BIAS_ENA_MASK 0x0001 /* STARTUP_BIAS_ENA */
  173 +#define WM9081_STARTUP_BIAS_ENA_SHIFT 0 /* STARTUP_BIAS_ENA */
  174 +#define WM9081_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
  175 +
  176 +/*
  177 + * R7 (0x07) - Analogue Mixer
  178 + */
  179 +#define WM9081_DAC_SEL 0x0010 /* DAC_SEL */
  180 +#define WM9081_DAC_SEL_MASK 0x0010 /* DAC_SEL */
  181 +#define WM9081_DAC_SEL_SHIFT 4 /* DAC_SEL */
  182 +#define WM9081_DAC_SEL_WIDTH 1 /* DAC_SEL */
  183 +#define WM9081_IN2_VOL 0x0008 /* IN2_VOL */
  184 +#define WM9081_IN2_VOL_MASK 0x0008 /* IN2_VOL */
  185 +#define WM9081_IN2_VOL_SHIFT 3 /* IN2_VOL */
  186 +#define WM9081_IN2_VOL_WIDTH 1 /* IN2_VOL */
  187 +#define WM9081_IN2_ENA 0x0004 /* IN2_ENA */
  188 +#define WM9081_IN2_ENA_MASK 0x0004 /* IN2_ENA */
  189 +#define WM9081_IN2_ENA_SHIFT 2 /* IN2_ENA */
  190 +#define WM9081_IN2_ENA_WIDTH 1 /* IN2_ENA */
  191 +#define WM9081_IN1_VOL 0x0002 /* IN1_VOL */
  192 +#define WM9081_IN1_VOL_MASK 0x0002 /* IN1_VOL */
  193 +#define WM9081_IN1_VOL_SHIFT 1 /* IN1_VOL */
  194 +#define WM9081_IN1_VOL_WIDTH 1 /* IN1_VOL */
  195 +#define WM9081_IN1_ENA 0x0001 /* IN1_ENA */
  196 +#define WM9081_IN1_ENA_MASK 0x0001 /* IN1_ENA */
  197 +#define WM9081_IN1_ENA_SHIFT 0 /* IN1_ENA */
  198 +#define WM9081_IN1_ENA_WIDTH 1 /* IN1_ENA */
  199 +
  200 +/*
  201 + * R8 (0x08) - Anti Pop Control
  202 + */
  203 +#define WM9081_LINEOUT_DISCH 0x0004 /* LINEOUT_DISCH */
  204 +#define WM9081_LINEOUT_DISCH_MASK 0x0004 /* LINEOUT_DISCH */
  205 +#define WM9081_LINEOUT_DISCH_SHIFT 2 /* LINEOUT_DISCH */
  206 +#define WM9081_LINEOUT_DISCH_WIDTH 1 /* LINEOUT_DISCH */
  207 +#define WM9081_LINEOUT_VROI 0x0002 /* LINEOUT_VROI */
  208 +#define WM9081_LINEOUT_VROI_MASK 0x0002 /* LINEOUT_VROI */
  209 +#define WM9081_LINEOUT_VROI_SHIFT 1 /* LINEOUT_VROI */
  210 +#define WM9081_LINEOUT_VROI_WIDTH 1 /* LINEOUT_VROI */
  211 +#define WM9081_LINEOUT_CLAMP 0x0001 /* LINEOUT_CLAMP */
  212 +#define WM9081_LINEOUT_CLAMP_MASK 0x0001 /* LINEOUT_CLAMP */
  213 +#define WM9081_LINEOUT_CLAMP_SHIFT 0 /* LINEOUT_CLAMP */
  214 +#define WM9081_LINEOUT_CLAMP_WIDTH 1 /* LINEOUT_CLAMP */
  215 +
  216 +/*
  217 + * R9 (0x09) - Analogue Speaker 1
  218 + */
  219 +#define WM9081_SPK_DCGAIN_MASK 0x0038 /* SPK_DCGAIN - [5:3] */
  220 +#define WM9081_SPK_DCGAIN_SHIFT 3 /* SPK_DCGAIN - [5:3] */
  221 +#define WM9081_SPK_DCGAIN_WIDTH 3 /* SPK_DCGAIN - [5:3] */
  222 +#define WM9081_SPK_ACGAIN_MASK 0x0007 /* SPK_ACGAIN - [2:0] */
  223 +#define WM9081_SPK_ACGAIN_SHIFT 0 /* SPK_ACGAIN - [2:0] */
  224 +#define WM9081_SPK_ACGAIN_WIDTH 3 /* SPK_ACGAIN - [2:0] */
  225 +
  226 +/*
  227 + * R10 (0x0A) - Analogue Speaker 2
  228 + */
  229 +#define WM9081_SPK_MODE 0x0040 /* SPK_MODE */
  230 +#define WM9081_SPK_MODE_MASK 0x0040 /* SPK_MODE */
  231 +#define WM9081_SPK_MODE_SHIFT 6 /* SPK_MODE */
  232 +#define WM9081_SPK_MODE_WIDTH 1 /* SPK_MODE */
  233 +#define WM9081_SPK_INV_MUTE 0x0010 /* SPK_INV_MUTE */
  234 +#define WM9081_SPK_INV_MUTE_MASK 0x0010 /* SPK_INV_MUTE */
  235 +#define WM9081_SPK_INV_MUTE_SHIFT 4 /* SPK_INV_MUTE */
  236 +#define WM9081_SPK_INV_MUTE_WIDTH 1 /* SPK_INV_MUTE */
  237 +#define WM9081_OUT_SPK_CTRL 0x0008 /* OUT_SPK_CTRL */
  238 +#define WM9081_OUT_SPK_CTRL_MASK 0x0008 /* OUT_SPK_CTRL */
  239 +#define WM9081_OUT_SPK_CTRL_SHIFT 3 /* OUT_SPK_CTRL */
  240 +#define WM9081_OUT_SPK_CTRL_WIDTH 1 /* OUT_SPK_CTRL */
  241 +
  242 +/*
  243 + * R11 (0x0B) - Power Management
  244 + */
  245 +#define WM9081_TSHUT_ENA 0x0100 /* TSHUT_ENA */
  246 +#define WM9081_TSHUT_ENA_MASK 0x0100 /* TSHUT_ENA */
  247 +#define WM9081_TSHUT_ENA_SHIFT 8 /* TSHUT_ENA */
  248 +#define WM9081_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */
  249 +#define WM9081_TSENSE_ENA 0x0080 /* TSENSE_ENA */
  250 +#define WM9081_TSENSE_ENA_MASK 0x0080 /* TSENSE_ENA */
  251 +#define WM9081_TSENSE_ENA_SHIFT 7 /* TSENSE_ENA */
  252 +#define WM9081_TSENSE_ENA_WIDTH 1 /* TSENSE_ENA */
  253 +#define WM9081_TEMP_SHUT 0x0040 /* TEMP_SHUT */
  254 +#define WM9081_TEMP_SHUT_MASK 0x0040 /* TEMP_SHUT */
  255 +#define WM9081_TEMP_SHUT_SHIFT 6 /* TEMP_SHUT */
  256 +#define WM9081_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */
  257 +#define WM9081_LINEOUT_ENA 0x0010 /* LINEOUT_ENA */
  258 +#define WM9081_LINEOUT_ENA_MASK 0x0010 /* LINEOUT_ENA */
  259 +#define WM9081_LINEOUT_ENA_SHIFT 4 /* LINEOUT_ENA */
  260 +#define WM9081_LINEOUT_ENA_WIDTH 1 /* LINEOUT_ENA */
  261 +#define WM9081_SPKPGA_ENA 0x0004 /* SPKPGA_ENA */
  262 +#define WM9081_SPKPGA_ENA_MASK 0x0004 /* SPKPGA_ENA */
  263 +#define WM9081_SPKPGA_ENA_SHIFT 2 /* SPKPGA_ENA */
  264 +#define WM9081_SPKPGA_ENA_WIDTH 1 /* SPKPGA_ENA */
  265 +#define WM9081_SPK_ENA 0x0002 /* SPK_ENA */
  266 +#define WM9081_SPK_ENA_MASK 0x0002 /* SPK_ENA */
  267 +#define WM9081_SPK_ENA_SHIFT 1 /* SPK_ENA */
  268 +#define WM9081_SPK_ENA_WIDTH 1 /* SPK_ENA */
  269 +#define WM9081_DAC_ENA 0x0001 /* DAC_ENA */
  270 +#define WM9081_DAC_ENA_MASK 0x0001 /* DAC_ENA */
  271 +#define WM9081_DAC_ENA_SHIFT 0 /* DAC_ENA */
  272 +#define WM9081_DAC_ENA_WIDTH 1 /* DAC_ENA */
  273 +
  274 +/*
  275 + * R12 (0x0C) - Clock Control 1
  276 + */
  277 +#define WM9081_CLK_OP_DIV_MASK 0x1C00 /* CLK_OP_DIV - [12:10] */
  278 +#define WM9081_CLK_OP_DIV_SHIFT 10 /* CLK_OP_DIV - [12:10] */
  279 +#define WM9081_CLK_OP_DIV_WIDTH 3 /* CLK_OP_DIV - [12:10] */
  280 +#define WM9081_CLK_TO_DIV_MASK 0x0300 /* CLK_TO_DIV - [9:8] */
  281 +#define WM9081_CLK_TO_DIV_SHIFT 8 /* CLK_TO_DIV - [9:8] */
  282 +#define WM9081_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [9:8] */
  283 +#define WM9081_MCLKDIV2 0x0080 /* MCLKDIV2 */
  284 +#define WM9081_MCLKDIV2_MASK 0x0080 /* MCLKDIV2 */
  285 +#define WM9081_MCLKDIV2_SHIFT 7 /* MCLKDIV2 */
  286 +#define WM9081_MCLKDIV2_WIDTH 1 /* MCLKDIV2 */
  287 +
  288 +/*
  289 + * R13 (0x0D) - Clock Control 2
  290 + */
  291 +#define WM9081_CLK_SYS_RATE_MASK 0x00F0 /* CLK_SYS_RATE - [7:4] */
  292 +#define WM9081_CLK_SYS_RATE_SHIFT 4 /* CLK_SYS_RATE - [7:4] */
  293 +#define WM9081_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [7:4] */
  294 +#define WM9081_SAMPLE_RATE_MASK 0x000F /* SAMPLE_RATE - [3:0] */
  295 +#define WM9081_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [3:0] */
  296 +#define WM9081_SAMPLE_RATE_WIDTH 4 /* SAMPLE_RATE - [3:0] */
  297 +
  298 +/*
  299 + * R14 (0x0E) - Clock Control 3
  300 + */
  301 +#define WM9081_CLK_SRC_SEL 0x2000 /* CLK_SRC_SEL */
  302 +#define WM9081_CLK_SRC_SEL_MASK 0x2000 /* CLK_SRC_SEL */
  303 +#define WM9081_CLK_SRC_SEL_SHIFT 13 /* CLK_SRC_SEL */
  304 +#define WM9081_CLK_SRC_SEL_WIDTH 1 /* CLK_SRC_SEL */
  305 +#define WM9081_CLK_OP_ENA 0x0020 /* CLK_OP_ENA */
  306 +#define WM9081_CLK_OP_ENA_MASK 0x0020 /* CLK_OP_ENA */
  307 +#define WM9081_CLK_OP_ENA_SHIFT 5 /* CLK_OP_ENA */
  308 +#define WM9081_CLK_OP_ENA_WIDTH 1 /* CLK_OP_ENA */
  309 +#define WM9081_CLK_TO_ENA 0x0004 /* CLK_TO_ENA */
  310 +#define WM9081_CLK_TO_ENA_MASK 0x0004 /* CLK_TO_ENA */
  311 +#define WM9081_CLK_TO_ENA_SHIFT 2 /* CLK_TO_ENA */
  312 +#define WM9081_CLK_TO_ENA_WIDTH 1 /* CLK_TO_ENA */
  313 +#define WM9081_CLK_DSP_ENA 0x0002 /* CLK_DSP_ENA */
  314 +#define WM9081_CLK_DSP_ENA_MASK 0x0002 /* CLK_DSP_ENA */
  315 +#define WM9081_CLK_DSP_ENA_SHIFT 1 /* CLK_DSP_ENA */
  316 +#define WM9081_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */
  317 +#define WM9081_CLK_SYS_ENA 0x0001 /* CLK_SYS_ENA */
  318 +#define WM9081_CLK_SYS_ENA_MASK 0x0001 /* CLK_SYS_ENA */
  319 +#define WM9081_CLK_SYS_ENA_SHIFT 0 /* CLK_SYS_ENA */
  320 +#define WM9081_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */
  321 +
  322 +/*
  323 + * R16 (0x10) - FLL Control 1
  324 + */
  325 +#define WM9081_FLL_HOLD 0x0008 /* FLL_HOLD */
  326 +#define WM9081_FLL_HOLD_MASK 0x0008 /* FLL_HOLD */
  327 +#define WM9081_FLL_HOLD_SHIFT 3 /* FLL_HOLD */
  328 +#define WM9081_FLL_HOLD_WIDTH 1 /* FLL_HOLD */
  329 +#define WM9081_FLL_FRAC 0x0004 /* FLL_FRAC */
  330 +#define WM9081_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */
  331 +#define WM9081_FLL_FRAC_SHIFT 2 /* FLL_FRAC */
  332 +#define WM9081_FLL_FRAC_WIDTH 1 /* FLL_FRAC */
  333 +#define WM9081_FLL_ENA 0x0001 /* FLL_ENA */
  334 +#define WM9081_FLL_ENA_MASK 0x0001 /* FLL_ENA */
  335 +#define WM9081_FLL_ENA_SHIFT 0 /* FLL_ENA */
  336 +#define WM9081_FLL_ENA_WIDTH 1 /* FLL_ENA */
  337 +
  338 +/*
  339 + * R17 (0x11) - FLL Control 2
  340 + */
  341 +#define WM9081_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */
  342 +#define WM9081_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */
  343 +#define WM9081_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */
  344 +#define WM9081_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */
  345 +#define WM9081_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */
  346 +#define WM9081_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */
  347 +#define WM9081_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
  348 +#define WM9081_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
  349 +#define WM9081_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
  350 +
  351 +/*
  352 + * R18 (0x12) - FLL Control 3
  353 + */
  354 +#define WM9081_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */
  355 +#define WM9081_FLL_K_SHIFT 0 /* FLL_K - [15:0] */
  356 +#define WM9081_FLL_K_WIDTH 16 /* FLL_K - [15:0] */
  357 +
  358 +/*
  359 + * R19 (0x13) - FLL Control 4
  360 + */
  361 +#define WM9081_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */
  362 +#define WM9081_FLL_N_SHIFT 5 /* FLL_N - [14:5] */
  363 +#define WM9081_FLL_N_WIDTH 10 /* FLL_N - [14:5] */
  364 +#define WM9081_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */
  365 +#define WM9081_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */
  366 +#define WM9081_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */
  367 +
  368 +/*
  369 + * R20 (0x14) - FLL Control 5
  370 + */
  371 +#define WM9081_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */
  372 +#define WM9081_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */
  373 +#define WM9081_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */
  374 +#define WM9081_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */
  375 +#define WM9081_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */
  376 +#define WM9081_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */
  377 +
  378 +/*
  379 + * R22 (0x16) - Audio Interface 1
  380 + */
  381 +#define WM9081_AIFDAC_CHAN 0x0040 /* AIFDAC_CHAN */
  382 +#define WM9081_AIFDAC_CHAN_MASK 0x0040 /* AIFDAC_CHAN */
  383 +#define WM9081_AIFDAC_CHAN_SHIFT 6 /* AIFDAC_CHAN */
  384 +#define WM9081_AIFDAC_CHAN_WIDTH 1 /* AIFDAC_CHAN */
  385 +#define WM9081_AIFDAC_TDM_SLOT_MASK 0x0030 /* AIFDAC_TDM_SLOT - [5:4] */
  386 +#define WM9081_AIFDAC_TDM_SLOT_SHIFT 4 /* AIFDAC_TDM_SLOT - [5:4] */
  387 +#define WM9081_AIFDAC_TDM_SLOT_WIDTH 2 /* AIFDAC_TDM_SLOT - [5:4] */
  388 +#define WM9081_AIFDAC_TDM_MODE_MASK 0x000C /* AIFDAC_TDM_MODE - [3:2] */
  389 +#define WM9081_AIFDAC_TDM_MODE_SHIFT 2 /* AIFDAC_TDM_MODE - [3:2] */
  390 +#define WM9081_AIFDAC_TDM_MODE_WIDTH 2 /* AIFDAC_TDM_MODE - [3:2] */
  391 +#define WM9081_DAC_COMP 0x0002 /* DAC_COMP */
  392 +#define WM9081_DAC_COMP_MASK 0x0002 /* DAC_COMP */
  393 +#define WM9081_DAC_COMP_SHIFT 1 /* DAC_COMP */
  394 +#define WM9081_DAC_COMP_WIDTH 1 /* DAC_COMP */
  395 +#define WM9081_DAC_COMPMODE 0x0001 /* DAC_COMPMODE */
  396 +#define WM9081_DAC_COMPMODE_MASK 0x0001 /* DAC_COMPMODE */
  397 +#define WM9081_DAC_COMPMODE_SHIFT 0 /* DAC_COMPMODE */
  398 +#define WM9081_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */
  399 +
  400 +/*
  401 + * R23 (0x17) - Audio Interface 2
  402 + */
  403 +#define WM9081_AIF_TRIS 0x0200 /* AIF_TRIS */
  404 +#define WM9081_AIF_TRIS_MASK 0x0200 /* AIF_TRIS */
  405 +#define WM9081_AIF_TRIS_SHIFT 9 /* AIF_TRIS */
  406 +#define WM9081_AIF_TRIS_WIDTH 1 /* AIF_TRIS */
  407 +#define WM9081_DAC_DAT_INV 0x0100 /* DAC_DAT_INV */
  408 +#define WM9081_DAC_DAT_INV_MASK 0x0100 /* DAC_DAT_INV */
  409 +#define WM9081_DAC_DAT_INV_SHIFT 8 /* DAC_DAT_INV */
  410 +#define WM9081_DAC_DAT_INV_WIDTH 1 /* DAC_DAT_INV */
  411 +#define WM9081_AIF_BCLK_INV 0x0080 /* AIF_BCLK_INV */
  412 +#define WM9081_AIF_BCLK_INV_MASK 0x0080 /* AIF_BCLK_INV */
  413 +#define WM9081_AIF_BCLK_INV_SHIFT 7 /* AIF_BCLK_INV */
  414 +#define WM9081_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */
  415 +#define WM9081_BCLK_DIR 0x0040 /* BCLK_DIR */
  416 +#define WM9081_BCLK_DIR_MASK 0x0040 /* BCLK_DIR */
  417 +#define WM9081_BCLK_DIR_SHIFT 6 /* BCLK_DIR */
  418 +#define WM9081_BCLK_DIR_WIDTH 1 /* BCLK_DIR */
  419 +#define WM9081_LRCLK_DIR 0x0020 /* LRCLK_DIR */
  420 +#define WM9081_LRCLK_DIR_MASK 0x0020 /* LRCLK_DIR */
  421 +#define WM9081_LRCLK_DIR_SHIFT 5 /* LRCLK_DIR */
  422 +#define WM9081_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */
  423 +#define WM9081_AIF_LRCLK_INV 0x0010 /* AIF_LRCLK_INV */
  424 +#define WM9081_AIF_LRCLK_INV_MASK 0x0010 /* AIF_LRCLK_INV */
  425 +#define WM9081_AIF_LRCLK_INV_SHIFT 4 /* AIF_LRCLK_INV */
  426 +#define WM9081_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */
  427 +#define WM9081_AIF_WL_MASK 0x000C /* AIF_WL - [3:2] */
  428 +#define WM9081_AIF_WL_SHIFT 2 /* AIF_WL - [3:2] */
  429 +#define WM9081_AIF_WL_WIDTH 2 /* AIF_WL - [3:2] */
  430 +#define WM9081_AIF_FMT_MASK 0x0003 /* AIF_FMT - [1:0] */
  431 +#define WM9081_AIF_FMT_SHIFT 0 /* AIF_FMT - [1:0] */
  432 +#define WM9081_AIF_FMT_WIDTH 2 /* AIF_FMT - [1:0] */
  433 +
  434 +/*
  435 + * R24 (0x18) - Audio Interface 3
  436 + */
  437 +#define WM9081_BCLK_DIV_MASK 0x001F /* BCLK_DIV - [4:0] */
  438 +#define WM9081_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [4:0] */
  439 +#define WM9081_BCLK_DIV_WIDTH 5 /* BCLK_DIV - [4:0] */
  440 +
  441 +/*
  442 + * R25 (0x19) - Audio Interface 4
  443 + */
  444 +#define WM9081_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */
  445 +#define WM9081_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */
  446 +#define WM9081_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */
  447 +
  448 +/*
  449 + * R26 (0x1A) - Interrupt Status
  450 + */
  451 +#define WM9081_WSEQ_BUSY_EINT 0x0004 /* WSEQ_BUSY_EINT */
  452 +#define WM9081_WSEQ_BUSY_EINT_MASK 0x0004 /* WSEQ_BUSY_EINT */
  453 +#define WM9081_WSEQ_BUSY_EINT_SHIFT 2 /* WSEQ_BUSY_EINT */
  454 +#define WM9081_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */
  455 +#define WM9081_TSHUT_EINT 0x0001 /* TSHUT_EINT */
  456 +#define WM9081_TSHUT_EINT_MASK 0x0001 /* TSHUT_EINT */
  457 +#define WM9081_TSHUT_EINT_SHIFT 0 /* TSHUT_EINT */
  458 +#define WM9081_TSHUT_EINT_WIDTH 1 /* TSHUT_EINT */
  459 +
  460 +/*
  461 + * R27 (0x1B) - Interrupt Status Mask
  462 + */
  463 +#define WM9081_IM_WSEQ_BUSY_EINT 0x0004 /* IM_WSEQ_BUSY_EINT */
  464 +#define WM9081_IM_WSEQ_BUSY_EINT_MASK 0x0004 /* IM_WSEQ_BUSY_EINT */
  465 +#define WM9081_IM_WSEQ_BUSY_EINT_SHIFT 2 /* IM_WSEQ_BUSY_EINT */
  466 +#define WM9081_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */
  467 +#define WM9081_IM_TSHUT_EINT 0x0001 /* IM_TSHUT_EINT */
  468 +#define WM9081_IM_TSHUT_EINT_MASK 0x0001 /* IM_TSHUT_EINT */
  469 +#define WM9081_IM_TSHUT_EINT_SHIFT 0 /* IM_TSHUT_EINT */
  470 +#define WM9081_IM_TSHUT_EINT_WIDTH 1 /* IM_TSHUT_EINT */
  471 +
  472 +/*
  473 + * R28 (0x1C) - Interrupt Polarity
  474 + */
  475 +#define WM9081_TSHUT_INV 0x0001 /* TSHUT_INV */
  476 +#define WM9081_TSHUT_INV_MASK 0x0001 /* TSHUT_INV */
  477 +#define WM9081_TSHUT_INV_SHIFT 0 /* TSHUT_INV */
  478 +#define WM9081_TSHUT_INV_WIDTH 1 /* TSHUT_INV */
  479 +
  480 +/*
  481 + * R29 (0x1D) - Interrupt Control
  482 + */
  483 +#define WM9081_IRQ_POL 0x8000 /* IRQ_POL */
  484 +#define WM9081_IRQ_POL_MASK 0x8000 /* IRQ_POL */
  485 +#define WM9081_IRQ_POL_SHIFT 15 /* IRQ_POL */
  486 +#define WM9081_IRQ_POL_WIDTH 1 /* IRQ_POL */
  487 +#define WM9081_IRQ_OP_CTRL 0x0001 /* IRQ_OP_CTRL */
  488 +#define WM9081_IRQ_OP_CTRL_MASK 0x0001 /* IRQ_OP_CTRL */
  489 +#define WM9081_IRQ_OP_CTRL_SHIFT 0 /* IRQ_OP_CTRL */
  490 +#define WM9081_IRQ_OP_CTRL_WIDTH 1 /* IRQ_OP_CTRL */
  491 +
  492 +/*
  493 + * R30 (0x1E) - DAC Digital 1
  494 + */
  495 +#define WM9081_DAC_VOL_MASK 0x00FF /* DAC_VOL - [7:0] */
  496 +#define WM9081_DAC_VOL_SHIFT 0 /* DAC_VOL - [7:0] */
  497 +#define WM9081_DAC_VOL_WIDTH 8 /* DAC_VOL - [7:0] */
  498 +
  499 +/*
  500 + * R31 (0x1F) - DAC Digital 2
  501 + */
  502 +#define WM9081_DAC_MUTERATE 0x0400 /* DAC_MUTERATE */
  503 +#define WM9081_DAC_MUTERATE_MASK 0x0400 /* DAC_MUTERATE */
  504 +#define WM9081_DAC_MUTERATE_SHIFT 10 /* DAC_MUTERATE */
  505 +#define WM9081_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
  506 +#define WM9081_DAC_MUTEMODE 0x0200 /* DAC_MUTEMODE */
  507 +#define WM9081_DAC_MUTEMODE_MASK 0x0200 /* DAC_MUTEMODE */
  508 +#define WM9081_DAC_MUTEMODE_SHIFT 9 /* DAC_MUTEMODE */
  509 +#define WM9081_DAC_MUTEMODE_WIDTH 1 /* DAC_MUTEMODE */
  510 +#define WM9081_DAC_MUTE 0x0008 /* DAC_MUTE */
  511 +#define WM9081_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */
  512 +#define WM9081_DAC_MUTE_SHIFT 3 /* DAC_MUTE */
  513 +#define WM9081_DAC_MUTE_WIDTH 1 /* DAC_MUTE */
  514 +#define WM9081_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */
  515 +#define WM9081_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */
  516 +#define WM9081_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */
  517 +
  518 +/*
  519 + * R32 (0x20) - DRC 1
  520 + */
  521 +#define WM9081_DRC_ENA 0x8000 /* DRC_ENA */
  522 +#define WM9081_DRC_ENA_MASK 0x8000 /* DRC_ENA */
  523 +#define WM9081_DRC_ENA_SHIFT 15 /* DRC_ENA */
  524 +#define WM9081_DRC_ENA_WIDTH 1 /* DRC_ENA */
  525 +#define WM9081_DRC_STARTUP_GAIN_MASK 0x07C0 /* DRC_STARTUP_GAIN - [10:6] */
  526 +#define WM9081_DRC_STARTUP_GAIN_SHIFT 6 /* DRC_STARTUP_GAIN - [10:6] */
  527 +#define WM9081_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [10:6] */
  528 +#define WM9081_DRC_FF_DLY 0x0020 /* DRC_FF_DLY */
  529 +#define WM9081_DRC_FF_DLY_MASK 0x0020 /* DRC_FF_DLY */
  530 +#define WM9081_DRC_FF_DLY_SHIFT 5 /* DRC_FF_DLY */
  531 +#define WM9081_DRC_FF_DLY_WIDTH 1 /* DRC_FF_DLY */
  532 +#define WM9081_DRC_QR 0x0004 /* DRC_QR */
  533 +#define WM9081_DRC_QR_MASK 0x0004 /* DRC_QR */
  534 +#define WM9081_DRC_QR_SHIFT 2 /* DRC_QR */
  535 +#define WM9081_DRC_QR_WIDTH 1 /* DRC_QR */
  536 +#define WM9081_DRC_ANTICLIP 0x0002 /* DRC_ANTICLIP */
  537 +#define WM9081_DRC_ANTICLIP_MASK 0x0002 /* DRC_ANTICLIP */
  538 +#define WM9081_DRC_ANTICLIP_SHIFT 1 /* DRC_ANTICLIP */
  539 +#define WM9081_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */
  540 +
  541 +/*
  542 + * R33 (0x21) - DRC 2
  543 + */
  544 +#define WM9081_DRC_ATK_MASK 0xF000 /* DRC_ATK - [15:12] */
  545 +#define WM9081_DRC_ATK_SHIFT 12 /* DRC_ATK - [15:12] */
  546 +#define WM9081_DRC_ATK_WIDTH 4 /* DRC_ATK - [15:12] */
  547 +#define WM9081_DRC_DCY_MASK 0x0F00 /* DRC_DCY - [11:8] */
  548 +#define WM9081_DRC_DCY_SHIFT 8 /* DRC_DCY - [11:8] */
  549 +#define WM9081_DRC_DCY_WIDTH 4 /* DRC_DCY - [11:8] */
  550 +#define WM9081_DRC_QR_THR_MASK 0x00C0 /* DRC_QR_THR - [7:6] */
  551 +#define WM9081_DRC_QR_THR_SHIFT 6 /* DRC_QR_THR - [7:6] */
  552 +#define WM9081_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [7:6] */
  553 +#define WM9081_DRC_QR_DCY_MASK 0x0030 /* DRC_QR_DCY - [5:4] */
  554 +#define WM9081_DRC_QR_DCY_SHIFT 4 /* DRC_QR_DCY - [5:4] */
  555 +#define WM9081_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [5:4] */
  556 +#define WM9081_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */
  557 +#define WM9081_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */
  558 +#define WM9081_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */
  559 +#define WM9081_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
  560 +#define WM9081_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
  561 +#define WM9081_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
  562 +
  563 +/*
  564 + * R34 (0x22) - DRC 3
  565 + */
  566 +#define WM9081_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */
  567 +#define WM9081_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */
  568 +#define WM9081_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */
  569 +#define WM9081_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */
  570 +#define WM9081_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */
  571 +#define WM9081_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */
  572 +
  573 +/*
  574 + * R35 (0x23) - DRC 4
  575 + */
  576 +#define WM9081_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */
  577 +#define WM9081_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */
  578 +#define WM9081_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */
  579 +#define WM9081_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */
  580 +#define WM9081_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */
  581 +#define WM9081_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */
  582 +
  583 +/*
  584 + * R38 (0x26) - Write Sequencer 1
  585 + */
  586 +#define WM9081_WSEQ_ENA 0x8000 /* WSEQ_ENA */
  587 +#define WM9081_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */
  588 +#define WM9081_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */
  589 +#define WM9081_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
  590 +#define WM9081_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */
  591 +#define WM9081_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */
  592 +#define WM9081_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */
  593 +#define WM9081_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
  594 +#define WM9081_WSEQ_START 0x0100 /* WSEQ_START */
  595 +#define WM9081_WSEQ_START_MASK 0x0100 /* WSEQ_START */
  596 +#define WM9081_WSEQ_START_SHIFT 8 /* WSEQ_START */
  597 +#define WM9081_WSEQ_START_WIDTH 1 /* WSEQ_START */
  598 +#define WM9081_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */
  599 +#define WM9081_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */
  600 +#define WM9081_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */
  601 +
  602 +/*
  603 + * R39 (0x27) - Write Sequencer 2
  604 + */
  605 +#define WM9081_WSEQ_CURRENT_INDEX_MASK 0x07F0 /* WSEQ_CURRENT_INDEX - [10:4] */
  606 +#define WM9081_WSEQ_CURRENT_INDEX_SHIFT 4 /* WSEQ_CURRENT_INDEX - [10:4] */
  607 +#define WM9081_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [10:4] */
  608 +#define WM9081_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
  609 +#define WM9081_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
  610 +#define WM9081_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
  611 +#define WM9081_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
  612 +
  613 +/*
  614 + * R40 (0x28) - MW Slave 1
  615 + */
  616 +#define WM9081_SPI_CFG 0x0020 /* SPI_CFG */
  617 +#define WM9081_SPI_CFG_MASK 0x0020 /* SPI_CFG */
  618 +#define WM9081_SPI_CFG_SHIFT 5 /* SPI_CFG */
  619 +#define WM9081_SPI_CFG_WIDTH 1 /* SPI_CFG */
  620 +#define WM9081_SPI_4WIRE 0x0010 /* SPI_4WIRE */
  621 +#define WM9081_SPI_4WIRE_MASK 0x0010 /* SPI_4WIRE */
  622 +#define WM9081_SPI_4WIRE_SHIFT 4 /* SPI_4WIRE */
  623 +#define WM9081_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */
  624 +#define WM9081_ARA_ENA 0x0008 /* ARA_ENA */
  625 +#define WM9081_ARA_ENA_MASK 0x0008 /* ARA_ENA */
  626 +#define WM9081_ARA_ENA_SHIFT 3 /* ARA_ENA */
  627 +#define WM9081_ARA_ENA_WIDTH 1 /* ARA_ENA */
  628 +#define WM9081_AUTO_INC 0x0002 /* AUTO_INC */
  629 +#define WM9081_AUTO_INC_MASK 0x0002 /* AUTO_INC */
  630 +#define WM9081_AUTO_INC_SHIFT 1 /* AUTO_INC */
  631 +#define WM9081_AUTO_INC_WIDTH 1 /* AUTO_INC */
  632 +
  633 +/*
  634 + * R42 (0x2A) - EQ 1
  635 + */
  636 +#define WM9081_EQ_B1_GAIN_MASK 0xF800 /* EQ_B1_GAIN - [15:11] */
  637 +#define WM9081_EQ_B1_GAIN_SHIFT 11 /* EQ_B1_GAIN - [15:11] */
  638 +#define WM9081_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [15:11] */
  639 +#define WM9081_EQ_B2_GAIN_MASK 0x07C0 /* EQ_B2_GAIN - [10:6] */
  640 +#define WM9081_EQ_B2_GAIN_SHIFT 6 /* EQ_B2_GAIN - [10:6] */
  641 +#define WM9081_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [10:6] */
  642 +#define WM9081_EQ_B4_GAIN_MASK 0x003E /* EQ_B4_GAIN - [5:1] */
  643 +#define WM9081_EQ_B4_GAIN_SHIFT 1 /* EQ_B4_GAIN - [5:1] */
  644 +#define WM9081_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [5:1] */
  645 +#define WM9081_EQ_ENA 0x0001 /* EQ_ENA */
  646 +#define WM9081_EQ_ENA_MASK 0x0001 /* EQ_ENA */
  647 +#define WM9081_EQ_ENA_SHIFT 0 /* EQ_ENA */
  648 +#define WM9081_EQ_ENA_WIDTH 1 /* EQ_ENA */
  649 +
  650 +/*
  651 + * R43 (0x2B) - EQ 2
  652 + */
  653 +#define WM9081_EQ_B3_GAIN_MASK 0xF800 /* EQ_B3_GAIN - [15:11] */
  654 +#define WM9081_EQ_B3_GAIN_SHIFT 11 /* EQ_B3_GAIN - [15:11] */
  655 +#define WM9081_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [15:11] */
  656 +#define WM9081_EQ_B5_GAIN_MASK 0x07C0 /* EQ_B5_GAIN - [10:6] */
  657 +#define WM9081_EQ_B5_GAIN_SHIFT 6 /* EQ_B5_GAIN - [10:6] */
  658 +#define WM9081_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [10:6] */
  659 +
  660 +/*
  661 + * R44 (0x2C) - EQ 3
  662 + */
  663 +#define WM9081_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */
  664 +#define WM9081_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */
  665 +#define WM9081_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */
  666 +
  667 +/*
  668 + * R45 (0x2D) - EQ 4
  669 + */
  670 +#define WM9081_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */
  671 +#define WM9081_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */
  672 +#define WM9081_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */
  673 +
  674 +/*
  675 + * R46 (0x2E) - EQ 5
  676 + */
  677 +#define WM9081_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */
  678 +#define WM9081_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */
  679 +#define WM9081_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */
  680 +
  681 +/*
  682 + * R47 (0x2F) - EQ 6
  683 + */
  684 +#define WM9081_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */
  685 +#define WM9081_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */
  686 +#define WM9081_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */
  687 +
  688 +/*
  689 + * R48 (0x30) - EQ 7
  690 + */
  691 +#define WM9081_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */
  692 +#define WM9081_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */
  693 +#define WM9081_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */
  694 +
  695 +/*
  696 + * R49 (0x31) - EQ 8
  697 + */
  698 +#define WM9081_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */
  699 +#define WM9081_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */
  700 +#define WM9081_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */
  701 +
  702 +/*
  703 + * R50 (0x32) - EQ 9
  704 + */
  705 +#define WM9081_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */
  706 +#define WM9081_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */
  707 +#define WM9081_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */
  708 +
  709 +/*
  710 + * R51 (0x33) - EQ 10
  711 + */
  712 +#define WM9081_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */
  713 +#define WM9081_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */
  714 +#define WM9081_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */
  715 +
  716 +/*
  717 + * R52 (0x34) - EQ 11
  718 + */
  719 +#define WM9081_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */
  720 +#define WM9081_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */
  721 +#define WM9081_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */
  722 +
  723 +/*
  724 + * R53 (0x35) - EQ 12
  725 + */
  726 +#define WM9081_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */
  727 +#define WM9081_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */
  728 +#define WM9081_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */
  729 +
  730 +/*
  731 + * R54 (0x36) - EQ 13
  732 + */
  733 +#define WM9081_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */
  734 +#define WM9081_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */
  735 +#define WM9081_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */
  736 +
  737 +/*
  738 + * R55 (0x37) - EQ 14
  739 + */
  740 +#define WM9081_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */
  741 +#define WM9081_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */
  742 +#define WM9081_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */
  743 +
  744 +/*
  745 + * R56 (0x38) - EQ 15
  746 + */
  747 +#define WM9081_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */
  748 +#define WM9081_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */
  749 +#define WM9081_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */
  750 +
  751 +/*
  752 + * R57 (0x39) - EQ 16
  753 + */
  754 +#define WM9081_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */
  755 +#define WM9081_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */
  756 +#define WM9081_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */
  757 +
  758 +/*
  759 + * R58 (0x3A) - EQ 17
  760 + */
  761 +#define WM9081_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */
  762 +#define WM9081_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */
  763 +#define WM9081_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */
  764 +
  765 +/*
  766 + * R59 (0x3B) - EQ 18
  767 + */
  768 +#define WM9081_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */
  769 +#define WM9081_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */
  770 +#define WM9081_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */
  771 +
  772 +/*
  773 + * R60 (0x3C) - EQ 19
  774 + */
  775 +#define WM9081_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */
  776 +#define WM9081_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */
  777 +#define WM9081_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */
  778 +
  779 +/*
  780 + * R61 (0x3D) - EQ 20
  781 + */
  782 +#define WM9081_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */
  783 +#define WM9081_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */
  784 +#define WM9081_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */
  785 +
  786 +
  787 +#endif