summaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/88pm860x-codec.c1486
-rw-r--r--sound/soc/codecs/88pm860x-codec.h97
-rw-r--r--sound/soc/codecs/Kconfig27
-rw-r--r--sound/soc/codecs/Makefile12
-rw-r--r--sound/soc/codecs/ac97.c125
-rw-r--r--sound/soc/codecs/ac97.h19
-rw-r--r--sound/soc/codecs/ad1836.c191
-rw-r--r--sound/soc/codecs/ad1836.h2
-rw-r--r--sound/soc/codecs/ad193x.c217
-rw-r--r--sound/soc/codecs/ad193x.h3
-rw-r--r--sound/soc/codecs/ad1980.c113
-rw-r--r--sound/soc/codecs/ad1980.h3
-rw-r--r--sound/soc/codecs/ad73311.c66
-rw-r--r--sound/soc/codecs/ad73311.h2
-rw-r--r--sound/soc/codecs/ads117x.c72
-rw-r--r--sound/soc/codecs/ads117x.h4
-rw-r--r--sound/soc/codecs/ak4104.c149
-rw-r--r--sound/soc/codecs/ak4104.h7
-rw-r--r--sound/soc/codecs/ak4535.c236
-rw-r--r--sound/soc/codecs/ak4535.h8
-rw-r--r--sound/soc/codecs/ak4642.c235
-rw-r--r--sound/soc/codecs/ak4642.h20
-rw-r--r--sound/soc/codecs/ak4671.c140
-rw-r--r--sound/soc/codecs/ak4671.h3
-rw-r--r--sound/soc/codecs/cq93vc.c132
-rw-r--r--sound/soc/codecs/cq93vc.h29
-rw-r--r--sound/soc/codecs/cs4270.c394
-rw-r--r--sound/soc/codecs/cs4270.h28
-rw-r--r--sound/soc/codecs/cs42l51.c295
-rw-r--r--sound/soc/codecs/cs42l51.h2
-rw-r--r--sound/soc/codecs/cx20442.c173
-rw-r--r--sound/soc/codecs/cx20442.h2
-rw-r--r--sound/soc/codecs/da7210.c163
-rw-r--r--sound/soc/codecs/da7210.h24
-rw-r--r--sound/soc/codecs/jz4740.c116
-rw-r--r--sound/soc/codecs/jz4740.h20
-rw-r--r--sound/soc/codecs/max98088.c2109
-rw-r--r--sound/soc/codecs/max98088.h193
-rw-r--r--sound/soc/codecs/pcm3008.c92
-rw-r--r--sound/soc/codecs/pcm3008.h3
-rw-r--r--sound/soc/codecs/spdif_transciever.c102
-rw-r--r--sound/soc/codecs/spdif_transciever.h18
-rw-r--r--sound/soc/codecs/ssm2602.c218
-rw-r--r--sound/soc/codecs/ssm2602.h3
-rw-r--r--sound/soc/codecs/stac9766.c119
-rw-r--r--sound/soc/codecs/stac9766.h4
-rw-r--r--sound/soc/codecs/tlv320aic23.c182
-rw-r--r--sound/soc/codecs/tlv320aic23.h3
-rw-r--r--sound/soc/codecs/tlv320aic26.c180
-rw-r--r--sound/soc/codecs/tlv320aic26.h3
-rw-r--r--sound/soc/codecs/tlv320aic3x.c1236
-rw-r--r--sound/soc/codecs/tlv320aic3x.h100
-rw-r--r--sound/soc/codecs/tlv320dac33.c308
-rw-r--r--sound/soc/codecs/tlv320dac33.h3
-rw-r--r--sound/soc/codecs/tpa6130a2.c38
-rw-r--r--sound/soc/codecs/twl4030.c228
-rw-r--r--sound/soc/codecs/twl4030.h55
-rw-r--r--sound/soc/codecs/twl6040.c170
-rw-r--r--sound/soc/codecs/twl6040.h3
-rw-r--r--sound/soc/codecs/uda134x.c155
-rw-r--r--sound/soc/codecs/uda134x.h3
-rw-r--r--sound/soc/codecs/uda1380.c331
-rw-r--r--sound/soc/codecs/uda1380.h3
-rw-r--r--sound/soc/codecs/wl1273.c528
-rw-r--r--sound/soc/codecs/wl1273.h101
-rw-r--r--sound/soc/codecs/wm2000.h3
-rw-r--r--sound/soc/codecs/wm8350.c240
-rw-r--r--sound/soc/codecs/wm8350.h3
-rw-r--r--sound/soc/codecs/wm8400.c181
-rw-r--r--sound/soc/codecs/wm8400.h3
-rw-r--r--sound/soc/codecs/wm8510.c288
-rw-r--r--sound/soc/codecs/wm8510.h3
-rw-r--r--sound/soc/codecs/wm8523.c178
-rw-r--r--sound/soc/codecs/wm8523.h3
-rw-r--r--sound/soc/codecs/wm8580.c321
-rw-r--r--sound/soc/codecs/wm8580.h17
-rw-r--r--sound/soc/codecs/wm8711.c203
-rw-r--r--sound/soc/codecs/wm8711.h3
-rw-r--r--sound/soc/codecs/wm8727.c106
-rw-r--r--sound/soc/codecs/wm8727.h21
-rw-r--r--sound/soc/codecs/wm8728.c289
-rw-r--r--sound/soc/codecs/wm8728.h9
-rw-r--r--sound/soc/codecs/wm8731.c247
-rw-r--r--sound/soc/codecs/wm8731.h7
-rw-r--r--sound/soc/codecs/wm8741.c378
-rw-r--r--sound/soc/codecs/wm8741.h3
-rw-r--r--sound/soc/codecs/wm8750.c264
-rw-r--r--sound/soc/codecs/wm8750.h9
-rw-r--r--sound/soc/codecs/wm8753.c404
-rw-r--r--sound/soc/codecs/wm8753.h3
-rw-r--r--sound/soc/codecs/wm8776.c249
-rw-r--r--sound/soc/codecs/wm8776.h3
-rw-r--r--sound/soc/codecs/wm8804.c833
-rw-r--r--sound/soc/codecs/wm8804.h61
-rw-r--r--sound/soc/codecs/wm8900.c250
-rw-r--r--sound/soc/codecs/wm8900.h3
-rw-r--r--sound/soc/codecs/wm8903.c265
-rw-r--r--sound/soc/codecs/wm8903.h3
-rw-r--r--sound/soc/codecs/wm8904.c210
-rw-r--r--sound/soc/codecs/wm8904.h3
-rw-r--r--sound/soc/codecs/wm8940.c199
-rw-r--r--sound/soc/codecs/wm8940.h2
-rw-r--r--sound/soc/codecs/wm8955.c181
-rw-r--r--sound/soc/codecs/wm8955.h3
-rw-r--r--sound/soc/codecs/wm8960.c209
-rw-r--r--sound/soc/codecs/wm8960.h3
-rw-r--r--sound/soc/codecs/wm8961.c241
-rw-r--r--sound/soc/codecs/wm8961.h3
-rw-r--r--sound/soc/codecs/wm8962.c3980
-rw-r--r--sound/soc/codecs/wm8962.h3780
-rw-r--r--sound/soc/codecs/wm8971.c247
-rw-r--r--sound/soc/codecs/wm8971.h8
-rw-r--r--sound/soc/codecs/wm8974.c167
-rw-r--r--sound/soc/codecs/wm8974.h3
-rw-r--r--sound/soc/codecs/wm8978.c190
-rw-r--r--sound/soc/codecs/wm8978.h3
-rw-r--r--sound/soc/codecs/wm8985.c1192
-rw-r--r--sound/soc/codecs/wm8985.h1045
-rw-r--r--sound/soc/codecs/wm8988.c261
-rw-r--r--sound/soc/codecs/wm8988.h3
-rw-r--r--sound/soc/codecs/wm8990.c223
-rw-r--r--sound/soc/codecs/wm8990.h8
-rw-r--r--sound/soc/codecs/wm8993.c304
-rw-r--r--sound/soc/codecs/wm8993.h3
-rw-r--r--sound/soc/codecs/wm8994.c3412
-rw-r--r--sound/soc/codecs/wm8994.h3
-rw-r--r--sound/soc/codecs/wm9081.c208
-rw-r--r--sound/soc/codecs/wm9081.h3
-rw-r--r--sound/soc/codecs/wm9090.c185
-rw-r--r--sound/soc/codecs/wm9090.h2
-rw-r--r--sound/soc/codecs/wm9705.c116
-rw-r--r--sound/soc/codecs/wm9705.h3
-rw-r--r--sound/soc/codecs/wm9712.c124
-rw-r--r--sound/soc/codecs/wm9712.h3
-rw-r--r--sound/soc/codecs/wm9713.c131
-rw-r--r--sound/soc/codecs/wm9713.h3
-rw-r--r--sound/soc/codecs/wm_hubs.c2
137 files changed, 21781 insertions, 10844 deletions
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
new file mode 100644
index 000000000000..01d19e9f53f9
--- /dev/null
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -0,0 +1,1486 @@
+/*
+ * 88pm860x-codec.c -- 88PM860x ALSA SoC Audio Driver
+ *
+ * Copyright 2010 Marvell International Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/88pm860x.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/initval.h>
+#include <sound/jack.h>
+
+#include "88pm860x-codec.h"
+
+#define MAX_NAME_LEN 20
+#define REG_CACHE_SIZE 0x40
+#define REG_CACHE_BASE 0xb0
+
+/* Status Register 1 (0x01) */
+#define REG_STATUS_1 0x01
+#define MIC_STATUS (1 << 7)
+#define HOOK_STATUS (1 << 6)
+#define HEADSET_STATUS (1 << 5)
+
+/* Mic Detection Register (0x37) */
+#define REG_MIC_DET 0x37
+#define CONTINUOUS_POLLING (3 << 1)
+#define EN_MIC_DET (1 << 0)
+#define MICDET_MASK 0x07
+
+/* Headset Detection Register (0x38) */
+#define REG_HS_DET 0x38
+#define EN_HS_DET (1 << 0)
+
+/* Misc2 Register (0x42) */
+#define REG_MISC2 0x42
+#define AUDIO_PLL (1 << 5)
+#define AUDIO_SECTION_RESET (1 << 4)
+#define AUDIO_SECTION_ON (1 << 3)
+
+/* PCM Interface Register 2 (0xb1) */
+#define PCM_INF2_BCLK (1 << 6) /* Bit clock polarity */
+#define PCM_INF2_FS (1 << 5) /* Frame Sync polarity */
+#define PCM_INF2_MASTER (1 << 4) /* Master / Slave */
+#define PCM_INF2_18WL (1 << 3) /* 18 / 16 bits */
+#define PCM_GENERAL_I2S 0
+#define PCM_EXACT_I2S 1
+#define PCM_LEFT_I2S 2
+#define PCM_RIGHT_I2S 3
+#define PCM_SHORT_FS 4
+#define PCM_LONG_FS 5
+#define PCM_MODE_MASK 7
+
+/* I2S Interface Register 4 (0xbe) */
+#define I2S_EQU_BYP (1 << 6)
+
+/* DAC Offset Register (0xcb) */
+#define DAC_MUTE (1 << 7)
+#define MUTE_LEFT (1 << 6)
+#define MUTE_RIGHT (1 << 2)
+
+/* ADC Analog Register 1 (0xd0) */
+#define REG_ADC_ANA_1 0xd0
+#define MIC1BIAS_MASK 0x60
+
+/* Earpiece/Speaker Control Register 2 (0xda) */
+#define REG_EAR2 0xda
+#define RSYNC_CHANGE (1 << 2)
+
+/* Audio Supplies Register 2 (0xdc) */
+#define REG_SUPPLIES2 0xdc
+#define LDO15_READY (1 << 4)
+#define LDO15_EN (1 << 3)
+#define CPUMP_READY (1 << 2)
+#define CPUMP_EN (1 << 1)
+#define AUDIO_EN (1 << 0)
+#define SUPPLY_MASK (LDO15_EN | CPUMP_EN | AUDIO_EN)
+
+/* Audio Enable Register 1 (0xdd) */
+#define ADC_MOD_RIGHT (1 << 1)
+#define ADC_MOD_LEFT (1 << 0)
+
+/* Audio Enable Register 2 (0xde) */
+#define ADC_LEFT (1 << 5)
+#define ADC_RIGHT (1 << 4)
+
+/* DAC Enable Register 2 (0xe1) */
+#define DAC_LEFT (1 << 5)
+#define DAC_RIGHT (1 << 4)
+#define MODULATOR (1 << 3)
+
+/* Shorts Register (0xeb) */
+#define REG_SHORTS 0xeb
+#define CLR_SHORT_LO2 (1 << 7)
+#define SHORT_LO2 (1 << 6)
+#define CLR_SHORT_LO1 (1 << 5)
+#define SHORT_LO1 (1 << 4)
+#define CLR_SHORT_HS2 (1 << 3)
+#define SHORT_HS2 (1 << 2)
+#define CLR_SHORT_HS1 (1 << 1)
+#define SHORT_HS1 (1 << 0)
+
+/*
+ * This widget should be just after DAC & PGA in DAPM power-on sequence and
+ * before DAC & PGA in DAPM power-off sequence.
+ */
+#define PM860X_DAPM_OUTPUT(wname, wevent) \
+{ .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+ .shift = 0, .invert = 0, .kcontrols = NULL, \
+ .num_kcontrols = 0, .event = wevent, \
+ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, }
+
+struct pm860x_det {
+ struct snd_soc_jack *hp_jack;
+ struct snd_soc_jack *mic_jack;
+ int hp_det;
+ int mic_det;
+ int hook_det;
+ int hs_shrt;
+ int lo_shrt;
+};
+
+struct pm860x_priv {
+ unsigned int sysclk;
+ unsigned int pcmclk;
+ unsigned int dir;
+ unsigned int filter;
+ struct snd_soc_codec *codec;
+ struct i2c_client *i2c;
+ struct pm860x_chip *chip;
+ struct pm860x_det det;
+
+ int irq[4];
+ unsigned char name[4][MAX_NAME_LEN];
+ unsigned char reg_cache[REG_CACHE_SIZE];
+};
+
+/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */
+static const DECLARE_TLV_DB_SCALE(dpga_tlv, -9450, 150, 1);
+
+/* -9dB to 0db in 3dB steps */
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0);
+
+/* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */
+static const unsigned int mic_tlv[] = {
+ TLV_DB_RANGE_HEAD(5),
+ 0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0),
+ 3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0),
+ 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0),
+};
+
+/* {0, 0, 0, -6, 0, 6, 12, 18}dB */
+static const unsigned int aux_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 2, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0),
+};
+
+/* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */
+static const unsigned int out_tlv[] = {
+ TLV_DB_RANGE_HEAD(4),
+ 0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1),
+ 4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0),
+ 5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0),
+ 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0),
+};
+
+static const unsigned int st_tlv[] = {
+ TLV_DB_RANGE_HEAD(8),
+ 0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0),
+ 2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0),
+ 4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0),
+ 6, 7, TLV_DB_SCALE_ITEM(-10351, 116, 0),
+ 8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0),
+ 10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0),
+ 14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0),
+ 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0),
+};
+
+/* Sidetone Gain = M * 2^(-5-N) */
+struct st_gain {
+ unsigned int db;
+ unsigned int m;
+ unsigned int n;
+};
+
+static struct st_gain st_table[] = {
+ {-12041, 1, 15}, {-11439, 1, 14}, {-11087, 3, 15}, {-10837, 1, 13},
+ {-10643, 5, 15}, {-10485, 3, 14}, {-10351, 7, 15}, {-10235, 1, 12},
+ {-10133, 9, 15}, {-10041, 5, 14}, { -9958, 11, 15}, { -9883, 3, 13},
+ { -9813, 13, 15}, { -9749, 7, 14}, { -9689, 15, 15}, { -9633, 1, 11},
+ { -9580, 17, 15}, { -9531, 9, 14}, { -9484, 19, 15}, { -9439, 5, 13},
+ { -9397, 21, 15}, { -9356, 11, 14}, { -9318, 23, 15}, { -9281, 3, 12},
+ { -9245, 25, 15}, { -9211, 13, 14}, { -9178, 27, 15}, { -9147, 7, 13},
+ { -9116, 29, 15}, { -9087, 15, 14}, { -9058, 31, 15}, { -9031, 1, 10},
+ { -8978, 17, 14}, { -8929, 9, 13}, { -8882, 19, 14}, { -8837, 5, 12},
+ { -8795, 21, 14}, { -8754, 11, 13}, { -8716, 23, 14}, { -8679, 3, 11},
+ { -8643, 25, 14}, { -8609, 13, 13}, { -8576, 27, 14}, { -8545, 7, 12},
+ { -8514, 29, 14}, { -8485, 15, 13}, { -8456, 31, 14}, { -8429, 1, 9},
+ { -8376, 17, 13}, { -8327, 9, 12}, { -8280, 19, 13}, { -8235, 5, 11},
+ { -8193, 21, 13}, { -8152, 11, 12}, { -8114, 23, 13}, { -8077, 3, 10},
+ { -8041, 25, 13}, { -8007, 13, 12}, { -7974, 27, 13}, { -7943, 7, 11},
+ { -7912, 29, 13}, { -7883, 15, 12}, { -7854, 31, 13}, { -7827, 1, 8},
+ { -7774, 17, 12}, { -7724, 9, 11}, { -7678, 19, 12}, { -7633, 5, 10},
+ { -7591, 21, 12}, { -7550, 11, 11}, { -7512, 23, 12}, { -7475, 3, 9},
+ { -7439, 25, 12}, { -7405, 13, 11}, { -7372, 27, 12}, { -7341, 7, 10},
+ { -7310, 29, 12}, { -7281, 15, 11}, { -7252, 31, 12}, { -7225, 1, 7},
+ { -7172, 17, 11}, { -7122, 9, 10}, { -7075, 19, 11}, { -7031, 5, 9},
+ { -6989, 21, 11}, { -6948, 11, 10}, { -6910, 23, 11}, { -6873, 3, 8},
+ { -6837, 25, 11}, { -6803, 13, 10}, { -6770, 27, 11}, { -6739, 7, 9},
+ { -6708, 29, 11}, { -6679, 15, 10}, { -6650, 31, 11}, { -6623, 1, 6},
+ { -6570, 17, 10}, { -6520, 9, 9}, { -6473, 19, 10}, { -6429, 5, 8},
+ { -6386, 21, 10}, { -6346, 11, 9}, { -6307, 23, 10}, { -6270, 3, 7},
+ { -6235, 25, 10}, { -6201, 13, 9}, { -6168, 27, 10}, { -6137, 7, 8},
+ { -6106, 29, 10}, { -6077, 15, 9}, { -6048, 31, 10}, { -6021, 1, 5},
+ { -5968, 17, 9}, { -5918, 9, 8}, { -5871, 19, 9}, { -5827, 5, 7},
+ { -5784, 21, 9}, { -5744, 11, 8}, { -5705, 23, 9}, { -5668, 3, 6},
+ { -5633, 25, 9}, { -5599, 13, 8}, { -5566, 27, 9}, { -5535, 7, 7},
+ { -5504, 29, 9}, { -5475, 15, 8}, { -5446, 31, 9}, { -5419, 1, 4},
+ { -5366, 17, 8}, { -5316, 9, 7}, { -5269, 19, 8}, { -5225, 5, 6},
+ { -5182, 21, 8}, { -5142, 11, 7}, { -5103, 23, 8}, { -5066, 3, 5},
+ { -5031, 25, 8}, { -4997, 13, 7}, { -4964, 27, 8}, { -4932, 7, 6},
+ { -4902, 29, 8}, { -4873, 15, 7}, { -4844, 31, 8}, { -4816, 1, 3},
+ { -4764, 17, 7}, { -4714, 9, 6}, { -4667, 19, 7}, { -4623, 5, 5},
+ { -4580, 21, 7}, { -4540, 11, 6}, { -4501, 23, 7}, { -4464, 3, 4},
+ { -4429, 25, 7}, { -4395, 13, 6}, { -4362, 27, 7}, { -4330, 7, 5},
+ { -4300, 29, 7}, { -4270, 15, 6}, { -4242, 31, 7}, { -4214, 1, 2},
+ { -4162, 17, 6}, { -4112, 9, 5}, { -4065, 19, 6}, { -4021, 5, 4},
+ { -3978, 21, 6}, { -3938, 11, 5}, { -3899, 23, 6}, { -3862, 3, 3},
+ { -3827, 25, 6}, { -3793, 13, 5}, { -3760, 27, 6}, { -3728, 7, 4},
+ { -3698, 29, 6}, { -3668, 15, 5}, { -3640, 31, 6}, { -3612, 1, 1},
+ { -3560, 17, 5}, { -3510, 9, 4}, { -3463, 19, 5}, { -3419, 5, 3},
+ { -3376, 21, 5}, { -3336, 11, 4}, { -3297, 23, 5}, { -3260, 3, 2},
+ { -3225, 25, 5}, { -3191, 13, 4}, { -3158, 27, 5}, { -3126, 7, 3},
+ { -3096, 29, 5}, { -3066, 15, 4}, { -3038, 31, 5}, { -3010, 1, 0},
+ { -2958, 17, 4}, { -2908, 9, 3}, { -2861, 19, 4}, { -2816, 5, 2},
+ { -2774, 21, 4}, { -2734, 11, 3}, { -2695, 23, 4}, { -2658, 3, 1},
+ { -2623, 25, 4}, { -2589, 13, 3}, { -2556, 27, 4}, { -2524, 7, 2},
+ { -2494, 29, 4}, { -2464, 15, 3}, { -2436, 31, 4}, { -2408, 2, 0},
+ { -2356, 17, 3}, { -2306, 9, 2}, { -2259, 19, 3}, { -2214, 5, 1},
+ { -2172, 21, 3}, { -2132, 11, 2}, { -2093, 23, 3}, { -2056, 3, 0},
+ { -2021, 25, 3}, { -1987, 13, 2}, { -1954, 27, 3}, { -1922, 7, 1},
+ { -1892, 29, 3}, { -1862, 15, 2}, { -1834, 31, 3}, { -1806, 4, 0},
+ { -1754, 17, 2}, { -1704, 9, 1}, { -1657, 19, 2}, { -1612, 5, 0},
+ { -1570, 21, 2}, { -1530, 11, 1}, { -1491, 23, 2}, { -1454, 6, 0},
+ { -1419, 25, 2}, { -1384, 13, 1}, { -1352, 27, 2}, { -1320, 7, 0},
+ { -1290, 29, 2}, { -1260, 15, 1}, { -1232, 31, 2}, { -1204, 8, 0},
+ { -1151, 17, 1}, { -1102, 9, 0}, { -1055, 19, 1}, { -1010, 10, 0},
+ { -968, 21, 1}, { -928, 11, 0}, { -889, 23, 1}, { -852, 12, 0},
+ { -816, 25, 1}, { -782, 13, 0}, { -750, 27, 1}, { -718, 14, 0},
+ { -688, 29, 1}, { -658, 15, 0}, { -630, 31, 1}, { -602, 16, 0},
+ { -549, 17, 0}, { -500, 18, 0}, { -453, 19, 0}, { -408, 20, 0},
+ { -366, 21, 0}, { -325, 22, 0}, { -287, 23, 0}, { -250, 24, 0},
+ { -214, 25, 0}, { -180, 26, 0}, { -148, 27, 0}, { -116, 28, 0},
+ { -86, 29, 0}, { -56, 30, 0}, { -28, 31, 0}, { 0, 0, 0},
+};
+
+static int pm860x_volatile(unsigned int reg)
+{
+ BUG_ON(reg >= REG_CACHE_SIZE);
+
+ switch (reg) {
+ case PM860X_AUDIO_SUPPLIES_2:
+ return 1;
+ }
+
+ return 0;
+}
+
+static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ unsigned char *cache = codec->reg_cache;
+
+ BUG_ON(reg >= REG_CACHE_SIZE);
+
+ if (pm860x_volatile(reg))
+ return cache[reg];
+
+ reg += REG_CACHE_BASE;
+
+ return pm860x_reg_read(codec->control_data, reg);
+}
+
+static int pm860x_write_reg_cache(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ unsigned char *cache = codec->reg_cache;
+
+ BUG_ON(reg >= REG_CACHE_SIZE);
+
+ if (!pm860x_volatile(reg))
+ cache[reg] = (unsigned char)value;
+
+ reg += REG_CACHE_BASE;
+
+ return pm860x_reg_write(codec->control_data, reg, value);
+}
+
+static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ int val[2], val2[2], i;
+
+ val[0] = snd_soc_read(codec, reg) & 0x3f;
+ val[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT) >> 4) & 0xf;
+ val2[0] = snd_soc_read(codec, reg2) & 0x3f;
+ val2[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT)) & 0xf;
+
+ for (i = 0; i < ARRAY_SIZE(st_table); i++) {
+ if ((st_table[i].m == val[0]) && (st_table[i].n == val[1]))
+ ucontrol->value.integer.value[0] = i;
+ if ((st_table[i].m == val2[0]) && (st_table[i].n == val2[1]))
+ ucontrol->value.integer.value[1] = i;
+ }
+ return 0;
+}
+
+static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ int err;
+ unsigned int val, val2;
+
+ val = ucontrol->value.integer.value[0];
+ val2 = ucontrol->value.integer.value[1];
+
+ err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m);
+ if (err < 0)
+ return err;
+ err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0xf0,
+ st_table[val].n << 4);
+ if (err < 0)
+ return err;
+
+ err = snd_soc_update_bits(codec, reg2, 0x3f, st_table[val2].m);
+ if (err < 0)
+ return err;
+ err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0x0f,
+ st_table[val2].n);
+ return err;
+}
+
+static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ int max = mc->max, val, val2;
+ unsigned int mask = (1 << fls(max)) - 1;
+
+ val = snd_soc_read(codec, reg) >> shift;
+ val2 = snd_soc_read(codec, reg2) >> shift;
+ ucontrol->value.integer.value[0] = (max - val) & mask;
+ ucontrol->value.integer.value[1] = (max - val2) & mask;
+
+ return 0;
+}
+
+static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
+ unsigned int shift = mc->shift;
+ int max = mc->max;
+ unsigned int mask = (1 << fls(max)) - 1;
+ int err;
+ unsigned int val, val2, val_mask;
+
+ val_mask = mask << shift;
+ val = ((max - ucontrol->value.integer.value[0]) & mask);
+ val2 = ((max - ucontrol->value.integer.value[1]) & mask);
+
+ val = val << shift;
+ val2 = val2 << shift;
+
+ err = snd_soc_update_bits(codec, reg, val_mask, val);
+ if (err < 0)
+ return err;
+
+ err = snd_soc_update_bits(codec, reg2, val_mask, val2);
+ return err;
+}
+
+/* DAPM Widget Events */
+/*
+ * A lot registers are belong to RSYNC domain. It requires enabling RSYNC bit
+ * after updating these registers. Otherwise, these updated registers won't
+ * be effective.
+ */
+static int pm860x_rsync_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ /*
+ * In order to avoid current on the load, mute power-on and power-off
+ * should be transients.
+ * Unmute by DAC_MUTE. It should be unmuted when DAPM sequence is
+ * finished.
+ */
+ snd_soc_update_bits(codec, PM860X_DAC_OFFSET, DAC_MUTE, 0);
+ snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+ RSYNC_CHANGE, RSYNC_CHANGE);
+ return 0;
+}
+
+static int pm860x_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ unsigned int dac = 0;
+ int data;
+
+ if (!strcmp(w->name, "Left DAC"))
+ dac = DAC_LEFT;
+ if (!strcmp(w->name, "Right DAC"))
+ dac = DAC_RIGHT;
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (dac) {
+ /* Auto mute in power-on sequence. */
+ dac |= MODULATOR;
+ snd_soc_update_bits(codec, PM860X_DAC_OFFSET,
+ DAC_MUTE, DAC_MUTE);
+ snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+ RSYNC_CHANGE, RSYNC_CHANGE);
+ /* update dac */
+ snd_soc_update_bits(codec, PM860X_DAC_EN_2,
+ dac, dac);
+ }
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ if (dac) {
+ /* Auto mute in power-off sequence. */
+ snd_soc_update_bits(codec, PM860X_DAC_OFFSET,
+ DAC_MUTE, DAC_MUTE);
+ snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+ RSYNC_CHANGE, RSYNC_CHANGE);
+ /* update dac */
+ data = snd_soc_read(codec, PM860X_DAC_EN_2);
+ data &= ~dac;
+ if (!(data & (DAC_LEFT | DAC_RIGHT)))
+ data &= ~MODULATOR;
+ snd_soc_write(codec, PM860X_DAC_EN_2, data);
+ }
+ break;
+ }
+ return 0;
+}
+
+static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"};
+
+static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"};
+
+static const struct soc_enum pm860x_hs1_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_hs2_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_hs1_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_hs2_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_lo1_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_lo2_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_lo1_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_lo2_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_spk_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_ear_pa_enum =
+ SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_spk_ear_opamp_enum =
+ SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts);
+
+static const struct snd_kcontrol_new pm860x_snd_controls[] = {
+ SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2,
+ PM860X_ADC_ANA_3, 6, 3, 0, adc_tlv),
+ SOC_DOUBLE_TLV("AUX Capture Volume", PM860X_ADC_ANA_3, 0, 3, 7, 0,
+ aux_tlv),
+ SOC_SINGLE_TLV("MIC1 Capture Volume", PM860X_ADC_ANA_2, 0, 7, 0,
+ mic_tlv),
+ SOC_SINGLE_TLV("MIC3 Capture Volume", PM860X_ADC_ANA_2, 3, 7, 0,
+ mic_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Sidetone Volume", PM860X_SIDETONE_L_GAIN,
+ PM860X_SIDETONE_R_GAIN, 0, ARRAY_SIZE(st_table)-1,
+ 0, snd_soc_get_volsw_2r_st,
+ snd_soc_put_volsw_2r_st, st_tlv),
+ SOC_SINGLE_TLV("Speaker Playback Volume", PM860X_EAR_CTRL_1,
+ 0, 7, 0, out_tlv),
+ SOC_DOUBLE_R_TLV("Line Playback Volume", PM860X_LO1_CTRL,
+ PM860X_LO2_CTRL, 0, 7, 0, out_tlv),
+ SOC_DOUBLE_R_TLV("Headset Playback Volume", PM860X_HS1_CTRL,
+ PM860X_HS2_CTRL, 0, 7, 0, out_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Hifi Left Playback Volume",
+ PM860X_HIFIL_GAIN_LEFT,
+ PM860X_HIFIL_GAIN_RIGHT, 0, 63, 0,
+ snd_soc_get_volsw_2r_out,
+ snd_soc_put_volsw_2r_out, dpga_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Hifi Right Playback Volume",
+ PM860X_HIFIR_GAIN_LEFT,
+ PM860X_HIFIR_GAIN_RIGHT, 0, 63, 0,
+ snd_soc_get_volsw_2r_out,
+ snd_soc_put_volsw_2r_out, dpga_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Lofi Playback Volume", PM860X_LOFI_GAIN_LEFT,
+ PM860X_LOFI_GAIN_RIGHT, 0, 63, 0,
+ snd_soc_get_volsw_2r_out,
+ snd_soc_put_volsw_2r_out, dpga_tlv),
+ SOC_ENUM("Headset1 Operational Amplifier Current",
+ pm860x_hs1_opamp_enum),
+ SOC_ENUM("Headset2 Operational Amplifier Current",
+ pm860x_hs2_opamp_enum),
+ SOC_ENUM("Headset1 Amplifier Current", pm860x_hs1_pa_enum),
+ SOC_ENUM("Headset2 Amplifier Current", pm860x_hs2_pa_enum),
+ SOC_ENUM("Lineout1 Operational Amplifier Current",
+ pm860x_lo1_opamp_enum),
+ SOC_ENUM("Lineout2 Operational Amplifier Current",
+ pm860x_lo2_opamp_enum),
+ SOC_ENUM("Lineout1 Amplifier Current", pm860x_lo1_pa_enum),
+ SOC_ENUM("Lineout2 Amplifier Current", pm860x_lo2_pa_enum),
+ SOC_ENUM("Speaker Operational Amplifier Current",
+ pm860x_spk_ear_opamp_enum),
+ SOC_ENUM("Speaker Amplifier Current", pm860x_spk_pa_enum),
+ SOC_ENUM("Earpiece Amplifier Current", pm860x_ear_pa_enum),
+};
+
+/*
+ * DAPM Controls
+ */
+
+/* PCM Switch / PCM Interface */
+static const struct snd_kcontrol_new pcm_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0);
+
+/* AUX1 Switch */
+static const struct snd_kcontrol_new aux1_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0);
+
+/* AUX2 Switch */
+static const struct snd_kcontrol_new aux2_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 5, 1, 0);
+
+/* Left Ex. PA Switch */
+static const struct snd_kcontrol_new lepa_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 2, 1, 0);
+
+/* Right Ex. PA Switch */
+static const struct snd_kcontrol_new repa_switch_controls =
+ SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0);
+
+/* PCM Mux / Mux7 */
+static const char *aif1_text[] = {
+ "PCM L", "PCM R",
+};
+
+static const struct soc_enum aif1_enum =
+ SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text);
+
+static const struct snd_kcontrol_new aif1_mux =
+ SOC_DAPM_ENUM("PCM Mux", aif1_enum);
+
+/* I2S Mux / Mux9 */
+static const char *i2s_din_text[] = {
+ "DIN", "DIN1",
+};
+
+static const struct soc_enum i2s_din_enum =
+ SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text);
+
+static const struct snd_kcontrol_new i2s_din_mux =
+ SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum);
+
+/* I2S Mic Mux / Mux8 */
+static const char *i2s_mic_text[] = {
+ "Ex PA", "ADC",
+};
+
+static const struct soc_enum i2s_mic_enum =
+ SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text);
+
+static const struct snd_kcontrol_new i2s_mic_mux =
+ SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum);
+
+/* ADCL Mux / Mux2 */
+static const char *adcl_text[] = {
+ "ADCR", "ADCL",
+};
+
+static const struct soc_enum adcl_enum =
+ SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text);
+
+static const struct snd_kcontrol_new adcl_mux =
+ SOC_DAPM_ENUM("ADC Left Mux", adcl_enum);
+
+/* ADCR Mux / Mux3 */
+static const char *adcr_text[] = {
+ "ADCL", "ADCR",
+};
+
+static const struct soc_enum adcr_enum =
+ SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text);
+
+static const struct snd_kcontrol_new adcr_mux =
+ SOC_DAPM_ENUM("ADC Right Mux", adcr_enum);
+
+/* ADCR EC Mux / Mux6 */
+static const char *adcr_ec_text[] = {
+ "ADCR", "EC",
+};
+
+static const struct soc_enum adcr_ec_enum =
+ SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text);
+
+static const struct snd_kcontrol_new adcr_ec_mux =
+ SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum);
+
+/* EC Mux / Mux4 */
+static const char *ec_text[] = {
+ "Left", "Right", "Left + Right",
+};
+
+static const struct soc_enum ec_enum =
+ SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text);
+
+static const struct snd_kcontrol_new ec_mux =
+ SOC_DAPM_ENUM("EC Mux", ec_enum);
+
+static const char *dac_text[] = {
+ "No input", "Right", "Left", "No input",
+};
+
+/* DAC Headset 1 Mux / Mux10 */
+static const struct soc_enum dac_hs1_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_hs1_mux =
+ SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum);
+
+/* DAC Headset 2 Mux / Mux11 */
+static const struct soc_enum dac_hs2_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_hs2_mux =
+ SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum);
+
+/* DAC Lineout 1 Mux / Mux12 */
+static const struct soc_enum dac_lo1_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_lo1_mux =
+ SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum);
+
+/* DAC Lineout 2 Mux / Mux13 */
+static const struct soc_enum dac_lo2_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_lo2_mux =
+ SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum);
+
+/* DAC Spearker Earphone Mux / Mux14 */
+static const struct soc_enum dac_spk_ear_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_spk_ear_mux =
+ SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum);
+
+/* Headset 1 Mux / Mux15 */
+static const char *in_text[] = {
+ "Digital", "Analog",
+};
+
+static const struct soc_enum hs1_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text);
+
+static const struct snd_kcontrol_new hs1_mux =
+ SOC_DAPM_ENUM("Headset1 Mux", hs1_enum);
+
+/* Headset 2 Mux / Mux16 */
+static const struct soc_enum hs2_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text);
+
+static const struct snd_kcontrol_new hs2_mux =
+ SOC_DAPM_ENUM("Headset2 Mux", hs2_enum);
+
+/* Lineout 1 Mux / Mux17 */
+static const struct soc_enum lo1_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text);
+
+static const struct snd_kcontrol_new lo1_mux =
+ SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum);
+
+/* Lineout 2 Mux / Mux18 */
+static const struct soc_enum lo2_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text);
+
+static const struct snd_kcontrol_new lo2_mux =
+ SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum);
+
+/* Speaker Earpiece Demux */
+static const char *spk_text[] = {
+ "Earpiece", "Speaker",
+};
+
+static const struct soc_enum spk_enum =
+ SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text);
+
+static const struct snd_kcontrol_new spk_demux =
+ SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum);
+
+/* MIC Mux / Mux1 */
+static const char *mic_text[] = {
+ "Mic 1", "Mic 2",
+};
+
+static const struct soc_enum mic_enum =
+ SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text);
+
+static const struct snd_kcontrol_new mic_mux =
+ SOC_DAPM_ENUM("MIC Mux", mic_enum);
+
+static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
+ SND_SOC_DAPM_AIF_IN("PCM SDI", "PCM Playback", 0,
+ PM860X_ADC_EN_2, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("PCM SDO", "PCM Capture", 0,
+ PM860X_PCM_IFACE_3, 1, 1),
+
+
+ SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
+ PM860X_DAC_EN_2, 0, 0),
+ SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
+ PM860X_DAC_EN_2, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
+ PM860X_I2S_IFACE_3, 5, 1),
+ SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
+ SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
+ SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
+ SND_SOC_DAPM_MUX("EC Mux", SND_SOC_NOPM, 0, 0, &ec_mux),
+ SND_SOC_DAPM_MUX("ADCR EC Mux", SND_SOC_NOPM, 0, 0, &adcr_ec_mux),
+ SND_SOC_DAPM_SWITCH("Left EPA", SND_SOC_NOPM, 0, 0,
+ &lepa_switch_controls),
+ SND_SOC_DAPM_SWITCH("Right EPA", SND_SOC_NOPM, 0, 0,
+ &repa_switch_controls),
+
+ SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Left ADC MOD", PM860X_ADC_EN_1,
+ 0, 1, 1, 0),
+ SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Right ADC MOD", PM860X_ADC_EN_1,
+ 1, 1, 1, 0),
+ SND_SOC_DAPM_ADC("Left ADC", NULL, PM860X_ADC_EN_2, 5, 0),
+ SND_SOC_DAPM_ADC("Right ADC", NULL, PM860X_ADC_EN_2, 4, 0),
+
+ SND_SOC_DAPM_SWITCH("AUX1 Switch", SND_SOC_NOPM, 0, 0,
+ &aux1_switch_controls),
+ SND_SOC_DAPM_SWITCH("AUX2 Switch", SND_SOC_NOPM, 0, 0,
+ &aux2_switch_controls),
+
+ SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &mic_mux),
+ SND_SOC_DAPM_MICBIAS("Mic1 Bias", PM860X_ADC_ANA_1, 2, 0),
+ SND_SOC_DAPM_MICBIAS("Mic3 Bias", PM860X_ADC_ANA_1, 7, 0),
+ SND_SOC_DAPM_PGA("MIC1 Volume", PM860X_ADC_EN_1, 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MIC3 Volume", PM860X_ADC_EN_1, 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("AUX1 Volume", PM860X_ADC_EN_1, 4, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("AUX2 Volume", PM860X_ADC_EN_1, 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Sidetone PGA", PM860X_ADC_EN_2, 1, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Lofi PGA", PM860X_ADC_EN_2, 2, 0, NULL, 0),
+
+ SND_SOC_DAPM_INPUT("AUX1"),
+ SND_SOC_DAPM_INPUT("AUX2"),
+ SND_SOC_DAPM_INPUT("MIC1P"),
+ SND_SOC_DAPM_INPUT("MIC1N"),
+ SND_SOC_DAPM_INPUT("MIC2P"),
+ SND_SOC_DAPM_INPUT("MIC2N"),
+ SND_SOC_DAPM_INPUT("MIC3P"),
+ SND_SOC_DAPM_INPUT("MIC3N"),
+
+ SND_SOC_DAPM_DAC_E("Left DAC", NULL, SND_SOC_NOPM, 0, 0,
+ pm860x_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_DAC_E("Right DAC", NULL, SND_SOC_NOPM, 0, 0,
+ pm860x_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_MUX("I2S DIN Mux", SND_SOC_NOPM, 0, 0, &i2s_din_mux),
+ SND_SOC_DAPM_MUX("DAC HS1 Mux", SND_SOC_NOPM, 0, 0, &dac_hs1_mux),
+ SND_SOC_DAPM_MUX("DAC HS2 Mux", SND_SOC_NOPM, 0, 0, &dac_hs2_mux),
+ SND_SOC_DAPM_MUX("DAC LO1 Mux", SND_SOC_NOPM, 0, 0, &dac_lo1_mux),
+ SND_SOC_DAPM_MUX("DAC LO2 Mux", SND_SOC_NOPM, 0, 0, &dac_lo2_mux),
+ SND_SOC_DAPM_MUX("DAC SP Mux", SND_SOC_NOPM, 0, 0, &dac_spk_ear_mux),
+ SND_SOC_DAPM_MUX("Headset1 Mux", SND_SOC_NOPM, 0, 0, &hs1_mux),
+ SND_SOC_DAPM_MUX("Headset2 Mux", SND_SOC_NOPM, 0, 0, &hs2_mux),
+ SND_SOC_DAPM_MUX("Lineout1 Mux", SND_SOC_NOPM, 0, 0, &lo1_mux),
+ SND_SOC_DAPM_MUX("Lineout2 Mux", SND_SOC_NOPM, 0, 0, &lo2_mux),
+ SND_SOC_DAPM_MUX("Speaker Earpiece Demux", SND_SOC_NOPM, 0, 0,
+ &spk_demux),
+
+
+ SND_SOC_DAPM_PGA("Headset1 PGA", PM860X_DAC_EN_1, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Headset2 PGA", PM860X_DAC_EN_1, 1, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("HS1"),
+ SND_SOC_DAPM_OUTPUT("HS2"),
+ SND_SOC_DAPM_PGA("Lineout1 PGA", PM860X_DAC_EN_1, 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Lineout2 PGA", PM860X_DAC_EN_1, 3, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+ SND_SOC_DAPM_PGA("Earpiece PGA", PM860X_DAC_EN_1, 4, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("EARP"),
+ SND_SOC_DAPM_OUTPUT("EARN"),
+ SND_SOC_DAPM_PGA("Speaker PGA", PM860X_DAC_EN_1, 5, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("LSP"),
+ SND_SOC_DAPM_OUTPUT("LSN"),
+ SND_SOC_DAPM_REG(snd_soc_dapm_supply, "VCODEC", PM860X_AUDIO_SUPPLIES_2,
+ 0, SUPPLY_MASK, SUPPLY_MASK, 0),
+
+ PM860X_DAPM_OUTPUT("RSYNC", pm860x_rsync_event),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* supply */
+ {"Left DAC", NULL, "VCODEC"},
+ {"Right DAC", NULL, "VCODEC"},
+ {"Left ADC", NULL, "VCODEC"},
+ {"Right ADC", NULL, "VCODEC"},
+ {"Left ADC", NULL, "Left ADC MOD"},
+ {"Right ADC", NULL, "Right ADC MOD"},
+
+ /* PCM/AIF1 Inputs */
+ {"PCM SDO", NULL, "ADC Left Mux"},
+ {"PCM SDO", NULL, "ADCR EC Mux"},
+
+ /* PCM/AFI2 Outputs */
+ {"Lofi PGA", NULL, "PCM SDI"},
+ {"Lofi PGA", NULL, "Sidetone PGA"},
+ {"Left DAC", NULL, "Lofi PGA"},
+ {"Right DAC", NULL, "Lofi PGA"},
+
+ /* I2S/AIF2 Inputs */
+ {"MIC Mux", "Mic 1", "MIC1P"},
+ {"MIC Mux", "Mic 1", "MIC1N"},
+ {"MIC Mux", "Mic 2", "MIC2P"},
+ {"MIC Mux", "Mic 2", "MIC2N"},
+ {"MIC1 Volume", NULL, "MIC Mux"},
+ {"MIC3 Volume", NULL, "MIC3P"},
+ {"MIC3 Volume", NULL, "MIC3N"},
+ {"Left ADC", NULL, "MIC1 Volume"},
+ {"Right ADC", NULL, "MIC3 Volume"},
+ {"ADC Left Mux", "ADCR", "Right ADC"},
+ {"ADC Left Mux", "ADCL", "Left ADC"},
+ {"ADC Right Mux", "ADCL", "Left ADC"},
+ {"ADC Right Mux", "ADCR", "Right ADC"},
+ {"Left EPA", "Switch", "Left DAC"},
+ {"Right EPA", "Switch", "Right DAC"},
+ {"EC Mux", "Left", "Left DAC"},
+ {"EC Mux", "Right", "Right DAC"},
+ {"EC Mux", "Left + Right", "Left DAC"},
+ {"EC Mux", "Left + Right", "Right DAC"},
+ {"ADCR EC Mux", "ADCR", "ADC Right Mux"},
+ {"ADCR EC Mux", "EC", "EC Mux"},
+ {"I2S Mic Mux", "Ex PA", "Left EPA"},
+ {"I2S Mic Mux", "Ex PA", "Right EPA"},
+ {"I2S Mic Mux", "ADC", "ADC Left Mux"},
+ {"I2S Mic Mux", "ADC", "ADCR EC Mux"},
+ {"I2S DOUT", NULL, "I2S Mic Mux"},
+
+ /* I2S/AIF2 Outputs */
+ {"I2S DIN Mux", "DIN", "I2S DIN"},
+ {"I2S DIN Mux", "DIN1", "I2S DIN1"},
+ {"Left DAC", NULL, "I2S DIN Mux"},
+ {"Right DAC", NULL, "I2S DIN Mux"},
+ {"DAC HS1 Mux", "Left", "Left DAC"},
+ {"DAC HS1 Mux", "Right", "Right DAC"},
+ {"DAC HS2 Mux", "Left", "Left DAC"},
+ {"DAC HS2 Mux", "Right", "Right DAC"},
+ {"DAC LO1 Mux", "Left", "Left DAC"},
+ {"DAC LO1 Mux", "Right", "Right DAC"},
+ {"DAC LO2 Mux", "Left", "Left DAC"},
+ {"DAC LO2 Mux", "Right", "Right DAC"},
+ {"Headset1 Mux", "Digital", "DAC HS1 Mux"},
+ {"Headset2 Mux", "Digital", "DAC HS2 Mux"},
+ {"Lineout1 Mux", "Digital", "DAC LO1 Mux"},
+ {"Lineout2 Mux", "Digital", "DAC LO2 Mux"},
+ {"Headset1 PGA", NULL, "Headset1 Mux"},
+ {"Headset2 PGA", NULL, "Headset2 Mux"},
+ {"Lineout1 PGA", NULL, "Lineout1 Mux"},
+ {"Lineout2 PGA", NULL, "Lineout2 Mux"},
+ {"DAC SP Mux", "Left", "Left DAC"},
+ {"DAC SP Mux", "Right", "Right DAC"},
+ {"Speaker Earpiece Demux", "Speaker", "DAC SP Mux"},
+ {"Speaker PGA", NULL, "Speaker Earpiece Demux"},
+ {"Earpiece PGA", NULL, "Speaker Earpiece Demux"},
+
+ {"RSYNC", NULL, "Headset1 PGA"},
+ {"RSYNC", NULL, "Headset2 PGA"},
+ {"RSYNC", NULL, "Lineout1 PGA"},
+ {"RSYNC", NULL, "Lineout2 PGA"},
+ {"RSYNC", NULL, "Speaker PGA"},
+ {"RSYNC", NULL, "Speaker PGA"},
+ {"RSYNC", NULL, "Earpiece PGA"},
+ {"RSYNC", NULL, "Earpiece PGA"},
+
+ {"HS1", NULL, "RSYNC"},
+ {"HS2", NULL, "RSYNC"},
+ {"LINEOUT1", NULL, "RSYNC"},
+ {"LINEOUT2", NULL, "RSYNC"},
+ {"LSP", NULL, "RSYNC"},
+ {"LSN", NULL, "RSYNC"},
+ {"EARP", NULL, "RSYNC"},
+ {"EARN", NULL, "RSYNC"},
+};
+
+/*
+ * Use MUTE_LEFT & MUTE_RIGHT to implement digital mute.
+ * These bits can also be used to mute.
+ */
+static int pm860x_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int data = 0, mask = MUTE_LEFT | MUTE_RIGHT;
+
+ if (mute)
+ data = mask;
+ snd_soc_update_bits(codec, PM860X_DAC_OFFSET, mask, data);
+ snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+ RSYNC_CHANGE, RSYNC_CHANGE);
+ return 0;
+}
+
+static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned char inf = 0, mask = 0;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ inf &= ~PCM_INF2_18WL;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ inf |= PCM_INF2_18WL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ mask |= PCM_INF2_18WL;
+ snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf);
+
+ /* sample rate */
+ switch (params_rate(params)) {
+ case 8000:
+ inf = 0;
+ break;
+ case 16000:
+ inf = 3;
+ break;
+ case 32000:
+ inf = 6;
+ break;
+ case 48000:
+ inf = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, PM860X_PCM_RATE, 0x0f, inf);
+
+ return 0;
+}
+
+static int pm860x_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ unsigned char inf = 0, mask = 0;
+ int ret = -EINVAL;
+
+ mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ case SND_SOC_DAIFMT_CBM_CFS:
+ if (pm860x->dir == PM860X_CLK_DIR_OUT) {
+ inf |= PCM_INF2_MASTER;
+ ret = 0;
+ }
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ if (pm860x->dir == PM860X_CLK_DIR_IN) {
+ inf &= ~PCM_INF2_MASTER;
+ ret = 0;
+ }
+ break;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ inf |= PCM_EXACT_I2S;
+ ret = 0;
+ break;
+ }
+ mask |= PCM_MODE_MASK;
+ if (ret)
+ return ret;
+ snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf);
+ return 0;
+}
+
+static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+
+ if (dir == PM860X_CLK_DIR_OUT)
+ pm860x->dir = PM860X_CLK_DIR_OUT;
+ else {
+ pm860x->dir = PM860X_CLK_DIR_IN;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned char inf;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ inf = 0;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ inf = PCM_INF2_18WL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, PCM_INF2_18WL, inf);
+
+ /* sample rate */
+ switch (params_rate(params)) {
+ case 8000:
+ inf = 0;
+ break;
+ case 11025:
+ inf = 1;
+ break;
+ case 16000:
+ inf = 3;
+ break;
+ case 22050:
+ inf = 4;
+ break;
+ case 32000:
+ inf = 6;
+ break;
+ case 44100:
+ inf = 7;
+ break;
+ case 48000:
+ inf = 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+ snd_soc_update_bits(codec, PM860X_I2S_IFACE_4, 0xf, inf);
+
+ return 0;
+}
+
+static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ unsigned char inf = 0, mask = 0;
+
+ mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ if (pm860x->dir == PM860X_CLK_DIR_OUT)
+ inf |= PCM_INF2_MASTER;
+ else
+ return -EINVAL;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ if (pm860x->dir == PM860X_CLK_DIR_IN)
+ inf &= ~PCM_INF2_MASTER;
+ else
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ inf |= PCM_EXACT_I2S;
+ break;
+ default:
+ return -EINVAL;
+ }
+ mask |= PCM_MODE_MASK;
+ snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, mask, inf);
+ return 0;
+}
+
+static int pm860x_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ int data;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ /* Enable Audio PLL & Audio section */
+ data = AUDIO_PLL | AUDIO_SECTION_RESET
+ | AUDIO_SECTION_ON;
+ pm860x_reg_write(codec->control_data, REG_MISC2, data);
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON;
+ pm860x_set_bits(codec->control_data, REG_MISC2, data, 0);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+static struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
+ .digital_mute = pm860x_digital_mute,
+ .hw_params = pm860x_pcm_hw_params,
+ .set_fmt = pm860x_pcm_set_dai_fmt,
+ .set_sysclk = pm860x_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
+ .digital_mute = pm860x_digital_mute,
+ .hw_params = pm860x_i2s_hw_params,
+ .set_fmt = pm860x_i2s_set_dai_fmt,
+ .set_sysclk = pm860x_set_dai_sysclk,
+};
+
+#define PM860X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+
+static struct snd_soc_dai_driver pm860x_dai[] = {
+ {
+ /* DAI PCM */
+ .name = "88pm860x-pcm",
+ .id = 1,
+ .playback = {
+ .stream_name = "PCM Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = PM860X_RATES,
+ .formats = SNDRV_PCM_FORMAT_S16_LE | \
+ SNDRV_PCM_FORMAT_S18_3LE,
+ },
+ .capture = {
+ .stream_name = "PCM Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = PM860X_RATES,
+ .formats = SNDRV_PCM_FORMAT_S16_LE | \
+ SNDRV_PCM_FORMAT_S18_3LE,
+ },
+ .ops = &pm860x_pcm_dai_ops,
+ }, {
+ /* DAI I2S */
+ .name = "88pm860x-i2s",
+ .id = 2,
+ .playback = {
+ .stream_name = "I2S Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FORMAT_S16_LE | \
+ SNDRV_PCM_FORMAT_S18_3LE,
+ },
+ .capture = {
+ .stream_name = "I2S Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FORMAT_S16_LE | \
+ SNDRV_PCM_FORMAT_S18_3LE,
+ },
+ .ops = &pm860x_i2s_dai_ops,
+ },
+};
+
+static irqreturn_t pm860x_codec_handler(int irq, void *data)
+{
+ struct pm860x_priv *pm860x = data;
+ int status, shrt, report = 0, mic_report = 0;
+ int mask;
+
+ status = pm860x_reg_read(pm860x->i2c, REG_STATUS_1);
+ shrt = pm860x_reg_read(pm860x->i2c, REG_SHORTS);
+ mask = pm860x->det.hs_shrt | pm860x->det.hook_det | pm860x->det.lo_shrt
+ | pm860x->det.hp_det;
+
+ if ((pm860x->det.hp_det & SND_JACK_HEADPHONE)
+ && (status & HEADSET_STATUS))
+ report |= SND_JACK_HEADPHONE;
+
+ if ((pm860x->det.mic_det & SND_JACK_MICROPHONE)
+ && (status & MIC_STATUS))
+ mic_report |= SND_JACK_MICROPHONE;
+
+ if (pm860x->det.hs_shrt && (shrt & (SHORT_HS1 | SHORT_HS2)))
+ report |= pm860x->det.hs_shrt;
+
+ if (pm860x->det.hook_det && (status & HOOK_STATUS))
+ report |= pm860x->det.hook_det;
+
+ if (pm860x->det.lo_shrt && (shrt & (SHORT_LO1 | SHORT_LO2)))
+ report |= pm860x->det.lo_shrt;
+
+ if (report)
+ snd_soc_jack_report(pm860x->det.hp_jack, report, mask);
+ if (mic_report)
+ snd_soc_jack_report(pm860x->det.mic_jack, SND_JACK_MICROPHONE,
+ SND_JACK_MICROPHONE);
+
+ dev_dbg(pm860x->codec->dev, "headphone report:0x%x, mask:%x\n",
+ report, mask);
+ dev_dbg(pm860x->codec->dev, "microphone report:0x%x\n", mic_report);
+ return IRQ_HANDLED;
+}
+
+int pm860x_hs_jack_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *jack,
+ int det, int hook, int hs_shrt, int lo_shrt)
+{
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ int data;
+
+ pm860x->det.hp_jack = jack;
+ pm860x->det.hp_det = det;
+ pm860x->det.hook_det = hook;
+ pm860x->det.hs_shrt = hs_shrt;
+ pm860x->det.lo_shrt = lo_shrt;
+
+ if (det & SND_JACK_HEADPHONE)
+ pm860x_set_bits(codec->control_data, REG_HS_DET,
+ EN_HS_DET, EN_HS_DET);
+ /* headset short detect */
+ if (hs_shrt) {
+ data = CLR_SHORT_HS2 | CLR_SHORT_HS1;
+ pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
+ }
+ /* Lineout short detect */
+ if (lo_shrt) {
+ data = CLR_SHORT_LO2 | CLR_SHORT_LO1;
+ pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
+ }
+
+ /* sync status */
+ pm860x_codec_handler(0, pm860x);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pm860x_hs_jack_detect);
+
+int pm860x_mic_jack_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *jack, int det)
+{
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+
+ pm860x->det.mic_jack = jack;
+ pm860x->det.mic_det = det;
+
+ if (det & SND_JACK_MICROPHONE)
+ pm860x_set_bits(codec->control_data, REG_MIC_DET,
+ MICDET_MASK, MICDET_MASK);
+
+ /* sync status */
+ pm860x_codec_handler(0, pm860x);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pm860x_mic_jack_detect);
+
+static int pm860x_probe(struct snd_soc_codec *codec)
+{
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ int i, ret;
+
+ pm860x->codec = codec;
+
+ codec->control_data = pm860x->i2c;
+
+ for (i = 0; i < 4; i++) {
+ ret = request_threaded_irq(pm860x->irq[i], NULL,
+ pm860x_codec_handler, IRQF_ONESHOT,
+ pm860x->name[i], pm860x);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to request IRQ!\n");
+ goto out_irq;
+ }
+ }
+
+ pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE,
+ REG_CACHE_SIZE, codec->reg_cache);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to fill register cache: %d\n",
+ ret);
+ goto out_codec;
+ }
+
+ snd_soc_add_controls(codec, pm860x_snd_controls,
+ ARRAY_SIZE(pm860x_snd_controls));
+ snd_soc_dapm_new_controls(codec, pm860x_dapm_widgets,
+ ARRAY_SIZE(pm860x_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+ return 0;
+
+out_codec:
+ i = 3;
+out_irq:
+ for (; i >= 0; i--)
+ free_irq(pm860x->irq[i], pm860x);
+ return -EINVAL;
+}
+
+static int pm860x_remove(struct snd_soc_codec *codec)
+{
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ for (i = 3; i >= 0; i--)
+ free_irq(pm860x->irq[i], pm860x);
+ pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
+ .probe = pm860x_probe,
+ .remove = pm860x_remove,
+ .read = pm860x_read_reg_cache,
+ .write = pm860x_write_reg_cache,
+ .reg_cache_size = REG_CACHE_SIZE,
+ .reg_word_size = sizeof(u8),
+ .set_bias_level = pm860x_set_bias_level,
+};
+
+static int __devinit pm860x_codec_probe(struct platform_device *pdev)
+{
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm860x_priv *pm860x;
+ struct resource *res;
+ int i, ret;
+
+ pm860x = kzalloc(sizeof(struct pm860x_priv), GFP_KERNEL);
+ if (pm860x == NULL)
+ return -ENOMEM;
+
+ pm860x->chip = chip;
+ pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client
+ : chip->companion;
+ platform_set_drvdata(pdev, pm860x);
+
+ for (i = 0; i < 4; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+ if (!res) {
+ dev_err(&pdev->dev, "Failed to get IRQ resources\n");
+ goto out;
+ }
+ pm860x->irq[i] = res->start + chip->irq_base;
+ strncpy(pm860x->name[i], res->name, MAX_NAME_LEN);
+ }
+
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pm860x,
+ pm860x_dai, ARRAY_SIZE(pm860x_dai));
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register codec\n");
+ goto out;
+ }
+ return ret;
+
+out:
+ platform_set_drvdata(pdev, NULL);
+ kfree(pm860x);
+ return -EINVAL;
+}
+
+static int __devexit pm860x_codec_remove(struct platform_device *pdev)
+{
+ struct pm860x_priv *pm860x = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_codec(&pdev->dev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(pm860x);
+ return 0;
+}
+
+static struct platform_driver pm860x_codec_driver = {
+ .driver = {
+ .name = "88pm860x-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = pm860x_codec_probe,
+ .remove = __devexit_p(pm860x_codec_remove),
+};
+
+static __init int pm860x_init(void)
+{
+ return platform_driver_register(&pm860x_codec_driver);
+}
+module_init(pm860x_init);
+
+static __exit void pm860x_exit(void)
+{
+ platform_driver_unregister(&pm860x_codec_driver);
+}
+module_exit(pm860x_exit);
+
+MODULE_DESCRIPTION("ASoC 88PM860x driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-codec");
+
diff --git a/sound/soc/codecs/88pm860x-codec.h b/sound/soc/codecs/88pm860x-codec.h
new file mode 100644
index 000000000000..3364ba4a3607
--- /dev/null
+++ b/sound/soc/codecs/88pm860x-codec.h
@@ -0,0 +1,97 @@
+/*
+ * 88pm860x-codec.h -- 88PM860x ALSA SoC Audio Driver
+ *
+ * Copyright 2010 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __88PM860X_H
+#define __88PM860X_H
+
+/* The offset of these registers are 0xb0 */
+#define PM860X_PCM_IFACE_1 0x00
+#define PM860X_PCM_IFACE_2 0x01
+#define PM860X_PCM_IFACE_3 0x02
+#define PM860X_PCM_RATE 0x03
+#define PM860X_EC_PATH 0x04
+#define PM860X_SIDETONE_L_GAIN 0x05
+#define PM860X_SIDETONE_R_GAIN 0x06
+#define PM860X_SIDETONE_SHIFT 0x07
+#define PM860X_ADC_OFFSET_1 0x08
+#define PM860X_ADC_OFFSET_2 0x09
+#define PM860X_DMIC_DELAY 0x0a
+
+#define PM860X_I2S_IFACE_1 0x0b
+#define PM860X_I2S_IFACE_2 0x0c
+#define PM860X_I2S_IFACE_3 0x0d
+#define PM860X_I2S_IFACE_4 0x0e
+#define PM860X_EQUALIZER_N0_1 0x0f
+#define PM860X_EQUALIZER_N0_2 0x10
+#define PM860X_EQUALIZER_N1_1 0x11
+#define PM860X_EQUALIZER_N1_2 0x12
+#define PM860X_EQUALIZER_D1_1 0x13
+#define PM860X_EQUALIZER_D1_2 0x14
+#define PM860X_LOFI_GAIN_LEFT 0x15
+#define PM860X_LOFI_GAIN_RIGHT 0x16
+#define PM860X_HIFIL_GAIN_LEFT 0x17
+#define PM860X_HIFIL_GAIN_RIGHT 0x18
+#define PM860X_HIFIR_GAIN_LEFT 0x19
+#define PM860X_HIFIR_GAIN_RIGHT 0x1a
+#define PM860X_DAC_OFFSET 0x1b
+#define PM860X_OFFSET_LEFT_1 0x1c
+#define PM860X_OFFSET_LEFT_2 0x1d
+#define PM860X_OFFSET_RIGHT_1 0x1e
+#define PM860X_OFFSET_RIGHT_2 0x1f
+#define PM860X_ADC_ANA_1 0x20
+#define PM860X_ADC_ANA_2 0x21
+#define PM860X_ADC_ANA_3 0x22
+#define PM860X_ADC_ANA_4 0x23
+#define PM860X_ANA_TO_ANA 0x24
+#define PM860X_HS1_CTRL 0x25
+#define PM860X_HS2_CTRL 0x26
+#define PM860X_LO1_CTRL 0x27
+#define PM860X_LO2_CTRL 0x28
+#define PM860X_EAR_CTRL_1 0x29
+#define PM860X_EAR_CTRL_2 0x2a
+#define PM860X_AUDIO_SUPPLIES_1 0x2b
+#define PM860X_AUDIO_SUPPLIES_2 0x2c
+#define PM860X_ADC_EN_1 0x2d
+#define PM860X_ADC_EN_2 0x2e
+#define PM860X_DAC_EN_1 0x2f
+#define PM860X_DAC_EN_2 0x31
+#define PM860X_AUDIO_CAL_1 0x32
+#define PM860X_AUDIO_CAL_2 0x33
+#define PM860X_AUDIO_CAL_3 0x34
+#define PM860X_AUDIO_CAL_4 0x35
+#define PM860X_AUDIO_CAL_5 0x36
+#define PM860X_ANA_INPUT_SEL_1 0x37
+#define PM860X_ANA_INPUT_SEL_2 0x38
+
+#define PM860X_PCM_IFACE_4 0x39
+#define PM860X_I2S_IFACE_5 0x3a
+
+#define PM860X_SHORTS 0x3b
+#define PM860X_PLL_ADJ_1 0x3c
+#define PM860X_PLL_ADJ_2 0x3d
+
+/* bits definition */
+#define PM860X_CLK_DIR_IN 0
+#define PM860X_CLK_DIR_OUT 1
+
+#define PM860X_DET_HEADSET (1 << 0)
+#define PM860X_DET_MIC (1 << 1)
+#define PM860X_DET_HOOK (1 << 2)
+#define PM860X_SHORT_HEADSET (1 << 3)
+#define PM860X_SHORT_LINEOUT (1 << 4)
+#define PM860X_DET_MASK 0x1F
+
+extern int pm860x_hs_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *,
+ int, int, int, int);
+extern int pm860x_mic_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *,
+ int);
+
+#endif /* __88PM860X_H */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 83f5c67d3c41..3b5690d28b8b 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI
config SND_SOC_ALL_CODECS
tristate "Build all ASoC CODEC drivers"
+ select SND_SOC_88PM860X if MFD_88PM860X
select SND_SOC_L3
select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
select SND_SOC_AD1836 if SPI_MASTER
@@ -24,8 +25,10 @@ config SND_SOC_ALL_CODECS
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS42L51 if I2C
select SND_SOC_CS4270 if I2C
+ select SND_SOC_CX20442
select SND_SOC_DA7210 if I2C
- select SND_SOC_JZ4740 if SOC_JZ4740
+ select SND_SOC_JZ4740_CODEC if SOC_JZ4740
+ select SND_SOC_MAX98088 if I2C
select SND_SOC_MAX9877 if I2C
select SND_SOC_PCM3008
select SND_SOC_SPDIF
@@ -40,6 +43,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_TWL6040 if TWL4030_CORE
select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C
+ select SND_SOC_WL1273 if WL1273_CORE
select SND_SOC_WM2000 if I2C
select SND_SOC_WM8350 if MFD_WM8350
select SND_SOC_WM8400 if MFD_WM8400
@@ -54,6 +58,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
+ select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8900 if I2C
select SND_SOC_WM8903 if I2C
select SND_SOC_WM8904 if I2C
@@ -61,9 +66,11 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8955 if I2C
select SND_SOC_WM8960 if I2C
select SND_SOC_WM8961 if I2C
+ select SND_SOC_WM8962 if I2C
select SND_SOC_WM8971 if I2C
select SND_SOC_WM8974 if I2C
select SND_SOC_WM8978 if I2C
+ select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8990 if I2C
select SND_SOC_WM8993 if I2C
@@ -84,6 +91,9 @@ config SND_SOC_ALL_CODECS
If unsure select "N".
+config SND_SOC_88PM860X
+ tristate
+
config SND_SOC_WM_HUBS
tristate
default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
@@ -150,6 +160,9 @@ config SND_SOC_L3
config SND_SOC_DA7210
tristate
+config SND_SOC_MAX98088
+ tristate
+
config SND_SOC_PCM3008
tristate
@@ -188,6 +201,9 @@ config SND_SOC_UDA134X
config SND_SOC_UDA1380
tristate
+config SND_SOC_WL1273
+ tristate
+
config SND_SOC_WM8350
tristate
@@ -227,6 +243,9 @@ config SND_SOC_WM8753
config SND_SOC_WM8776
tristate
+config SND_SOC_WM8804
+ tristate
+
config SND_SOC_WM8900
tristate
@@ -248,6 +267,9 @@ config SND_SOC_WM8960
config SND_SOC_WM8961
tristate
+config SND_SOC_WM8962
+ tristate
+
config SND_SOC_WM8971
tristate
@@ -257,6 +279,9 @@ config SND_SOC_WM8974
config SND_SOC_WM8978
tristate
+config SND_SOC_WM8985
+ tristate
+
config SND_SOC_WM8988
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 53524095759c..f67a2d6f7a46 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,3 +1,4 @@
+snd-soc-88pm860x-objs := 88pm860x-codec.o
snd-soc-ac97-objs := ac97.o
snd-soc-ad1836-objs := ad1836.o
snd-soc-ad193x-objs := ad193x.o
@@ -14,6 +15,7 @@ snd-soc-cs4270-objs := cs4270.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o
snd-soc-l3-objs := l3.o
+snd-soc-max98088-objs := max98088.o
snd-soc-pcm3008-objs := pcm3008.o
snd-soc-spdif-objs := spdif_transciever.o
snd-soc-ssm2602-objs := ssm2602.o
@@ -26,6 +28,7 @@ snd-soc-twl4030-objs := twl4030.o
snd-soc-twl6040-objs := twl6040.o
snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
+snd-soc-wl1273-objs := wl1273.o
snd-soc-wm8350-objs := wm8350.o
snd-soc-wm8400-objs := wm8400.o
snd-soc-wm8510-objs := wm8510.o
@@ -39,6 +42,7 @@ snd-soc-wm8741-objs := wm8741.o
snd-soc-wm8750-objs := wm8750.o
snd-soc-wm8753-objs := wm8753.o
snd-soc-wm8776-objs := wm8776.o
+snd-soc-wm8804-objs := wm8804.o
snd-soc-wm8900-objs := wm8900.o
snd-soc-wm8903-objs := wm8903.o
snd-soc-wm8904-objs := wm8904.o
@@ -46,9 +50,11 @@ snd-soc-wm8940-objs := wm8940.o
snd-soc-wm8955-objs := wm8955.o
snd-soc-wm8960-objs := wm8960.o
snd-soc-wm8961-objs := wm8961.o
+snd-soc-wm8962-objs := wm8962.o
snd-soc-wm8971-objs := wm8971.o
snd-soc-wm8974-objs := wm8974.o
snd-soc-wm8978-objs := wm8978.o
+snd-soc-wm8985-objs := wm8985.o
snd-soc-wm8988-objs := wm8988.o
snd-soc-wm8990-objs := wm8990.o
snd-soc-wm8993-objs := wm8993.o
@@ -66,6 +72,7 @@ snd-soc-tpa6130a2-objs := tpa6130a2.o
snd-soc-wm2000-objs := wm2000.o
snd-soc-wm9090-objs := wm9090.o
+obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
@@ -83,6 +90,7 @@ obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
+obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@@ -95,6 +103,7 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
@@ -108,6 +117,7 @@ obj-$(CONFIG_SND_SOC_WM8741) += snd-soc-wm8741.o
obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
+obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o
obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o
@@ -115,9 +125,11 @@ obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o
obj-$(CONFIG_SND_SOC_WM8955) += snd-soc-wm8955.o
obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o
+obj-$(CONFIG_SND_SOC_WM8962) += snd-soc-wm8962.o
obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o
obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o
+obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o
obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 1f5e57a4bb7a..3c087936aa57 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -21,17 +21,13 @@
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/soc.h>
-#include "ac97.h"
-
-#define AC97_VERSION "0.6"
static int ac97_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
@@ -46,8 +42,8 @@ static struct snd_soc_dai_ops ac97_dai_ops = {
.prepare = ac97_prepare,
};
-struct snd_soc_dai ac97_dai = {
- .name = "AC97 HiFi",
+static struct snd_soc_dai_driver ac97_dai = {
+ .name = "ac97-hifi",
.ac97_control = 1,
.playback = {
.stream_name = "AC97 Playback",
@@ -63,7 +59,6 @@ struct snd_soc_dai ac97_dai = {
.formats = SND_SOC_STD_AC97_FMTS,},
.ops = &ac97_dai_ops,
};
-EXPORT_SYMBOL_GPL(ac97_dai);
static unsigned int ac97_read(struct snd_soc_codec *codec,
unsigned int reg)
@@ -78,95 +73,41 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
return 0;
}
-static int ac97_soc_probe(struct platform_device *pdev)
+static int ac97_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_codec *codec;
struct snd_ac97_bus *ac97_bus;
struct snd_ac97_template ac97_template;
- int i;
- int ret = 0;
-
- printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
-
- socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (!socdev->card->codec)
- return -ENOMEM;
- codec = socdev->card->codec;
- mutex_init(&codec->mutex);
-
- codec->name = "AC97";
- codec->owner = THIS_MODULE;
- codec->dai = &ac97_dai;
- codec->num_dai = 1;
- codec->write = ac97_write;
- codec->read = ac97_read;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0)
- goto err;
+ int ret;
/* add codec as bus device for standard ac97 */
- ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
+ ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus);
if (ret < 0)
- goto bus_err;
+ return ret;
memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
if (ret < 0)
- goto bus_err;
-
- for (i = 0; i < card->num_links; i++) {
- if (card->dai_link[i].codec_dai->ac97_control) {
- snd_ac97_dev_add_pdata(codec->ac97,
- card->dai_link[i].cpu_dai->ac97_pdata);
- }
- }
+ return ret;
return 0;
-
-bus_err:
- snd_soc_free_pcms(socdev);
-
-err:
- kfree(socdev->card->codec);
- socdev->card->codec = NULL;
- return ret;
}
-static int ac97_soc_remove(struct platform_device *pdev)
+static int ac97_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (!codec)
- return 0;
-
- snd_soc_free_pcms(socdev);
- kfree(socdev->card->codec);
-
return 0;
}
#ifdef CONFIG_PM
-static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_ac97_suspend(socdev->card->codec->ac97);
+ snd_ac97_suspend(codec->ac97);
return 0;
}
-static int ac97_soc_resume(struct platform_device *pdev)
+static int ac97_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_ac97_resume(socdev->card->codec->ac97);
+ snd_ac97_resume(codec->ac97);
return 0;
}
@@ -175,14 +116,50 @@ static int ac97_soc_resume(struct platform_device *pdev)
#define ac97_soc_resume NULL
#endif
-struct snd_soc_codec_device soc_codec_dev_ac97 = {
+static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
+ .write = ac97_write,
+ .read = ac97_read,
.probe = ac97_soc_probe,
.remove = ac97_soc_remove,
.suspend = ac97_soc_suspend,
.resume = ac97_soc_resume,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
+
+static __devinit int ac97_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_ac97, &ac97_dai, 1);
+}
+
+static int __devexit ac97_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver ac97_codec_driver = {
+ .driver = {
+ .name = "ac97-codec",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = ac97_probe,
+ .remove = __devexit_p(ac97_remove),
+};
+
+static int __init ac97_init(void)
+{
+ return platform_driver_register(&ac97_codec_driver);
+}
+module_init(ac97_init);
+
+static void __exit ac97_exit(void)
+{
+ platform_driver_unregister(&ac97_codec_driver);
+}
+module_exit(ac97_exit);
MODULE_DESCRIPTION("Soc Generic AC97 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ac97-codec");
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h
deleted file mode 100644
index 281aa42e2bbb..000000000000
--- a/sound/soc/codecs/ac97.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * linux/sound/codecs/ac97.h -- ALSA SoC Layer
- *
- * Author: Liam Girdwood
- * Created: Dec 1st 2005
- * Copyright: Wolfson Microelectronics. PLC.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __LINUX_SND_SOC_AC97_H
-#define __LINUX_SND_SOC_AC97_H
-
-extern struct snd_soc_codec_device soc_codec_dev_ac97;
-extern struct snd_soc_dai ac97_dai;
-
-#endif
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index a01006c8c606..d272534c8f84 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -33,15 +33,10 @@
/* codec private data */
struct ad1836_priv {
- struct snd_soc_codec codec;
- u16 reg_cache[AD1836_NUM_REGS];
+ enum snd_soc_control_type control_type;
+ void *control_data;
};
-static struct snd_soc_codec *ad1836_codec;
-struct snd_soc_codec_device soc_codec_dev_ad1836;
-static int ad1836_register(struct ad1836_priv *ad1836);
-static void ad1836_unregister(struct ad1836_priv *ad1836);
-
/*
* AD1836 volume/mute/de-emphasis etc. controls
*/
@@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
int word_len = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
/* bit size */
switch (params_format(params)) {
@@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
}
#ifdef CONFIG_PM
-static int ad1836_soc_suspend(struct platform_device *pdev,
+static int ad1836_soc_suspend(struct snd_soc_codec *codec,
pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
/* reset clock control mode */
u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
@@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev,
return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
}
-static int ad1836_soc_resume(struct platform_device *pdev)
+static int ad1836_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
/* restore clock control mode */
u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
adc_ctrl2 |= AD1836_ADC_AUX;
@@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev)
#define ad1836_soc_resume NULL
#endif
-static int __devinit ad1836_spi_probe(struct spi_device *spi)
-{
- struct snd_soc_codec *codec;
- struct ad1836_priv *ad1836;
-
- ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
- if (ad1836 == NULL)
- return -ENOMEM;
-
- codec = &ad1836->codec;
- codec->control_data = spi;
- codec->dev = &spi->dev;
-
- dev_set_drvdata(&spi->dev, ad1836);
-
- return ad1836_register(ad1836);
-}
-
-static int __devexit ad1836_spi_remove(struct spi_device *spi)
-{
- struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev);
-
- ad1836_unregister(ad1836);
- return 0;
-}
-
-static struct spi_driver ad1836_spi_driver = {
- .driver = {
- .name = "ad1836",
- .owner = THIS_MODULE,
- },
- .probe = ad1836_spi_probe,
- .remove = __devexit_p(ad1836_spi_remove),
-};
-
static struct snd_soc_dai_ops ad1836_dai_ops = {
.hw_params = ad1836_hw_params,
.set_fmt = ad1836_set_dai_fmt,
};
/* codec DAI instance */
-struct snd_soc_dai ad1836_dai = {
- .name = "AD1836",
+static struct snd_soc_dai_driver ad1836_dai = {
+ .name = "ad1836-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = {
},
.ops = &ad1836_dai_ops,
};
-EXPORT_SYMBOL_GPL(ad1836_dai);
-static int ad1836_register(struct ad1836_priv *ad1836)
+static int ad1836_probe(struct snd_soc_codec *codec)
{
- int ret;
- struct snd_soc_codec *codec = &ad1836->codec;
-
- if (ad1836_codec) {
- dev_err(codec->dev, "Another ad1836 is registered\n");
- kfree(ad1836);
- return -EINVAL;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
- snd_soc_codec_set_drvdata(codec, ad1836);
- codec->reg_cache = ad1836->reg_cache;
- codec->reg_cache_size = AD1836_NUM_REGS;
- codec->name = "AD1836";
- codec->owner = THIS_MODULE;
- codec->dai = &ad1836_dai;
- codec->num_dai = 1;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- ad1836_dai.dev = codec->dev;
- ad1836_codec = codec;
+ struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+ codec->control_data = ad1836->control_data;
ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
if (ret < 0) {
dev_err(codec->dev, "failed to set cache I/O: %d\n",
@@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836)
snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF);
snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF);
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- kfree(ad1836);
- return ret;
- }
-
- ret = snd_soc_register_dai(&ad1836_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- snd_soc_unregister_codec(codec);
- kfree(ad1836);
- return ret;
- }
-
- return 0;
-}
-
-static void ad1836_unregister(struct ad1836_priv *ad1836)
-{
- snd_soc_unregister_dai(&ad1836_dai);
- snd_soc_unregister_codec(&ad1836->codec);
- kfree(ad1836);
- ad1836_codec = NULL;
-}
-
-static int ad1836_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (ad1836_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = ad1836_codec;
- codec = ad1836_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
snd_soc_add_controls(codec, ad1836_snd_controls,
ARRAY_SIZE(ad1836_snd_controls));
snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
ARRAY_SIZE(ad1836_dapm_widgets));
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
-pcm_err:
return ret;
}
/* power down chip */
-static int ad1836_remove(struct platform_device *pdev)
+static int ad1836_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ /* reset clock control mode */
+ u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
+ adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
- return 0;
+ return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
}
-struct snd_soc_codec_device soc_codec_dev_ad1836 = {
+static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
.probe = ad1836_probe,
.remove = ad1836_remove,
.suspend = ad1836_soc_suspend,
.resume = ad1836_soc_resume,
+ .reg_cache_size = AD1836_NUM_REGS,
+ .reg_word_size = sizeof(u16),
+};
+
+static int __devinit ad1836_spi_probe(struct spi_device *spi)
+{
+ struct ad1836_priv *ad1836;
+ int ret;
+
+ ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
+ if (ad1836 == NULL)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, ad1836);
+ ad1836->control_data = spi;
+ ad1836->control_type = SND_SOC_SPI;
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_ad1836, &ad1836_dai, 1);
+ if (ret < 0)
+ kfree(ad1836);
+ return ret;
+}
+
+static int __devexit ad1836_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
+ return 0;
+}
+
+static struct spi_driver ad1836_spi_driver = {
+ .driver = {
+ .name = "ad1836-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad1836_spi_probe,
+ .remove = __devexit_p(ad1836_spi_remove),
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
static int __init ad1836_init(void)
{
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
index e9d90d3951c5..845596717fdf 100644
--- a/sound/soc/codecs/ad1836.h
+++ b/sound/soc/codecs/ad1836.h
@@ -60,6 +60,4 @@
#define AD1836_NUM_REGS 16
-extern struct snd_soc_dai ad1836_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ad1836;
#endif
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index 1def75e4862f..fa2834c91b9f 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -24,9 +24,10 @@
/* codec private data */
struct ad193x_priv {
- unsigned int sysclk;
- struct snd_soc_codec codec;
u8 reg_cache[AD193X_NUM_REGS];
+ enum snd_soc_control_type bus_type;
+ void *control_data;
+ int sysclk;
};
/* ad193x register cache & default register settings */
@@ -34,9 +35,6 @@ static const u8 ad193x_reg[AD193X_NUM_REGS] = {
0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
};
-static struct snd_soc_codec *ad193x_codec;
-struct snd_soc_codec_device soc_codec_dev_ad193x;
-
/*
* AD193X volume/mute/de-emphasis etc. controls
*/
@@ -275,8 +273,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
int word_len = 0, reg = 0, master_rate = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
/* bit size */
@@ -323,100 +320,6 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
-{
- struct snd_soc_codec *codec;
- struct ad193x_priv *ad193x;
- int ret;
-
- if (ad193x_codec) {
- dev_err(dev, "Another ad193x is registered\n");
- return -EINVAL;
- }
-
- ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
- if (ad193x == NULL)
- return -ENOMEM;
-
- dev_set_drvdata(dev, ad193x);
-
- codec = &ad193x->codec;
- mutex_init(&codec->mutex);
- codec->control_data = ctrl_data;
- codec->dev = dev;
- snd_soc_codec_set_drvdata(codec, ad193x);
- codec->reg_cache = ad193x->reg_cache;
- codec->reg_cache_size = AD193X_NUM_REGS;
- codec->name = "AD193X";
- codec->owner = THIS_MODULE;
- codec->dai = &ad193x_dai;
- codec->num_dai = 1;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- ad193x_dai.dev = codec->dev;
- ad193x_codec = codec;
-
- memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS);
-
- if (bus_type == SND_SOC_I2C)
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type);
- else
- ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type);
- if (ret < 0) {
- dev_err(codec->dev, "failed to set cache I/O: %d\n",
- ret);
- kfree(ad193x);
- return ret;
- }
-
- /* default setting for ad193x */
-
- /* unmute dac channels */
- snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
- /* de-emphasis: 48kHz, powedown dac */
- snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
- /* powerdown dac, dac in tdm mode */
- snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
- /* high-pass filter enable */
- snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
- /* sata delay=1, adc aux mode */
- snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
- /* pll input: mclki/xi */
- snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
- snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
- ad193x->sysclk = 12288000;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- kfree(ad193x);
- return ret;
- }
-
- ret = snd_soc_register_dai(&ad193x_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- snd_soc_unregister_codec(codec);
- kfree(ad193x);
- return ret;
- }
-
- return 0;
-}
-
-static int ad193x_bus_remove(struct device *dev)
-{
- struct ad193x_priv *ad193x = dev_get_drvdata(dev);
-
- snd_soc_unregister_dai(&ad193x_dai);
- snd_soc_unregister_codec(&ad193x->codec);
- kfree(ad193x);
- ad193x_codec = NULL;
-
- return 0;
-}
-
static struct snd_soc_dai_ops ad193x_dai_ops = {
.hw_params = ad193x_hw_params,
.digital_mute = ad193x_mute,
@@ -426,8 +329,8 @@ static struct snd_soc_dai_ops ad193x_dai_ops = {
};
/* codec DAI instance */
-struct snd_soc_dai ad193x_dai = {
- .name = "AD193X",
+static struct snd_soc_dai_driver ad193x_dai = {
+ .name = "ad193x-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -446,28 +349,39 @@ struct snd_soc_dai ad193x_dai = {
},
.ops = &ad193x_dai_ops,
};
-EXPORT_SYMBOL_GPL(ad193x_dai);
-static int ad193x_probe(struct platform_device *pdev)
+static int ad193x_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
+ struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
+ int ret;
- if (ad193x_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
+ codec->control_data = ad193x->control_data;
+ if (ad193x->bus_type == SND_SOC_I2C)
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type);
+ else
+ ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to set cache I/O: %d\n",
+ ret);
+ kfree(ad193x);
+ return ret;
}
- socdev->card->codec = ad193x_codec;
- codec = ad193x_codec;
+ /* default setting for ad193x */
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
+ /* unmute dac channels */
+ snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
+ /* de-emphasis: 48kHz, powedown dac */
+ snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
+ /* powerdown dac, dac in tdm mode */
+ snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
+ /* high-pass filter enable */
+ snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
+ /* sata delay=1, adc aux mode */
+ snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
+ /* pll input: mclki/xi */
+ snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
+ snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
snd_soc_add_controls(codec, ad193x_snd_controls,
ARRAY_SIZE(ad193x_snd_controls));
@@ -475,41 +389,47 @@ static int ad193x_probe(struct platform_device *pdev)
ARRAY_SIZE(ad193x_dapm_widgets));
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
-pcm_err:
return ret;
}
-/* power down chip */
-static int ad193x_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_ad193x = {
+static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
.probe = ad193x_probe,
- .remove = ad193x_remove,
+ .reg_cache_default = ad193x_reg,
+ .reg_cache_size = AD193X_NUM_REGS,
+ .reg_word_size = sizeof(u16),
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x);
#if defined(CONFIG_SPI_MASTER)
static int __devinit ad193x_spi_probe(struct spi_device *spi)
{
- return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI);
+ struct ad193x_priv *ad193x;
+ int ret;
+
+ ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
+ if (ad193x == NULL)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, ad193x);
+ ad193x->control_data = spi;
+ ad193x->bus_type = SND_SOC_SPI;
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_ad193x, &ad193x_dai, 1);
+ if (ret < 0)
+ kfree(ad193x);
+ return ret;
}
static int __devexit ad193x_spi_remove(struct spi_device *spi)
{
- return ad193x_bus_remove(&spi->dev);
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
+ return 0;
}
static struct spi_driver ad193x_spi_driver = {
.driver = {
- .name = "ad193x",
+ .name = "ad193x-codec",
.owner = THIS_MODULE,
},
.probe = ad193x_spi_probe,
@@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id);
static int __devinit ad193x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C);
+ struct ad193x_priv *ad193x;
+ int ret;
+
+ ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
+ if (ad193x == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, ad193x);
+ ad193x->control_data = client;
+ ad193x->bus_type = SND_SOC_I2C;
+
+ ret = snd_soc_register_codec(&client->dev,
+ &soc_codec_dev_ad193x, &ad193x_dai, 1);
+ if (ret < 0)
+ kfree(ad193x);
+ return ret;
}
static int __devexit ad193x_i2c_remove(struct i2c_client *client)
{
- return ad193x_bus_remove(&client->dev);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
+ return 0;
}
static struct i2c_driver ad193x_i2c_driver = {
.driver = {
- .name = "ad193x",
+ .name = "ad193x-codec",
},
.probe = ad193x_i2c_probe,
.remove = __devexit_p(ad193x_i2c_remove),
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 654ba64ae04c..9747b5497877 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -80,7 +80,4 @@
#define AD193X_NUM_REGS 17
-extern struct snd_soc_dai ad193x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ad193x;
-
#endif
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 70cfaec3be2c..410ccd5d41cd 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -33,11 +33,6 @@
#include "ad1980.h"
-static unsigned int ac97_read(struct snd_soc_codec *codec,
- unsigned int reg);
-static int ac97_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int val);
-
/*
* AD1980 register cache
*/
@@ -138,8 +133,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
return 0;
}
-struct snd_soc_dai ad1980_dai = {
- .name = "AC97",
+static struct snd_soc_dai_driver ad1980_dai = {
+ .name = "ad1980-hifi",
.ac97_control = 1,
.playback = {
.stream_name = "Playback",
@@ -185,53 +180,20 @@ err:
return -EIO;
}
-static int ad1980_soc_probe(struct platform_device *pdev)
+static int ad1980_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
+ int ret;
u16 vendor_id2;
u16 ext_status;
printk(KERN_INFO "AD1980 SoC Audio Codec\n");
- socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (socdev->card->codec == NULL)
- return -ENOMEM;
- codec = socdev->card->codec;
- mutex_init(&codec->mutex);
-
- codec->reg_cache =
- kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- ret = -ENOMEM;
- goto cache_err;
- }
- memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \
- ARRAY_SIZE(ad1980_reg));
- codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg);
- codec->reg_cache_step = 2;
- codec->name = "AD1980";
- codec->owner = THIS_MODULE;
- codec->dai = &ad1980_dai;
- codec->num_dai = 1;
- codec->write = ac97_write;
- codec->read = ac97_read;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0) {
printk(KERN_ERR "ad1980: failed to register AC97 codec\n");
- goto codec_err;
+ return ret;
}
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0)
- goto pcm_err;
-
-
ret = ad1980_reset(codec, 0);
if (ret < 0) {
printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
@@ -270,41 +232,60 @@ static int ad1980_soc_probe(struct platform_device *pdev)
return 0;
reset_err:
- snd_soc_free_pcms(socdev);
-
-pcm_err:
snd_soc_free_ac97_codec(codec);
-
-codec_err:
- kfree(codec->reg_cache);
-
-cache_err:
- kfree(socdev->card->codec);
- socdev->card->codec = NULL;
return ret;
}
-static int ad1980_soc_remove(struct platform_device *pdev)
+static int ad1980_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec == NULL)
- return 0;
-
- snd_soc_dapm_free(socdev);
- snd_soc_free_pcms(socdev);
snd_soc_free_ac97_codec(codec);
- kfree(codec->reg_cache);
- kfree(codec);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_ad1980 = {
+static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
.probe = ad1980_soc_probe,
.remove = ad1980_soc_remove,
+ .reg_cache_size = ARRAY_SIZE(ad1980_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = ad1980_reg,
+ .reg_cache_step = 2,
+ .write = ac97_write,
+ .read = ac97_read,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980);
+
+static __devinit int ad1980_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_ad1980, &ad1980_dai, 1);
+}
+
+static int __devexit ad1980_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver ad1980_codec_driver = {
+ .driver = {
+ .name = "ad1980-codec",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = ad1980_probe,
+ .remove = __devexit_p(ad1980_remove),
+};
+
+static int __init ad1980_init(void)
+{
+ return platform_driver_register(&ad1980_codec_driver);
+}
+module_init(ad1980_init);
+
+static void __exit ad1980_exit(void)
+{
+ platform_driver_unregister(&ad1980_codec_driver);
+}
+module_exit(ad1980_exit);
MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)");
MODULE_AUTHOR("Roy Huang, Cliff Cai");
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h
index 538f37c90806..eb0af44ad3df 100644
--- a/sound/soc/codecs/ad1980.h
+++ b/sound/soc/codecs/ad1980.h
@@ -23,7 +23,4 @@
#define PR5 0x2000
#define PR6 0x4000
-extern struct snd_soc_dai ad1980_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ad1980;
-
#endif
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index 475807bea2c2..de799cd1ba72 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -23,8 +23,8 @@
#include "ad73311.h"
-struct snd_soc_dai ad73311_dai = {
- .name = "AD73311",
+static struct snd_soc_dai_driver ad73311_dai = {
+ .name = "ad73311-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = {
.rates = SNDRV_PCM_RATE_8000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
};
-EXPORT_SYMBOL_GPL(ad73311_dai);
-static int ad73311_soc_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
- mutex_init(&codec->mutex);
- codec->name = "AD73311";
- codec->owner = THIS_MODULE;
- codec->dai = &ad73311_dai;
- codec->num_dai = 1;
- socdev->card->codec = codec;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "ad73311: failed to create pcms\n");
- goto pcm_err;
- }
-
- return ret;
+static struct snd_soc_codec_driver soc_codec_dev_ad73311;
-pcm_err:
- kfree(socdev->card->codec);
- socdev->card->codec = NULL;
- return ret;
+static int ad73311_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_ad73311, &ad73311_dai, 1);
}
-static int ad73311_soc_remove(struct platform_device *pdev)
+static int __devexit ad73311_remove(struct platform_device *pdev)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec == NULL)
- return 0;
- snd_soc_free_pcms(socdev);
- kfree(codec);
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_ad73311 = {
- .probe = ad73311_soc_probe,
- .remove = ad73311_soc_remove,
+static struct platform_driver ad73311_codec_driver = {
+ .driver = {
+ .name = "ad73311-codec",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = ad73311_probe,
+ .remove = __devexit_p(ad73311_remove),
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
static int __init ad73311_init(void)
{
- return snd_soc_register_dai(&ad73311_dai);
+ return platform_driver_register(&ad73311_codec_driver);
}
module_init(ad73311_init);
static void __exit ad73311_exit(void)
{
- snd_soc_unregister_dai(&ad73311_dai);
+ platform_driver_unregister(&ad73311_codec_driver);
}
module_exit(ad73311_exit);
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h
index 569573d2d4d7..4b353eefc0bf 100644
--- a/sound/soc/codecs/ad73311.h
+++ b/sound/soc/codecs/ad73311.h
@@ -85,6 +85,4 @@
#define REGF_INV (1 << 6)
#define REGF_ALB (1 << 7)
-extern struct snd_soc_dai ad73311_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ad73311;
#endif
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index f8e75edb27b7..8402854ec15e 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -19,16 +19,12 @@
#include <sound/initval.h>
#include <sound/soc.h>
-#include "ads117x.h"
-
#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
-
#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
-struct snd_soc_dai ads117x_dai = {
+static struct snd_soc_dai_driver ads117x_dai = {
/* ADC */
- .name = "ADS117X ADC",
- .id = 1,
+ .name = "ads117x-hifi",
.capture = {
.stream_name = "Capture",
.channels_min = 1,
@@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = {
.rates = ADS117X_RATES,
.formats = ADS117X_FORMATS,},
};
-EXPORT_SYMBOL_GPL(ads117x_dai);
-
-static int ads117x_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret;
-
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
- socdev->card->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
- codec->name = "ADS117X";
- codec->owner = THIS_MODULE;
- codec->dai = &ads117x_dai;
- codec->num_dai = 1;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "ads117x: failed to create pcms\n");
- kfree(codec);
- return ret;
- }
-
- return 0;
-}
-
-static int ads117x_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- snd_soc_free_pcms(socdev);
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_ads117x = {
- .probe = ads117x_probe,
- .remove = ads117x_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x);
+static struct snd_soc_codec_driver soc_codec_dev_ads117x;
-static __devinit int ads117x_platform_probe(struct platform_device *pdev)
+static __devinit int ads117x_probe(struct platform_device *pdev)
{
- ads117x_dai.dev = &pdev->dev;
- return snd_soc_register_dai(&ads117x_dai);
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_ads117x, &ads117x_dai, 1);
}
-static int __devexit ads117x_platform_remove(struct platform_device *pdev)
+static int __devexit ads117x_remove(struct platform_device *pdev)
{
- snd_soc_unregister_dai(&ads117x_dai);
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
static struct platform_driver ads117x_codec_driver = {
.driver = {
- .name = "ads117x",
+ .name = "ads117x-codec",
.owner = THIS_MODULE,
},
- .probe = ads117x_platform_probe,
- .remove = __devexit_p(ads117x_platform_remove),
+ .probe = ads117x_probe,
+ .remove = __devexit_p(ads117x_remove),
};
static int __init ads117x_init(void)
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h
index dbcf50ec9bd1..3ce028614002 100644
--- a/sound/soc/codecs/ads117x.h
+++ b/sound/soc/codecs/ads117x.h
@@ -9,5 +9,5 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
-extern struct snd_soc_dai ads117x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ads117x;
+extern struct snd_soc_dai_driver ads117x_dai;
+extern struct snd_soc_codec_driver soc_codec_dev_ads117x;
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 192aebda3029..c27f8f59dc66 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -17,8 +17,6 @@
#include <linux/spi/spi.h>
#include <sound/asoundef.h>
-#include "ak4104.h"
-
/* AK4104 registers addresses */
#define AK4104_REG_CONTROL1 0x00
#define AK4104_REG_RESERVED 0x01
@@ -45,11 +43,11 @@
#define AK4104_TX_TXE (1 << 0)
#define AK4104_TX_V (1 << 1)
-#define DRV_NAME "ak4104"
+#define DRV_NAME "ak4104-codec"
struct ak4104_private {
- struct snd_soc_codec codec;
- u8 reg_cache[AK4104_NUM_REGS];
+ enum snd_soc_control_type control_type;
+ void *control_data;
};
static int ak4104_fill_cache(struct snd_soc_codec *codec)
@@ -58,7 +56,7 @@ static int ak4104_fill_cache(struct snd_soc_codec *codec)
u8 *reg_cache = codec->reg_cache;
struct spi_device *spi = codec->control_data;
- for (i = 0; i < codec->reg_cache_size; i++) {
+ for (i = 0; i < codec->driver->reg_cache_size; i++) {
int ret = spi_w8r8(spi, i | AK4104_READ);
if (ret < 0) {
dev_err(&spi->dev, "SPI write failure\n");
@@ -76,7 +74,7 @@ static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
{
u8 *reg_cache = codec->reg_cache;
- if (reg >= codec->reg_cache_size)
+ if (reg >= codec->driver->reg_cache_size)
return -EINVAL;
return reg_cache[reg];
@@ -88,7 +86,7 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
u8 *cache = codec->reg_cache;
struct spi_device *spi = codec->control_data;
- if (reg >= codec->reg_cache_size)
+ if (reg >= codec->driver->reg_cache_size)
return -EINVAL;
/* only write to the hardware if value has changed */
@@ -145,8 +143,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
int val = 0;
/* set the IEC958 bits: consumer mode, no copyright bit */
@@ -178,8 +175,8 @@ static struct snd_soc_dai_ops ak4101_dai_ops = {
.set_fmt = ak4104_set_dai_fmt,
};
-struct snd_soc_dai ak4104_dai = {
- .name = DRV_NAME,
+static struct snd_soc_dai_driver ak4104_dai = {
+ .name = "ak4104-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -192,45 +189,17 @@ struct snd_soc_dai ak4104_dai = {
.ops = &ak4101_dai_ops,
};
-static struct snd_soc_codec *ak4104_codec;
-
-static int ak4104_spi_probe(struct spi_device *spi)
+static int ak4104_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec;
- struct ak4104_private *ak4104;
+ struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
int ret, val;
- spi->bits_per_word = 8;
- spi->mode = SPI_MODE_0;
- ret = spi_setup(spi);
- if (ret < 0)
- return ret;
-
- ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
- if (!ak4104) {
- dev_err(&spi->dev, "could not allocate codec\n");
- return -ENOMEM;
- }
-
- codec = &ak4104->codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->dev = &spi->dev;
- codec->name = DRV_NAME;
- codec->owner = THIS_MODULE;
- codec->dai = &ak4104_dai;
- codec->num_dai = 1;
- snd_soc_codec_set_drvdata(codec, ak4104);
- codec->control_data = spi;
- codec->reg_cache = ak4104->reg_cache;
- codec->reg_cache_size = AK4104_NUM_REGS;
+ codec->control_data = ak4104->control_data;
/* read all regs and fill the cache */
ret = ak4104_fill_cache(codec);
if (ret < 0) {
- dev_err(&spi->dev, "failed to fill register cache\n");
+ dev_err(codec->dev, "failed to fill register cache\n");
return ret;
}
@@ -238,93 +207,81 @@ static int ak4104_spi_probe(struct spi_device *spi)
* should contain 0x5b. Not a good way to verify the presence of
* the device, but there is no hardware ID register. */
if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
- AK4104_RESERVED_VAL) {
- ret = -ENODEV;
- goto error_free_codec;
- }
+ AK4104_RESERVED_VAL)
+ return -ENODEV;
/* set power-up and non-reset bits */
val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN;
ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
if (ret < 0)
- goto error_free_codec;
+ return ret;
/* enable transmitter */
val = ak4104_read_reg_cache(codec, AK4104_REG_TX);
val |= AK4104_TX_TXE;
ret = ak4104_spi_write(codec, AK4104_REG_TX, val);
if (ret < 0)
- goto error_free_codec;
-
- ak4104_codec = codec;
- ret = snd_soc_register_dai(&ak4104_dai);
- if (ret < 0) {
- dev_err(&spi->dev, "failed to register DAI\n");
- goto error_free_codec;
- }
+ return ret;
- spi_set_drvdata(spi, ak4104);
- dev_info(&spi->dev, "SPI device initialized\n");
+ dev_info(codec->dev, "SPI device initialized\n");
return 0;
-
-error_free_codec:
- kfree(ak4104);
- ak4104_dai.dev = NULL;
- return ret;
}
-static int __devexit ak4104_spi_remove(struct spi_device *spi)
+static int ak4104_remove(struct snd_soc_codec *codec)
{
- int ret, val;
- struct ak4104_private *ak4104 = spi_get_drvdata(spi);
+ int val, ret;
- val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1);
+ val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
if (val < 0)
return val;
/* clear power-up and non-reset bits */
val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
- ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val);
- if (ret < 0)
- return ret;
+ ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
- ak4104_codec = NULL;
- kfree(ak4104);
- return 0;
+ return ret;
}
-static int ak4104_probe(struct platform_device *pdev)
+static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
+ .probe = ak4104_probe,
+ .remove = ak4104_remove,
+ .reg_cache_size = AK4104_NUM_REGS,
+ .reg_word_size = sizeof(u16),
+};
+
+static int ak4104_spi_probe(struct spi_device *spi)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = ak4104_codec;
+ struct ak4104_private *ak4104;
int ret;
- /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
- socdev->card->codec = codec;
-
- /* Register PCMs */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms\n");
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_0;
+ ret = spi_setup(spi);
+ if (ret < 0)
return ret;
- }
- return 0;
+ ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
+ if (ak4104 == NULL)
+ return -ENOMEM;
+
+ ak4104->control_data = spi;
+ ak4104->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, ak4104);
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_device_ak4104, &ak4104_dai, 1);
+ if (ret < 0)
+ kfree(ak4104);
+ return ret;
}
-static int ak4104_remove(struct platform_device *pdev)
+static int __devexit ak4104_spi_remove(struct spi_device *spi)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- snd_soc_free_pcms(socdev);
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
return 0;
-};
-
-struct snd_soc_codec_device soc_codec_device_ak4104 = {
- .probe = ak4104_probe,
- .remove = ak4104_remove
-};
-EXPORT_SYMBOL_GPL(soc_codec_device_ak4104);
+}
static struct spi_driver ak4104_spi_driver = {
.driver = {
diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h
deleted file mode 100644
index eb88fe7e4def..000000000000
--- a/sound/soc/codecs/ak4104.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _AK4104_H
-#define _AK4104_H
-
-extern struct snd_soc_dai ak4104_dai;
-extern struct snd_soc_codec_device soc_codec_device_ak4104;
-
-#endif
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index d4253675b2d3..cd88c8f32a38 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -31,11 +31,11 @@
#define AK4535_VERSION "0.3"
-struct snd_soc_codec_device soc_codec_dev_ak4535;
-
/* codec private data */
struct ak4535_priv {
unsigned int sysclk;
+ enum snd_soc_control_type control_type;
+ void *control_data;
};
/*
@@ -313,8 +313,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
int rate = params_rate(params), fs = 256;
@@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute)
static int ak4535_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 i;
+ u16 i, mute_reg;
switch (level) {
case SND_SOC_BIAS_ON:
- ak4535_mute(codec->dai, 0);
+ mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
+ ak4535_write(codec, AK4535_DAC, mute_reg);
break;
case SND_SOC_BIAS_PREPARE:
- ak4535_mute(codec->dai, 1);
+ mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
+ ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
break;
case SND_SOC_BIAS_STANDBY:
i = ak4535_read_reg_cache(codec, AK4535_PM1);
@@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = {
.set_sysclk = ak4535_set_dai_sysclk,
};
-struct snd_soc_dai ak4535_dai = {
- .name = "AK4535",
+static struct snd_soc_dai_driver ak4535_dai = {
+ .name = "ak4535-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = &ak4535_dai_ops,
};
-EXPORT_SYMBOL_GPL(ak4535_dai);
-static int ak4535_suspend(struct platform_device *pdev, pm_message_t state)
+static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int ak4535_resume(struct platform_device *pdev)
+static int ak4535_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
ak4535_sync(codec);
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
-/*
- * initialise the AK4535 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int ak4535_init(struct snd_soc_device *socdev)
+static int ak4535_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = socdev->card->codec;
- int ret = 0;
+ struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
- codec->name = "AK4535";
- codec->owner = THIS_MODULE;
- codec->read = ak4535_read_reg_cache;
- codec->write = ak4535_write;
- codec->set_bias_level = ak4535_set_bias_level;
- codec->dai = &ak4535_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(ak4535_reg);
- codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL);
-
- if (codec->reg_cache == NULL)
- return -ENOMEM;
+ printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "ak4535: failed to create pcms\n");
- goto pcm_err;
- }
+ codec->control_data = ak4535->control_data;
/* power on device */
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev)
ARRAY_SIZE(ak4535_snd_controls));
ak4535_add_widgets(codec);
- return ret;
-
-pcm_err:
- kfree(codec->reg_cache);
+ return 0;
+}
- return ret;
+/* power down chip */
+static int ak4535_remove(struct snd_soc_codec *codec)
+{
+ ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
-static struct snd_soc_device *ak4535_socdev;
+static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
+ .probe = ak4535_probe,
+ .remove = ak4535_remove,
+ .suspend = ak4535_suspend,
+ .resume = ak4535_resume,
+ .read = ak4535_read_reg_cache,
+ .write = ak4535_write,
+ .set_bias_level = ak4535_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(ak4535_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = ak4535_reg,
+};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-static int ak4535_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_device *socdev = ak4535_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct ak4535_priv *ak4535;
int ret;
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
+ ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
+ if (ak4535 == NULL)
+ return -ENOMEM;
- ret = ak4535_init(socdev);
- if (ret < 0)
- printk(KERN_ERR "failed to initialise AK4535\n");
+ i2c_set_clientdata(i2c, ak4535);
+ ak4535->control_data = i2c;
+ ak4535->control_type = SND_SOC_I2C;
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_ak4535, &ak4535_dai, 1);
+ if (ret < 0)
+ kfree(ak4535);
return ret;
}
-static int ak4535_i2c_remove(struct i2c_client *client)
+static __devexit int ak4535_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
static struct i2c_driver ak4535_i2c_driver = {
.driver = {
- .name = "AK4535 I2C Codec",
+ .name = "ak4535-codec",
.owner = THIS_MODULE,
},
.probe = ak4535_i2c_probe,
- .remove = ak4535_i2c_remove,
+ .remove = __devexit_p(ak4535_i2c_remove),
.id_table = ak4535_i2c_id,
};
-
-static int ak4535_add_i2c_device(struct platform_device *pdev,
- const struct ak4535_setup_data *setup)
-{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- int ret;
-
- ret = i2c_add_driver(&ak4535_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = setup->i2c_address;
- strlcpy(info.type, "ak4535", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n",
- setup->i2c_bus);
- goto err_driver;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
-
- return 0;
-
-err_driver:
- i2c_del_driver(&ak4535_i2c_driver);
- return -ENODEV;
-}
#endif
-static int ak4535_probe(struct platform_device *pdev)
+static int __init ak4535_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct ak4535_setup_data *setup;
- struct snd_soc_codec *codec;
- struct ak4535_priv *ak4535;
- int ret;
-
- printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
- if (ak4535 == NULL) {
- kfree(codec);
- return -ENOMEM;
- }
-
- snd_soc_codec_set_drvdata(codec, ak4535);
- socdev->card->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- ak4535_socdev = socdev;
- ret = -ENODEV;
-
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- codec->hw_write = (hw_write_t)i2c_master_send;
- ret = ak4535_add_i2c_device(pdev, setup);
- }
-#endif
-
+ ret = i2c_add_driver(&ak4535_i2c_driver);
if (ret != 0) {
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec);
+ printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
+ ret);
}
+#endif
return ret;
}
+module_init(ak4535_modinit);
-/* power down chip */
-static int ak4535_remove(struct platform_device *pdev)
+static void __exit ak4535_exit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec->control_data)
- ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (codec->control_data)
- i2c_unregister_device(codec->control_data);
i2c_del_driver(&ak4535_i2c_driver);
#endif
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_ak4535 = {
- .probe = ak4535_probe,
- .remove = ak4535_remove,
- .suspend = ak4535_suspend,
- .resume = ak4535_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
-
-static int __init ak4535_modinit(void)
-{
- return snd_soc_register_dai(&ak4535_dai);
-}
-module_init(ak4535_modinit);
-
-static void __exit ak4535_exit(void)
-{
- snd_soc_unregister_dai(&ak4535_dai);
}
module_exit(ak4535_exit);
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
index c7a58703ea39..0431e5f634a2 100644
--- a/sound/soc/codecs/ak4535.h
+++ b/sound/soc/codecs/ak4535.h
@@ -36,12 +36,4 @@
#define AK4535_CACHEREGNUM 0x10
-struct ak4535_setup_data {
- int i2c_bus;
- unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai ak4535_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ak4535;
-
#endif
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 3d7dc55305ec..90c90b7f4a2e 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -30,8 +30,6 @@
#include <sound/initval.h>
#include <sound/tlv.h>
-#include "ak4642.h"
-
#define AK4642_VERSION "0.0.1"
#define PW_MGMT1 0x00
@@ -74,6 +72,12 @@
#define AK4642_CACHEREGNUM 0x25
+/* PW_MGMT1*/
+#define PMVCM (1 << 6) /* VCOM Power Management */
+#define PMMIN (1 << 5) /* MIN Input Power Management */
+#define PMDAC (1 << 2) /* DAC Power Management */
+#define PMADL (1 << 0) /* MIC Amp Lch and ADC Lch Power Management */
+
/* PW_MGMT2 */
#define HPMTN (1 << 6)
#define PMHPL (1 << 5)
@@ -85,6 +89,23 @@
#define PMHP_MASK (PMHPL | PMHPR)
#define PMHP PMHP_MASK
+/* PW_MGMT3 */
+#define PMADR (1 << 0) /* MIC L / ADC R Power Management */
+
+/* SG_SL1 */
+#define MINS (1 << 6) /* Switch from MIN to Speaker */
+#define DACL (1 << 4) /* Switch from DAC to Stereo or Receiver */
+#define PMMP (1 << 2) /* MPWR pin Power Management */
+#define MGAIN0 (1 << 0) /* MIC amp gain*/
+
+/* TIMER */
+#define ZTM(param) ((param & 0x3) << 4) /* ALC Zoro Crossing TimeOut */
+#define WTM(param) (((param & 0x4) << 4) | ((param & 0x3) << 2))
+
+/* ALC_CTL1 */
+#define ALC (1 << 5) /* ALC Enable */
+#define LMTH0 (1 << 0) /* ALC Limiter / Recovery Level */
+
/* MD_CTL1 */
#define PLL3 (1 << 7)
#define PLL2 (1 << 6)
@@ -102,7 +123,11 @@
#define FS3 (1 << 5)
#define FS_MASK (FS0 | FS1 | FS2 | FS3)
-struct snd_soc_codec_device soc_codec_dev_ak4642;
+/* MD_CTL3 */
+#define BST1 (1 << 3)
+
+/* MD_CTL4 */
+#define DACH (1 << 0)
/*
* Playback Volume (table 39)
@@ -123,11 +148,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
/* codec private data */
struct ak4642_priv {
- struct snd_soc_codec codec;
+ unsigned int sysclk;
+ enum snd_soc_control_type control_type;
+ void *control_data;
};
-static struct snd_soc_codec *ak4642_codec;
-
/*
* ak4642 register cache
*/
@@ -219,11 +244,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
* This operation came from example code of
* "ASAHI KASEI AK4642" (japanese) manual p97.
*/
- ak4642_write(codec, 0x0f, 0x09);
- ak4642_write(codec, 0x0e, 0x19);
- ak4642_write(codec, 0x09, 0x91);
- ak4642_write(codec, 0x0c, 0x91);
- ak4642_write(codec, 0x00, 0x64);
+ snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
+ snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
+ ak4642_write(codec, L_IVC, 0x91); /* volume */
+ ak4642_write(codec, R_IVC, 0x91); /* volume */
+ snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC,
+ PMVCM | PMMIN | PMDAC);
snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN);
} else {
@@ -240,13 +266,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
* This operation came from example code of
* "ASAHI KASEI AK4642" (japanese) manual p94.
*/
- ak4642_write(codec, 0x02, 0x05);
- ak4642_write(codec, 0x06, 0x3c);
- ak4642_write(codec, 0x08, 0xe1);
- ak4642_write(codec, 0x0b, 0x00);
- ak4642_write(codec, 0x07, 0x21);
- ak4642_write(codec, 0x00, 0x41);
- ak4642_write(codec, 0x10, 0x01);
+ ak4642_write(codec, SG_SL1, PMMP | MGAIN0);
+ ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
+ ak4642_write(codec, ALC_CTL1, ALC | LMTH0);
+ snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL,
+ PMVCM | PMADL);
+ snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
}
return 0;
@@ -262,14 +287,14 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
/* stop headphone output */
snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0);
snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0);
- ak4642_write(codec, 0x00, 0x40);
- ak4642_write(codec, 0x0e, 0x11);
- ak4642_write(codec, 0x0f, 0x08);
+ snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, 0);
+ snd_soc_update_bits(codec, MD_CTL3, BST1, 0);
+ snd_soc_update_bits(codec, MD_CTL4, DACH, 0);
} else {
/* stop stereo input */
- ak4642_write(codec, 0x00, 0x40);
- ak4642_write(codec, 0x10, 0x00);
- ak4642_write(codec, 0x07, 0x01);
+ snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0);
+ snd_soc_update_bits(codec, PW_MGMT3, PMADR, 0);
+ snd_soc_update_bits(codec, ALC_CTL1, ALC, 0);
}
}
@@ -393,8 +418,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = {
.hw_params = ak4642_dai_hw_params,
};
-struct snd_soc_dai ak4642_dai = {
- .name = "AK4642",
+static struct snd_soc_dai_driver ak4642_dai = {
+ .name = "ak4642-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -410,112 +435,65 @@ struct snd_soc_dai ak4642_dai = {
.ops = &ak4642_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(ak4642_dai);
-static int ak4642_resume(struct platform_device *pdev)
+static int ak4642_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
ak4642_sync(codec);
return 0;
}
-/*
- * initialise the AK4642 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int ak4642_init(struct ak4642_priv *ak4642)
+
+static int ak4642_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = &ak4642->codec;
- int ret = 0;
+ struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
- if (ak4642_codec) {
- dev_err(codec->dev, "Another ak4642 is registered\n");
- return -EINVAL;
- }
+ dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, ak4642);
- codec->name = "AK4642";
- codec->owner = THIS_MODULE;
- codec->read = ak4642_read_reg_cache;
- codec->write = ak4642_write;
- codec->dai = &ak4642_dai;
- codec->num_dai = 1;
codec->hw_write = (hw_write_t)i2c_master_send;
- codec->reg_cache_size = ARRAY_SIZE(ak4642_reg);
- codec->reg_cache = kmemdup(ak4642_reg,
- sizeof(ak4642_reg), GFP_KERNEL);
+ codec->control_data = ak4642->control_data;
- if (!codec->reg_cache)
- return -ENOMEM;
-
- ak4642_dai.dev = codec->dev;
- ak4642_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto reg_cache_err;
- }
-
- ret = snd_soc_register_dai(&ak4642_dai);
- if (ret) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- snd_soc_unregister_codec(codec);
- goto reg_cache_err;
- }
-
- return ret;
-
-reg_cache_err:
- kfree(codec->reg_cache);
- codec->reg_cache = NULL;
+ snd_soc_add_controls(codec, ak4642_snd_controls,
+ ARRAY_SIZE(ak4642_snd_controls));
- return ret;
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
+ .probe = ak4642_probe,
+ .resume = ak4642_resume,
+ .read = ak4642_read_reg_cache,
+ .write = ak4642_write,
+ .reg_cache_size = ARRAY_SIZE(ak4642_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = ak4642_reg,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static int ak4642_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct ak4642_priv *ak4642;
- struct snd_soc_codec *codec;
int ret;
ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL);
if (!ak4642)
return -ENOMEM;
- codec = &ak4642->codec;
- codec->dev = &i2c->dev;
-
i2c_set_clientdata(i2c, ak4642);
- codec->control_data = i2c;
+ ak4642->control_data = i2c;
+ ak4642->control_type = SND_SOC_I2C;
- ret = ak4642_init(ak4642);
- if (ret < 0) {
- printk(KERN_ERR "failed to initialise AK4642\n");
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_ak4642, &ak4642_dai, 1);
+ if (ret < 0)
kfree(ak4642);
- }
-
return ret;
}
-static int ak4642_i2c_remove(struct i2c_client *client)
+static __devexit int ak4642_i2c_remove(struct i2c_client *client)
{
- struct ak4642_priv *ak4642 = i2c_get_clientdata(client);
-
- snd_soc_unregister_dai(&ak4642_dai);
- snd_soc_unregister_codec(&ak4642->codec);
- kfree(ak4642->codec.reg_cache);
- kfree(ak4642);
- ak4642_codec = NULL;
-
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -528,64 +506,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
static struct i2c_driver ak4642_i2c_driver = {
.driver = {
- .name = "AK4642 I2C Codec",
+ .name = "ak4642-codec",
.owner = THIS_MODULE,
},
.probe = ak4642_i2c_probe,
- .remove = ak4642_i2c_remove,
+ .remove = __devexit_p(ak4642_i2c_remove),
.id_table = ak4642_i2c_id,
};
-
#endif
-static int ak4642_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- int ret;
-
- if (!ak4642_codec) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = ak4642_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "ak4642: failed to create pcms\n");
- goto pcm_err;
- }
-
- snd_soc_add_controls(ak4642_codec, ak4642_snd_controls,
- ARRAY_SIZE(ak4642_snd_controls));
-
- dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
- return ret;
-
-pcm_err:
- return ret;
-
-}
-
-/* power down chip */
-static int ak4642_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_ak4642 = {
- .probe = ak4642_probe,
- .remove = ak4642_remove,
- .resume = ak4642_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642);
-
static int __init ak4642_modinit(void)
{
int ret = 0;
diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h
deleted file mode 100644
index e476833d314e..000000000000
--- a/sound/soc/codecs/ak4642.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * ak4642.h -- AK4642 Soc Audio driver
- *
- * Copyright (C) 2009 Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * Based on ak4535.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _AK4642_H
-#define _AK4642_H
-
-extern struct snd_soc_dai ak4642_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ak4642;
-
-#endif
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 87566932a3b1..24f5f49bb9d2 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -23,11 +23,11 @@
#include "ak4671.h"
-static struct snd_soc_codec *ak4671_codec;
/* codec private data */
struct ak4671_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
u8 reg_cache[AK4671_CACHEREGNUM];
};
@@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = {
.set_fmt = ak4671_set_dai_fmt,
};
-struct snd_soc_dai ak4671_dai = {
- .name = "AK4671",
+static struct snd_soc_dai_driver ak4671_dai = {
+ .name = "ak4671-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -635,27 +635,18 @@ struct snd_soc_dai ak4671_dai = {
.formats = AK4671_FORMATS,},
.ops = &ak4671_dai_ops,
};
-EXPORT_SYMBOL_GPL(ak4671_dai);
-static int ak4671_probe(struct platform_device *pdev)
+static int ak4671_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (ak4671_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
+ struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
+ int ret;
- socdev->card->codec = ak4671_codec;
- codec = ak4671_codec;
+ codec->hw_write = (hw_write_t)i2c_master_send;
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
snd_soc_add_controls(codec, ak4671_snd_controls,
@@ -665,121 +656,48 @@ static int ak4671_probe(struct platform_device *pdev)
ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return ret;
-
-pcm_err:
- return ret;
}
-static int ak4671_remove(struct platform_device *pdev)
+static int ak4671_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
+ ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_ak4671 = {
+static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
.probe = ak4671_probe,
.remove = ak4671_remove,
+ .set_bias_level = ak4671_set_bias_level,
+ .reg_cache_size = AK4671_CACHEREGNUM,
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = ak4671_reg,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671);
-
-static int ak4671_register(struct ak4671_priv *ak4671,
- enum snd_soc_control_type control)
-{
- int ret;
- struct snd_soc_codec *codec = &ak4671->codec;
-
- if (ak4671_codec) {
- dev_err(codec->dev, "Another AK4671 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, ak4671);
- codec->name = "AK4671";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = ak4671_set_bias_level;
- codec->dai = &ak4671_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = AK4671_CACHEREGNUM;
- codec->reg_cache = &ak4671->reg_cache;
-
- memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
-
- ak4671_dai.dev = codec->dev;
- ak4671_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&ak4671_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
- return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(ak4671);
- return ret;
-}
-
-static void ak4671_unregister(struct ak4671_priv *ak4671)
-{
- ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&ak4671_dai);
- snd_soc_unregister_codec(&ak4671->codec);
- kfree(ak4671);
- ak4671_codec = NULL;
-}
static int __devinit ak4671_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ak4671_priv *ak4671;
- struct snd_soc_codec *codec;
+ int ret;
ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
if (ak4671 == NULL)
return -ENOMEM;
- codec = &ak4671->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
i2c_set_clientdata(client, ak4671);
- codec->control_data = client;
-
- codec->dev = &client->dev;
+ ak4671->control_data = client;
+ ak4671->control_type = SND_SOC_I2C;
- return ak4671_register(ak4671, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&client->dev,
+ &soc_codec_dev_ak4671, &ak4671_dai, 1);
+ if (ret < 0)
+ kfree(ak4671);
+ return ret;
}
static __devexit int ak4671_i2c_remove(struct i2c_client *client)
{
- struct ak4671_priv *ak4671 = i2c_get_clientdata(client);
-
- ak4671_unregister(ak4671);
-
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -791,7 +709,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
static struct i2c_driver ak4671_i2c_driver = {
.driver = {
- .name = "ak4671",
+ .name = "ak4671-codec",
.owner = THIS_MODULE,
},
.probe = ak4671_i2c_probe,
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h
index e2fad964e88b..61cb7ab7552c 100644
--- a/sound/soc/codecs/ak4671.h
+++ b/sound/soc/codecs/ak4671.h
@@ -150,7 +150,4 @@
/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */
#define AK4671_MUTEN 0x04
-extern struct snd_soc_dai ak4671_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ak4671;
-
#endif
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index a320fb5a0e26..823643932dde 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -30,6 +30,7 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/mfd/davinci_voicecodec.h>
+#include <linux/spi/spi.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -41,8 +42,6 @@
#include <mach/dm365.h>
-#include "cq93vc.h"
-
static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
unsigned int reg)
{
@@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = {
.set_sysclk = cq93vc_set_dai_sysclk,
};
-struct snd_soc_dai cq93vc_dai = {
- .name = "CQ93VC",
+static struct snd_soc_dai_driver cq93vc_dai = {
+ .name = "cq93vc-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = {
.formats = CQ93VC_FORMATS,},
.ops = &cq93vc_dai_ops,
};
-EXPORT_SYMBOL_GPL(cq93vc_dai);
-static int cq93vc_resume(struct platform_device *pdev)
+static int cq93vc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
-static struct snd_soc_codec *cq93vc_codec;
-
-static int cq93vc_probe(struct platform_device *pdev)
+static int cq93vc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct device *dev = &pdev->dev;
- struct snd_soc_codec *codec;
- int ret;
-
- socdev->card->codec = cq93vc_codec;
- codec = socdev->card->codec;
-
- /* Register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(dev, "%s: failed to create pcms\n", pdev->name);
- return ret;
- }
+ struct davinci_vc *davinci_vc = codec->dev->platform_data;
+
+ davinci_vc->cq93vc.codec = codec;
+ codec->control_data = davinci_vc;
/* Set controls */
snd_soc_add_controls(codec, cq93vc_snd_controls,
@@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev)
return 0;
}
-static int cq93vc_remove(struct platform_device *pdev)
+static int cq93vc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_cq93vc = {
+static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
+ .read = cq93vc_read,
+ .write = cq93vc_write,
+ .set_bias_level = cq93vc_set_bias_level,
.probe = cq93vc_probe,
.remove = cq93vc_remove,
.resume = cq93vc_resume,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc);
-static __init int cq93vc_codec_probe(struct platform_device *pdev)
+static int cq93vc_platform_probe(struct platform_device *pdev)
{
- struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret;
-
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL) {
- dev_dbg(davinci_vc->dev,
- "could not allocate memory for codec data\n");
- return -ENOMEM;
- }
-
- davinci_vc->cq93vc.codec = codec;
-
- cq93vc_dai.dev = &pdev->dev;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
- codec->dev = &pdev->dev;
- codec->name = "CQ93VC";
- codec->owner = THIS_MODULE;
- codec->read = cq93vc_read;
- codec->write = cq93vc_write;
- codec->set_bias_level = cq93vc_set_bias_level;
- codec->dai = &cq93vc_dai;
- codec->num_dai = 1;
- codec->control_data = davinci_vc;
-
- cq93vc_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret) {
- dev_err(davinci_vc->dev, "failed to register codec\n");
- goto fail1;
- }
-
- ret = snd_soc_register_dai(&cq93vc_dai);
- if (ret) {
- dev_err(davinci_vc->dev, "could register dai\n");
- goto fail2;
- }
- return 0;
-
-fail2:
- snd_soc_unregister_codec(codec);
-
-fail1:
- kfree(codec);
- cq93vc_codec = NULL;
-
- return ret;
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_cq93vc, &cq93vc_dai, 1);
}
-static int __devexit cq93vc_codec_remove(struct platform_device *pdev)
+static int cq93vc_platform_remove(struct platform_device *pdev)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- snd_soc_unregister_dai(&cq93vc_dai);
- snd_soc_unregister_codec(&codec);
-
- kfree(codec);
- cq93vc_codec = NULL;
-
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
static struct platform_driver cq93vc_codec_driver = {
.driver = {
- .name = "cq93vc",
- .owner = THIS_MODULE,
- },
- .probe = cq93vc_codec_probe,
- .remove = __devexit_p(cq93vc_codec_remove),
+ .name = "cq93vc-codec",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = cq93vc_platform_probe,
+ .remove = __devexit_p(cq93vc_platform_remove),
};
-static __init int cq93vc_init(void)
+static int __init cq93vc_init(void)
{
- return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe);
+ return platform_driver_register(&cq93vc_codec_driver);
}
module_init(cq93vc_init);
-static __exit void cq93vc_exit(void)
+static void __exit cq93vc_exit(void)
{
platform_driver_unregister(&cq93vc_codec_driver);
}
diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h
deleted file mode 100644
index 845b1968ef9c..000000000000
--- a/sound/soc/codecs/cq93vc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
- *
- * Copyright (C) 2010 Texas Instruments, Inc
- *
- * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _CQ93VC_H
-#define _CQ93VC_H
-
-extern struct snd_soc_dai cq93vc_dai;
-extern struct snd_soc_codec_device soc_codec_dev_cq93vc;
-
-#endif
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 30d949239def..6d4bdc609ac8 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -31,8 +31,6 @@
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
-#include "cs4270.h"
-
/*
* The codec isn't really big-endian or little-endian, since the I2S
* interface requires data to be sent serially with the MSbit first.
@@ -114,7 +112,8 @@ static const char *supply_names[] = {
/* Private data for the CS4270 */
struct cs4270_private {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
u8 reg_cache[CS4270_NUMREGS];
unsigned int mclk; /* Input frequency of the MCLK pin */
unsigned int mode; /* The mode (I2S or left-justified) */
@@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
- unsigned int rates = 0;
- unsigned int rate_min = -1;
- unsigned int rate_max = 0;
- unsigned int i;
cs4270->mclk = freq;
-
- if (cs4270->mclk) {
- for (i = 0; i < NUM_MCLK_RATIOS; i++) {
- unsigned int rate = freq / cs4270_mode_ratios[i].ratio;
- rates |= snd_pcm_rate_to_rate_bit(rate);
- if (rate < rate_min)
- rate_min = rate;
- if (rate > rate_max)
- rate_max = rate;
- }
- /* FIXME: soc should support a rate list */
- rates &= ~SNDRV_PCM_RATE_KNOT;
-
- if (!rates) {
- dev_err(codec->dev, "could not find a valid sample rate\n");
- return -EINVAL;
- }
- } else {
- /* enable all possible rates */
- rates = SNDRV_PCM_RATE_8000_192000;
- rate_min = 8000;
- rate_max = 192000;
- }
-
- codec_dai->playback.rates = rates;
- codec_dai->playback.rate_min = rate_min;
- codec_dai->playback.rate_max = rate_max;
-
- codec_dai->capture.rates = rates;
- codec_dai->capture.rate_min = rate_min;
- codec_dai->capture.rate_max = rate_max;
-
return 0;
}
@@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int ret;
unsigned int i;
@@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
snd_soc_get_volsw, cs4270_soc_put_mute),
};
-/*
- * cs4270_codec - global variable to store codec for the ASoC probe function
- *
- * If struct i2c_driver had a private_data field, we wouldn't need to use
- * cs4270_codec. This is the only way to pass the codec structure from
- * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good
- * way to synchronize these two functions. cs4270_i2c_probe() can be called
- * multiple times before cs4270_probe() is called even once. So for now, we
- * also only allow cs4270_i2c_probe() to be run once. That means that we do
- * not support more than one cs4270 device in the system, at least for now.
- */
-static struct snd_soc_codec *cs4270_codec;
-
static struct snd_soc_dai_ops cs4270_dai_ops = {
.hw_params = cs4270_hw_params,
.set_sysclk = cs4270_set_dai_sysclk,
@@ -569,25 +518,28 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {
.digital_mute = cs4270_dai_mute,
};
-struct snd_soc_dai cs4270_dai = {
- .name = "cs4270",
+static struct snd_soc_dai_driver cs4270_dai = {
+ .name = "cs4270-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
- .rates = 0,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 4000,
+ .rate_max = 216000,
.formats = CS4270_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
- .rates = 0,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 4000,
+ .rate_max = 216000,
.formats = CS4270_FORMATS,
},
.ops = &cs4270_dai_ops,
};
-EXPORT_SYMBOL_GPL(cs4270_dai);
/**
* cs4270_probe - ASoC probe function
@@ -596,153 +548,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai);
* This function is called when ASoC has all the pieces it needs to
* instantiate a sound driver.
*/
-static int cs4270_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = cs4270_codec;
- struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
- int i, ret;
-
- /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
- socdev->card->codec = codec;
-
- /* Register PCMs */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms\n");
- return ret;
- }
-
- /* Add the non-DAPM controls */
- ret = snd_soc_add_controls(codec, cs4270_snd_controls,
- ARRAY_SIZE(cs4270_snd_controls));
- if (ret < 0) {
- dev_err(codec->dev, "failed to add controls\n");
- goto error_free_pcms;
- }
-
- /* get the power supply regulators */
- for (i = 0; i < ARRAY_SIZE(supply_names); i++)
- cs4270->supplies[i].supply = supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
- cs4270->supplies);
- if (ret < 0)
- goto error_free_pcms;
-
- ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
- cs4270->supplies);
- if (ret < 0)
- goto error_free_regulators;
-
- return 0;
-
-error_free_regulators:
- regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
- cs4270->supplies);
-
-error_free_pcms:
- snd_soc_free_pcms(socdev);
-
- return ret;
-}
-
-/**
- * cs4270_remove - ASoC remove function
- * @pdev: platform device
- *
- * This function is the counterpart to cs4270_probe().
- */
-static int cs4270_remove(struct platform_device *pdev)
+static int cs4270_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = cs4270_codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
+ int i, ret, reg;
- snd_soc_free_pcms(socdev);
- regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
- regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
-
- return 0;
-};
-
-/**
- * cs4270_i2c_probe - initialize the I2C interface of the CS4270
- * @i2c_client: the I2C client object
- * @id: the I2C device ID (ignored)
- *
- * This function is called whenever the I2C subsystem finds a device that
- * matches the device ID given via a prior call to i2c_add_driver().
- */
-static int cs4270_i2c_probe(struct i2c_client *i2c_client,
- const struct i2c_device_id *id)
-{
- struct snd_soc_codec *codec;
- struct cs4270_private *cs4270;
- unsigned int reg;
- int ret;
-
- /* For now, we only support one cs4270 device in the system. See the
- * comment for cs4270_codec.
- */
- if (cs4270_codec) {
- dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n",
- i2c_client->addr);
- dev_err(&i2c_client->dev, "only one per board allowed\n");
- /* Should we return something other than ENODEV here? */
- return -ENODEV;
- }
-
- /* Verify that we have a CS4270 */
-
- ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
- i2c_client->addr);
- return ret;
- }
- /* The top four bits of the chip ID should be 1100. */
- if ((ret & 0xF0) != 0xC0) {
- dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
- i2c_client->addr);
- return -ENODEV;
- }
-
- dev_info(&i2c_client->dev, "found device at i2c address %X\n",
- i2c_client->addr);
- dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
-
- /* Allocate enough space for the snd_soc_codec structure
- and our private data together. */
- cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
- if (!cs4270) {
- dev_err(&i2c_client->dev, "could not allocate codec\n");
- return -ENOMEM;
- }
- codec = &cs4270->codec;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->dev = &i2c_client->dev;
- codec->name = "CS4270";
- codec->owner = THIS_MODULE;
- codec->dai = &cs4270_dai;
- codec->num_dai = 1;
- snd_soc_codec_set_drvdata(codec, cs4270);
- codec->control_data = i2c_client;
- codec->read = cs4270_read_reg_cache;
- codec->write = cs4270_i2c_write;
- codec->reg_cache = cs4270->reg_cache;
- codec->reg_cache_size = CS4270_NUMREGS;
+ codec->control_data = cs4270->control_data;
/* The I2C interface is set up, so pre-fill our register cache */
ret = cs4270_fill_cache(codec);
if (ret < 0) {
- dev_err(&i2c_client->dev, "failed to fill register cache\n");
- goto error_free_codec;
+ dev_err(codec->dev, "failed to fill register cache\n");
+ return ret;
}
/* Disable auto-mute. This feature appears to be buggy. In some
@@ -755,7 +573,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
reg &= ~CS4270_MUTE_AUTO;
ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);
if (ret < 0) {
- dev_err(&i2c_client->dev, "i2c write failed\n");
+ dev_err(codec->dev, "i2c write failed\n");
return ret;
}
@@ -769,65 +587,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
if (ret < 0) {
- dev_err(&i2c_client->dev, "i2c write failed\n");
+ dev_err(codec->dev, "i2c write failed\n");
return ret;
}
- /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI
- * structure for each CS4270 device, but the machine driver needs to
- * have a pointer to the DAI structure, so for now it must be a global
- * variable.
- */
- cs4270_dai.dev = &i2c_client->dev;
-
- /* Register the DAI. If all the other ASoC driver have already
- * registered, then this will call our probe function, so
- * cs4270_codec needs to be ready.
- */
- cs4270_codec = codec;
- ret = snd_soc_register_dai(&cs4270_dai);
+ /* Add the non-DAPM controls */
+ ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+ ARRAY_SIZE(cs4270_snd_controls));
if (ret < 0) {
- dev_err(&i2c_client->dev, "failed to register DAIe\n");
- goto error_free_codec;
+ dev_err(codec->dev, "failed to add controls\n");
+ return ret;
}
- i2c_set_clientdata(i2c_client, cs4270);
+ /* get the power supply regulators */
+ for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+ cs4270->supplies[i].supply = supply_names[i];
+
+ ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
+ cs4270->supplies);
+ if (ret < 0)
+ return ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
+ cs4270->supplies);
+ if (ret < 0)
+ goto error_free_regulators;
return 0;
-error_free_codec:
- kfree(cs4270);
- cs4270_codec = NULL;
- cs4270_dai.dev = NULL;
+error_free_regulators:
+ regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
+ cs4270->supplies);
return ret;
}
/**
- * cs4270_i2c_remove - remove an I2C device
- * @i2c_client: the I2C client object
+ * cs4270_remove - ASoC remove function
+ * @pdev: platform device
*
- * This function is the counterpart to cs4270_i2c_probe().
+ * This function is the counterpart to cs4270_probe().
*/
-static int cs4270_i2c_remove(struct i2c_client *i2c_client)
+static int cs4270_remove(struct snd_soc_codec *codec)
{
- struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client);
+ struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
- kfree(cs4270);
- cs4270_codec = NULL;
- cs4270_dai.dev = NULL;
+ regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
+ regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
return 0;
-}
-
-/*
- * cs4270_id - I2C device IDs supported by this driver
- */
-static struct i2c_device_id cs4270_id[] = {
- {"cs4270", 0},
- {}
};
-MODULE_DEVICE_TABLE(i2c, cs4270_id);
#ifdef CONFIG_PM
@@ -840,9 +649,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
* and all registers are written back to the hardware when resuming.
*/
-static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
+static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
{
- struct snd_soc_codec *codec = cs4270_codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int reg, ret;
@@ -860,9 +668,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
return 0;
}
-static int cs4270_soc_resume(struct platform_device *pdev)
+static int cs4270_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = cs4270_codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c_client = codec->control_data;
int reg;
@@ -896,6 +703,95 @@ static int cs4270_soc_resume(struct platform_device *pdev)
#endif /* CONFIG_PM */
/*
+ * ASoC codec device structure
+ *
+ * Assign this variable to the codec_dev field of the machine driver's
+ * snd_soc_device structure.
+ */
+static struct snd_soc_codec_driver soc_codec_device_cs4270 = {
+ .probe = cs4270_probe,
+ .remove = cs4270_remove,
+ .suspend = cs4270_soc_suspend,
+ .resume = cs4270_soc_resume,
+ .read = cs4270_read_reg_cache,
+ .write = cs4270_i2c_write,
+ .reg_cache_size = CS4270_NUMREGS,
+ .reg_word_size = sizeof(u8),
+};
+
+/**
+ * cs4270_i2c_probe - initialize the I2C interface of the CS4270
+ * @i2c_client: the I2C client object
+ * @id: the I2C device ID (ignored)
+ *
+ * This function is called whenever the I2C subsystem finds a device that
+ * matches the device ID given via a prior call to i2c_add_driver().
+ */
+static int cs4270_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
+{
+ struct cs4270_private *cs4270;
+ int ret;
+
+ /* Verify that we have a CS4270 */
+
+ ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
+ if (ret < 0) {
+ dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
+ i2c_client->addr);
+ return ret;
+ }
+ /* The top four bits of the chip ID should be 1100. */
+ if ((ret & 0xF0) != 0xC0) {
+ dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
+ i2c_client->addr);
+ return -ENODEV;
+ }
+
+ dev_info(&i2c_client->dev, "found device at i2c address %X\n",
+ i2c_client->addr);
+ dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
+
+ cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
+ if (!cs4270) {
+ dev_err(&i2c_client->dev, "could not allocate codec\n");
+ return -ENOMEM;
+ }
+
+ i2c_set_clientdata(i2c_client, cs4270);
+ cs4270->control_data = i2c_client;
+ cs4270->control_type = SND_SOC_I2C;
+
+ ret = snd_soc_register_codec(&i2c_client->dev,
+ &soc_codec_device_cs4270, &cs4270_dai, 1);
+ if (ret < 0)
+ kfree(cs4270);
+ return ret;
+}
+
+/**
+ * cs4270_i2c_remove - remove an I2C device
+ * @i2c_client: the I2C client object
+ *
+ * This function is the counterpart to cs4270_i2c_probe().
+ */
+static int cs4270_i2c_remove(struct i2c_client *i2c_client)
+{
+ snd_soc_unregister_codec(&i2c_client->dev);
+ kfree(i2c_get_clientdata(i2c_client));
+ return 0;
+}
+
+/*
+ * cs4270_id - I2C device IDs supported by this driver
+ */
+static struct i2c_device_id cs4270_id[] = {
+ {"cs4270", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cs4270_id);
+
+/*
* cs4270_i2c_driver - I2C device identification
*
* This structure tells the I2C subsystem how to identify and support a
@@ -903,7 +799,7 @@ static int cs4270_soc_resume(struct platform_device *pdev)
*/
static struct i2c_driver cs4270_i2c_driver = {
.driver = {
- .name = "cs4270",
+ .name = "cs4270-codec",
.owner = THIS_MODULE,
},
.id_table = cs4270_id,
@@ -911,20 +807,6 @@ static struct i2c_driver cs4270_i2c_driver = {
.remove = cs4270_i2c_remove,
};
-/*
- * ASoC codec device structure
- *
- * Assign this variable to the codec_dev field of the machine driver's
- * snd_soc_device structure.
- */
-struct snd_soc_codec_device soc_codec_device_cs4270 = {
- .probe = cs4270_probe,
- .remove = cs4270_remove,
- .suspend = cs4270_soc_suspend,
- .resume = cs4270_soc_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
-
static int __init cs4270_init(void)
{
pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h
deleted file mode 100644
index adc6cd9667d4..000000000000
--- a/sound/soc/codecs/cs4270.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Cirrus Logic CS4270 ALSA SoC Codec Driver
- *
- * Author: Timur Tabi <timur@freescale.com>
- *
- * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef _CS4270_H
-#define _CS4270_H
-
-/*
- * The ASoC codec DAI structure for the CS4270. Assign this structure to
- * the .codec_dai field of your machine driver's snd_soc_dai_link structure.
- */
-extern struct snd_soc_dai cs4270_dai;
-
-/*
- * The ASoC codec device structure for the CS4270. Assign this structure
- * to the .codec_dev field of your machine driver's snd_soc_device
- * structure.
- */
-extern struct snd_soc_codec_device soc_codec_device_cs4270;
-
-#endif
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index dd9b8550c402..cb086eaf4e07 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -42,15 +42,14 @@ enum master_slave_mode {
};
struct cs42l51_private {
+ enum snd_soc_control_type control_type;
+ void *control_data;
unsigned int mclk;
unsigned int audio_mode; /* The mode (I2S or left-justified) */
enum master_slave_mode func;
- struct snd_soc_codec codec;
u8 reg_cache[CS42L51_NUMREGS];
};
-static struct snd_soc_codec *cs42l51_codec;
-
#define CS42L51_FORMATS ( \
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
@@ -75,134 +74,6 @@ static int cs42l51_fill_cache(struct snd_soc_codec *codec)
return 0;
}
-static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
- const struct i2c_device_id *id)
-{
- struct snd_soc_codec *codec;
- struct cs42l51_private *cs42l51;
- int ret = 0;
- int reg;
-
- if (cs42l51_codec)
- return -EBUSY;
-
- /* Verify that we have a CS42L51 */
- ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "failed to read I2C\n");
- goto error;
- }
-
- if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
- (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
- dev_err(&i2c_client->dev, "Invalid chip id\n");
- ret = -ENODEV;
- goto error;
- }
-
- dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
- ret & 7);
-
- cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
- if (!cs42l51) {
- dev_err(&i2c_client->dev, "could not allocate codec\n");
- return -ENOMEM;
- }
- codec = &cs42l51->codec;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->dev = &i2c_client->dev;
- codec->name = "CS42L51";
- codec->owner = THIS_MODULE;
- codec->dai = &cs42l51_dai;
- codec->num_dai = 1;
- snd_soc_codec_set_drvdata(codec, cs42l51);
-
- codec->control_data = i2c_client;
- codec->reg_cache = cs42l51->reg_cache;
- codec->reg_cache_size = CS42L51_NUMREGS;
- i2c_set_clientdata(i2c_client, codec);
-
- ret = cs42l51_fill_cache(codec);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "failed to fill register cache\n");
- goto error_alloc;
- }
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret);
- goto error_alloc;
- }
-
- /*
- * DAC configuration
- * - Use signal processor
- * - auto mute
- * - vol changes immediate
- * - no de-emphasize
- */
- reg = CS42L51_DAC_CTL_DATA_SEL(1)
- | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
- ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
- if (ret < 0)
- goto error_alloc;
-
- cs42l51_dai.dev = codec->dev;
- cs42l51_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto error_alloc;
- }
-
- ret = snd_soc_register_dai(&cs42l51_dai);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "failed to register DAIe\n");
- goto error_reg;
- }
-
- return 0;
-
-error_reg:
- snd_soc_unregister_codec(codec);
-error_alloc:
- kfree(cs42l51);
-error:
- return ret;
-}
-
-static int cs42l51_i2c_remove(struct i2c_client *client)
-{
- struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
- snd_soc_unregister_dai(&cs42l51_dai);
- snd_soc_unregister_codec(cs42l51_codec);
- cs42l51_codec = NULL;
- kfree(cs42l51);
- return 0;
-}
-
-
-static const struct i2c_device_id cs42l51_id[] = {
- {"cs42l51", 0},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, cs42l51_id);
-
-static struct i2c_driver cs42l51_i2c_driver = {
- .driver = {
- .name = "CS42L51 I2C",
- .owner = THIS_MODULE,
- },
- .id_table = cs42l51_id,
- .probe = cs42l51_i2c_probe,
- .remove = cs42l51_i2c_remove,
-};
-
static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -484,51 +355,8 @@ static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
- struct cs42l51_ratios *ratios = NULL;
- int nr_ratios = 0;
- unsigned int rates = 0;
- unsigned int rate_min = -1;
- unsigned int rate_max = 0;
- int i;
cs42l51->mclk = freq;
-
- switch (cs42l51->func) {
- case MODE_MASTER:
- return -EINVAL;
- case MODE_SLAVE:
- ratios = slave_ratios;
- nr_ratios = ARRAY_SIZE(slave_ratios);
- break;
- case MODE_SLAVE_AUTO:
- ratios = slave_auto_ratios;
- nr_ratios = ARRAY_SIZE(slave_auto_ratios);
- break;
- }
-
- for (i = 0; i < nr_ratios; i++) {
- unsigned int rate = freq / ratios[i].ratio;
- rates |= snd_pcm_rate_to_rate_bit(rate);
- if (rate < rate_min)
- rate_min = rate;
- if (rate > rate_max)
- rate_max = rate;
- }
- rates &= ~SNDRV_PCM_RATE_KNOT;
-
- if (!rates) {
- dev_err(codec->dev, "could not find a valid sample rate\n");
- return -EINVAL;
- }
-
- codec_dai->playback.rates = rates;
- codec_dai->playback.rate_min = rate_min;
- codec_dai->playback.rate_max = rate_max;
-
- codec_dai->capture.rates = rates;
- codec_dai->capture.rate_min = rate_min;
- codec_dai->capture.rate_max = rate_max;
-
return 0;
}
@@ -537,8 +365,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
int ret;
unsigned int i;
@@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = {
.digital_mute = cs42l51_dai_mute,
};
-struct snd_soc_dai cs42l51_dai = {
- .name = "CS42L51 HiFi",
+static struct snd_soc_dai_driver cs42l51_dai = {
+ .name = "cs42l51-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = {
},
.ops = &cs42l51_dai_ops,
};
-EXPORT_SYMBOL_GPL(cs42l51_dai);
-
-static int cs42l51_probe(struct platform_device *pdev)
+static int cs42l51_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
+ struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
+ int ret, reg;
- if (!cs42l51_codec) {
- dev_err(&pdev->dev, "CS42L51 codec not yet registered\n");
- return -EINVAL;
- }
+ codec->control_data = cs42l51->control_data;
- socdev->card->codec = cs42l51_codec;
- codec = socdev->card->codec;
+ ret = cs42l51_fill_cache(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "failed to fill register cache\n");
+ return ret;
+ }
- /* Register PCMs */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type);
if (ret < 0) {
- dev_err(&pdev->dev, "failed to create PCMs\n");
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
+ /*
+ * DAC configuration
+ * - Use signal processor
+ * - auto mute
+ * - vol changes immediate
+ * - no de-emphasize
+ */
+ reg = CS42L51_DAC_CTL_DATA_SEL(1)
+ | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
+ ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
+ if (ret < 0)
+ return ret;
+
snd_soc_add_controls(codec, cs42l51_snd_controls,
ARRAY_SIZE(cs42l51_snd_controls));
snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
@@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev)
return 0;
}
+static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
+ .probe = cs42l51_probe,
+ .reg_cache_size = CS42L51_NUMREGS,
+ .reg_word_size = sizeof(u8),
+};
-static int cs42l51_remove(struct platform_device *pdev)
+static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct cs42l51_private *cs42l51;
+ int ret;
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ /* Verify that we have a CS42L51 */
+ ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
+ if (ret < 0) {
+ dev_err(&i2c_client->dev, "failed to read I2C\n");
+ goto error;
+ }
+
+ if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
+ (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
+ dev_err(&i2c_client->dev, "Invalid chip id\n");
+ ret = -ENODEV;
+ goto error;
+ }
+
+ dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
+ ret & 7);
+
+ cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
+ if (!cs42l51) {
+ dev_err(&i2c_client->dev, "could not allocate codec\n");
+ return -ENOMEM;
+ }
+
+ i2c_set_clientdata(i2c_client, cs42l51);
+ cs42l51->control_data = i2c_client;
+ cs42l51->control_type = SND_SOC_I2C;
+ ret = snd_soc_register_codec(&i2c_client->dev,
+ &soc_codec_device_cs42l51, &cs42l51_dai, 1);
+ if (ret < 0)
+ kfree(cs42l51);
+error:
+ return ret;
+}
+
+static int cs42l51_i2c_remove(struct i2c_client *client)
+{
+ struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ kfree(cs42l51);
return 0;
}
-struct snd_soc_codec_device soc_codec_device_cs42l51 = {
- .probe = cs42l51_probe,
- .remove = cs42l51_remove
+static const struct i2c_device_id cs42l51_id[] = {
+ {"cs42l51", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cs42l51_id);
+
+static struct i2c_driver cs42l51_i2c_driver = {
+ .driver = {
+ .name = "cs42l51-codec",
+ .owner = THIS_MODULE,
+ },
+ .id_table = cs42l51_id,
+ .probe = cs42l51_i2c_probe,
+ .remove = cs42l51_i2c_remove,
};
-EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51);
static int __init cs42l51_init(void)
{
@@ -758,6 +649,6 @@ static void __exit cs42l51_exit(void)
}
module_exit(cs42l51_exit);
-MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h
index 8f0bd9786ad2..2beeb171db4b 100644
--- a/sound/soc/codecs/cs42l51.h
+++ b/sound/soc/codecs/cs42l51.h
@@ -158,6 +158,4 @@
#define CS42L51_LASTREG 0x20
#define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1)
-extern struct snd_soc_dai cs42l51_dai;
-extern struct snd_soc_codec_device soc_codec_device_cs42l51;
#endif
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index f07a415c753f..e8d27c8f9ba3 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -24,7 +24,8 @@
struct cx20442_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
u8 reg_cache[1];
};
@@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,
{
u8 *reg_cache = codec->reg_cache;
- if (reg >= codec->reg_cache_size)
+ if (reg >= codec->driver->reg_cache_size)
return -EINVAL;
return reg_cache[reg];
@@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value)
static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
+ struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
u8 *reg_cache = codec->reg_cache;
int vls, vsp, old, len;
char buf[18];
- if (reg >= codec->reg_cache_size)
+ if (reg >= codec->driver->reg_cache_size)
return -EINVAL;
/* hw_write and control_data pointers required for talking to the modem
* are expected to be set by the line discipline initialization code */
- if (!codec->hw_write || !codec->control_data)
+ if (!codec->hw_write || !cx20442->control_data)
return -EIO;
old = reg_cache[reg];
@@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
return -ENOMEM;
dev_dbg(codec->dev, "%s: %s\n", __func__, buf);
- if (codec->hw_write(codec->control_data, buf, len) != len)
+ if (codec->hw_write(cx20442->control_data, buf, len) != len)
return -EIO;
return 0;
}
-/* Moved up here as line discipline referres it during initialization */
-static struct snd_soc_codec *cx20442_codec;
-
-
/*
* Line discpline related code
*
@@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r";
/* Line discipline .open() */
static int v253_open(struct tty_struct *tty)
{
- struct snd_soc_codec *codec = cx20442_codec;
int ret, len = strlen(v253_init);
/* Doesn't make sense without write callback */
if (!tty->ops->write)
return -EINVAL;
- /* Pass the codec structure address for use by other ldisc callbacks */
- tty->disc_data = codec;
+ /* Won't work if no codec pointer has been passed by a card driver */
+ if (!tty->disc_data)
+ return -ENODEV;
if (tty->ops->write(tty, v253_init, len) != len) {
ret = -EIO;
@@ -253,15 +251,18 @@ err:
static void v253_close(struct tty_struct *tty)
{
struct snd_soc_codec *codec = tty->disc_data;
+ struct cx20442_priv *cx20442;
tty->disc_data = NULL;
if (!codec)
return;
+ cx20442 = snd_soc_codec_get_drvdata(codec);
+
/* Prevent the codec driver from further accessing the modem */
codec->hw_write = NULL;
- codec->control_data = NULL;
+ cx20442->control_data = NULL;
codec->pop_time = 0;
}
@@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty,
const unsigned char *cp, char *fp, int count)
{
struct snd_soc_codec *codec = tty->disc_data;
+ struct cx20442_priv *cx20442;
if (!codec)
return;
- if (!codec->control_data) {
+ cx20442 = snd_soc_codec_get_drvdata(codec);
+
+ if (!cx20442->control_data) {
/* First modem response, complete setup procedure */
/* Set up codec driver access to modem controls */
- codec->control_data = tty;
+ cx20442->control_data = tty;
codec->hw_write = (hw_write_t)tty->ops->write;
codec->pop_time = 1;
}
@@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops);
* Codec DAI
*/
-struct snd_soc_dai cx20442_dai = {
- .name = "CX20442",
+static struct snd_soc_dai_driver cx20442_dai = {
+ .name = "cx20442-voice",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
};
-EXPORT_SYMBOL_GPL(cx20442_dai);
-static int cx20442_codec_probe(struct platform_device *pdev)
+static int cx20442_codec_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret;
-
- if (!cx20442_codec) {
- dev_err(&pdev->dev, "cx20442 not yet discovered\n");
- return -ENODEV;
- }
- codec = cx20442_codec;
-
- socdev->card->codec = codec;
+ struct cx20442_priv *cx20442;
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to create pcms\n");
- goto pcm_err;
- }
+ cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
+ if (cx20442 == NULL)
+ return -ENOMEM;
+ snd_soc_codec_set_drvdata(codec, cx20442);
cx20442_add_widgets(codec);
-pcm_err:
- return ret;
+ cx20442->control_data = NULL;
+ codec->hw_write = NULL;
+ codec->pop_time = 0;
+
+ return 0;
}
/* power down chip */
-static int cx20442_codec_remove(struct platform_device *pdev)
+static int cx20442_codec_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ if (cx20442->control_data) {
+ struct tty_struct *tty = cx20442->control_data;
+ tty_hangup(tty);
+ }
+ kfree(cx20442);
return 0;
}
-struct snd_soc_codec_device cx20442_codec_dev = {
+static struct snd_soc_codec_driver cx20442_codec_dev = {
.probe = cx20442_codec_probe,
.remove = cx20442_codec_remove,
+ .reg_cache_size = 1,
+ .reg_word_size = sizeof(u8),
+ .read = cx20442_read_reg_cache,
+ .write = cx20442_write,
};
-EXPORT_SYMBOL_GPL(cx20442_codec_dev);
-
-static int cx20442_register(struct cx20442_priv *cx20442)
-{
- struct snd_soc_codec *codec = &cx20442->codec;
- int ret;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "CX20442";
- codec->owner = THIS_MODULE;
- snd_soc_codec_set_drvdata(codec, cx20442);
-
- codec->dai = &cx20442_dai;
- codec->num_dai = 1;
-
- codec->reg_cache = &cx20442->reg_cache;
- codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache);
- codec->read = cx20442_read_reg_cache;
- codec->write = cx20442_write;
-
- codec->bias_level = SND_SOC_BIAS_OFF;
-
- cx20442_dai.dev = codec->dev;
-
- cx20442_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&cx20442_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
- return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- cx20442_codec = NULL;
- kfree(cx20442);
- return ret;
-}
-
-static void cx20442_unregister(struct cx20442_priv *cx20442)
-{
- snd_soc_unregister_dai(&cx20442_dai);
- snd_soc_unregister_codec(&cx20442->codec);
-
- cx20442_codec = NULL;
- kfree(cx20442);
-}
static int cx20442_platform_probe(struct platform_device *pdev)
{
- struct cx20442_priv *cx20442;
- struct snd_soc_codec *codec;
-
- cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
- if (cx20442 == NULL)
- return -ENOMEM;
-
- codec = &cx20442->codec;
-
- codec->control_data = NULL;
- codec->hw_write = NULL;
- codec->pop_time = 0;
-
- codec->dev = &pdev->dev;
- platform_set_drvdata(pdev, cx20442);
-
- return cx20442_register(cx20442);
+ return snd_soc_register_codec(&pdev->dev,
+ &cx20442_codec_dev, &cx20442_dai, 1);
}
static int __exit cx20442_platform_remove(struct platform_device *pdev)
{
- struct cx20442_priv *cx20442 = platform_get_drvdata(pdev);
-
- cx20442_unregister(cx20442);
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
static struct platform_driver cx20442_platform_driver = {
.driver = {
- .name = "cx20442",
+ .name = "cx20442-codec",
.owner = THIS_MODULE,
},
.probe = cx20442_platform_probe,
@@ -487,4 +412,4 @@ module_exit(cx20442_exit);
MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
MODULE_AUTHOR("Janusz Krzysztofik");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:cx20442");
+MODULE_ALIAS("platform:cx20442-codec");
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h
index 688a5eb62e17..c7a7c79ef0cd 100644
--- a/sound/soc/codecs/cx20442.h
+++ b/sound/soc/codecs/cx20442.h
@@ -13,8 +13,6 @@
#ifndef _CX20442_CODEC_H
#define _CX20442_CODEC_H
-extern struct snd_soc_dai cx20442_dai;
-extern struct snd_soc_codec_device cx20442_codec_dev;
extern struct tty_ldisc_ops v253_ops;
#endif
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 3c51d6a57523..58bb9b994811 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -25,8 +25,6 @@
#include <sound/initval.h>
#include <sound/tlv.h>
-#include "da7210.h"
-
/* DA7210 register space */
#define DA7210_STATUS 0x02
#define DA7210_STARTUP1 0x03
@@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = {
/* Codec private data */
struct da7210_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
};
-static struct snd_soc_codec *da7210_codec;
-
/*
* Register cache
*/
@@ -209,12 +206,12 @@ static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)
u8 *cache = codec->reg_cache;
u8 data[2];
- BUG_ON(codec->volatile_register);
+ BUG_ON(codec->driver->volatile_register);
data[0] = reg & 0xff;
data[1] = value & 0xff;
- if (reg >= codec->reg_cache_size)
+ if (reg >= codec->driver->reg_cache_size)
return -EIO;
if (2 != codec->hw_write(codec->control_data, data, 2))
@@ -267,8 +264,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u32 dai_cfg1;
u32 hpf_reg, hpf_mask, hpf_value;
u32 fs, bypass;
@@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = {
.set_fmt = da7210_set_dai_fmt,
};
-struct snd_soc_dai da7210_dai = {
- .name = "DA7210 IIS",
- .id = 0,
+static struct snd_soc_dai_driver da7210_dai = {
+ .name = "da7210-hifi",
/* playback capabilities */
.playback = {
.stream_name = "Playback",
@@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = {
.ops = &da7210_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(da7210_dai);
-/*
- * Initialize the DA7210 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int da7210_init(struct da7210_priv *da7210)
+static int da7210_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = &da7210->codec;
- int ret = 0;
+ struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
- if (da7210_codec) {
- dev_err(codec->dev, "Another da7210 is registered\n");
- return -EINVAL;
- }
+ dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, da7210);
- codec->name = "DA7210";
- codec->owner = THIS_MODULE;
- codec->read = da7210_read;
- codec->write = da7210_write;
- codec->dai = &da7210_dai;
- codec->num_dai = 1;
+ codec->control_data = da7210->control_data;
codec->hw_write = (hw_write_t)i2c_master_send;
- codec->reg_cache_size = ARRAY_SIZE(da7210_reg);
- codec->reg_cache = kmemdup(da7210_reg,
- sizeof(da7210_reg), GFP_KERNEL);
-
- if (!codec->reg_cache)
- return -ENOMEM;
-
- da7210_dai.dev = codec->dev;
- da7210_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret) {
- dev_err(codec->dev, "Failed to register CODEC: %d\n", ret);
- goto init_err;
- }
-
- ret = snd_soc_register_dai(&da7210_dai);
- if (ret) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto codec_err;
- }
/* FIXME
*
@@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210)
/* Activate all enabled subsystem */
da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
- return ret;
-
-codec_err:
- snd_soc_unregister_codec(codec);
-init_err:
- kfree(codec->reg_cache);
- codec->reg_cache = NULL;
+ snd_soc_add_controls(codec, da7210_snd_controls,
+ ARRAY_SIZE(da7210_snd_controls));
- return ret;
+ dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
+ .probe = da7210_probe,
+ .read = da7210_read,
+ .write = da7210_write,
+ .reg_cache_size = ARRAY_SIZE(da7210_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = da7210_reg,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct da7210_priv *da7210;
- struct snd_soc_codec *codec;
int ret;
da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL);
if (!da7210)
return -ENOMEM;
- codec = &da7210->codec;
- codec->dev = &i2c->dev;
-
i2c_set_clientdata(i2c, da7210);
- codec->control_data = i2c;
+ da7210->control_data = i2c;
+ da7210->control_type = SND_SOC_I2C;
- ret = da7210_init(da7210);
- if (ret < 0) {
- pr_err("Failed to initialise da7210 audio codec\n");
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_da7210, &da7210_dai, 1);
+ if (ret < 0)
kfree(da7210);
- }
return ret;
}
static int __devexit da7210_i2c_remove(struct i2c_client *client)
{
- struct da7210_priv *da7210 = i2c_get_clientdata(client);
-
- snd_soc_unregister_dai(&da7210_dai);
- kfree(da7210->codec.reg_cache);
- kfree(da7210);
- da7210_codec = NULL;
-
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -643,59 +594,15 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
/* I2C codec control layer */
static struct i2c_driver da7210_i2c_driver = {
.driver = {
- .name = "DA7210 I2C Codec",
+ .name = "da7210-codec",
.owner = THIS_MODULE,
},
- .probe = da7210_i2c_probe,
- .remove = __devexit_p(da7210_i2c_remove),
- .id_table = da7210_i2c_id,
+ .probe = da7210_i2c_probe,
+ .remove = __devexit_p(da7210_i2c_remove),
+ .id_table = da7210_i2c_id,
};
#endif
-static int da7210_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret;
-
- if (!da7210_codec) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = da7210_codec;
- codec = da7210_codec;
-
- /* Register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0)
- goto pcm_err;
-
- snd_soc_add_controls(da7210_codec, da7210_snd_controls,
- ARRAY_SIZE(da7210_snd_controls));
-
- dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
-
-pcm_err:
- return ret;
-}
-
-static int da7210_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_da7210 = {
- .probe = da7210_probe,
- .remove = da7210_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_da7210);
-
static int __init da7210_modinit(void)
{
int ret = 0;
diff --git a/sound/soc/codecs/da7210.h b/sound/soc/codecs/da7210.h
deleted file mode 100644
index 390d621eb742..000000000000
--- a/sound/soc/codecs/da7210.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * da7210.h -- audio driver for da7210
- *
- * Copyright (c) 2009 Dialog Semiconductor
- * Written by David Chen <Dajun.chen@diasemi.com>
- *
- * Copyright (C) 2009 Renesas Solutions Corp.
- * Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
-
-#ifndef _DA7210_H
-#define _DA7210_H
-
-extern struct snd_soc_dai da7210_dai;
-extern struct snd_soc_codec_device soc_codec_dev_da7210;
-
-#endif
-
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 66557de1e4fe..16253ec9b022 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = {
struct jz4740_codec {
void __iomem *base;
struct resource *mem;
-
- uint32_t reg_cache[2];
- struct snd_soc_codec codec;
};
-static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
-{
- return container_of(codec, struct jz4740_codec, codec);
-}
-
static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
unsigned int reg)
{
- struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
+ struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
return readl(jz4740_codec->base + (reg << 2));
}
static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int val)
{
- struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
+ struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
+ u32 *cache = codec->reg_cache;
- jz4740_codec->reg_cache[reg] = val;
+ cache[reg] = val;
writel(val, jz4740_codec->base + (reg << 2));
return 0;
@@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
{
uint32_t val;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec =rtd->codec;
switch (params_rate(params)) {
case 8000:
@@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
.hw_params = jz4740_codec_hw_params,
};
-struct snd_soc_dai jz4740_codec_dai = {
- .name = "jz4740",
+static struct snd_soc_dai_driver jz4740_codec_dai = {
+ .name = "jz4740-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = {
.ops = &jz4740_codec_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(jz4740_codec_dai);
static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
{
@@ -302,23 +293,10 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static struct snd_soc_codec *jz4740_codec_codec;
-
-static int jz4740_codec_dev_probe(struct platform_device *pdev)
+static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
{
- int ret;
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = jz4740_codec_codec;
-
- BUG_ON(!codec);
-
- socdev->card->codec = codec;
-
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret) {
- dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
- return ret;
- }
+ snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+ JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
snd_soc_add_controls(codec, jz4740_codec_controls,
ARRAY_SIZE(jz4740_codec_controls));
@@ -331,34 +309,27 @@ static int jz4740_codec_dev_probe(struct platform_device *pdev)
snd_soc_dapm_new_widgets(codec);
+ jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
return 0;
}
-static int jz4740_codec_dev_remove(struct platform_device *pdev)
+static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
#ifdef CONFIG_PM_SLEEP
-static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state)
+static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
-static int jz4740_codec_resume(struct platform_device *pdev)
+static int jz4740_codec_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
}
@@ -367,19 +338,23 @@ static int jz4740_codec_resume(struct platform_device *pdev)
#define jz4740_codec_resume NULL
#endif
-struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
+static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
.probe = jz4740_codec_dev_probe,
.remove = jz4740_codec_dev_remove,
.suspend = jz4740_codec_suspend,
.resume = jz4740_codec_resume,
+ .read = jz4740_codec_read,
+ .write = jz4740_codec_write,
+ .set_bias_level = jz4740_codec_set_bias_level,
+ .reg_cache_default = jz4740_codec_regs,
+ .reg_word_size = sizeof(u32),
+ .reg_cache_size = 2,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
static int __devinit jz4740_codec_probe(struct platform_device *pdev)
{
int ret;
struct jz4740_codec *jz4740_codec;
- struct snd_soc_codec *codec;
struct resource *mem;
jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
@@ -408,55 +383,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
}
jz4740_codec->mem = mem;
- jz4740_codec_dai.dev = &pdev->dev;
-
- codec = &jz4740_codec->codec;
-
- codec->dev = &pdev->dev;
- codec->name = "jz4740";
- codec->owner = THIS_MODULE;
-
- codec->read = jz4740_codec_read;
- codec->write = jz4740_codec_write;
- codec->set_bias_level = jz4740_codec_set_bias_level;
- codec->bias_level = SND_SOC_BIAS_OFF;
-
- codec->dai = &jz4740_codec_dai;
- codec->num_dai = 1;
-
- codec->reg_cache = jz4740_codec->reg_cache;
- codec->reg_cache_size = 2;
- memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs));
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- jz4740_codec_codec = codec;
-
- snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
- JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
-
platform_set_drvdata(pdev, jz4740_codec);
- ret = snd_soc_register_codec(codec);
+ ret = snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
if (ret) {
dev_err(&pdev->dev, "Failed to register codec\n");
goto err_iounmap;
}
- ret = snd_soc_register_dai(&jz4740_codec_dai);
- if (ret) {
- dev_err(&pdev->dev, "Failed to register codec dai\n");
- goto err_unregister_codec;
- }
-
- jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
-err_unregister_codec:
- snd_soc_unregister_codec(codec);
err_iounmap:
iounmap(jz4740_codec->base);
err_release_mem_region:
@@ -472,8 +409,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
struct resource *mem = jz4740_codec->mem;
- snd_soc_unregister_dai(&jz4740_codec_dai);
- snd_soc_unregister_codec(&jz4740_codec->codec);
+ snd_soc_unregister_codec(&pdev->dev);
iounmap(jz4740_codec->base);
release_mem_region(mem->start, resource_size(mem));
diff --git a/sound/soc/codecs/jz4740.h b/sound/soc/codecs/jz4740.h
deleted file mode 100644
index b5a0691be763..000000000000
--- a/sound/soc/codecs/jz4740.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__
-#define __SND_SOC_CODECS_JZ4740_CODEC_H__
-
-extern struct snd_soc_dai jz4740_codec_dai;
-extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec;
-
-#endif
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
new file mode 100644
index 000000000000..d63e28773eb1
--- /dev/null
+++ b/sound/soc/codecs/max98088.c
@@ -0,0 +1,2109 @@
+/*
+ * max98088.c -- MAX98088 ALSA SoC Audio driver
+ *
+ * Copyright 2010 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+#include <sound/max98088.h>
+#include "max98088.h"
+
+enum max98088_type {
+ MAX98088,
+ MAX98089,
+};
+
+struct max98088_cdata {
+ unsigned int rate;
+ unsigned int fmt;
+ int eq_sel;
+};
+
+struct max98088_priv {
+ u8 reg_cache[M98088_REG_CNT];
+ enum max98088_type devtype;
+ void *control_data;
+ struct max98088_pdata *pdata;
+ unsigned int sysclk;
+ struct max98088_cdata dai[2];
+ int eq_textcnt;
+ const char **eq_texts;
+ struct soc_enum eq_enum;
+ u8 ina_state;
+ u8 inb_state;
+ unsigned int ex_mode;
+ unsigned int digmic;
+ unsigned int mic1pre;
+ unsigned int mic2pre;
+ unsigned int extmic_mode;
+};
+
+static const u8 max98088_reg[M98088_REG_CNT] = {
+ 0x00, /* 00 IRQ status */
+ 0x00, /* 01 MIC status */
+ 0x00, /* 02 jack status */
+ 0x00, /* 03 battery voltage */
+ 0x00, /* 04 */
+ 0x00, /* 05 */
+ 0x00, /* 06 */
+ 0x00, /* 07 */
+ 0x00, /* 08 */
+ 0x00, /* 09 */
+ 0x00, /* 0A */
+ 0x00, /* 0B */
+ 0x00, /* 0C */
+ 0x00, /* 0D */
+ 0x00, /* 0E */
+ 0x00, /* 0F interrupt enable */
+
+ 0x00, /* 10 master clock */
+ 0x00, /* 11 DAI1 clock mode */
+ 0x00, /* 12 DAI1 clock control */
+ 0x00, /* 13 DAI1 clock control */
+ 0x00, /* 14 DAI1 format */
+ 0x00, /* 15 DAI1 clock */
+ 0x00, /* 16 DAI1 config */
+ 0x00, /* 17 DAI1 TDM */
+ 0x00, /* 18 DAI1 filters */
+ 0x00, /* 19 DAI2 clock mode */
+ 0x00, /* 1A DAI2 clock control */
+ 0x00, /* 1B DAI2 clock control */
+ 0x00, /* 1C DAI2 format */
+ 0x00, /* 1D DAI2 clock */
+ 0x00, /* 1E DAI2 config */
+ 0x00, /* 1F DAI2 TDM */
+
+ 0x00, /* 20 DAI2 filters */
+ 0x00, /* 21 data config */
+ 0x00, /* 22 DAC mixer */
+ 0x00, /* 23 left ADC mixer */
+ 0x00, /* 24 right ADC mixer */
+ 0x00, /* 25 left HP mixer */
+ 0x00, /* 26 right HP mixer */
+ 0x00, /* 27 HP control */
+ 0x00, /* 28 left REC mixer */
+ 0x00, /* 29 right REC mixer */
+ 0x00, /* 2A REC control */
+ 0x00, /* 2B left SPK mixer */
+ 0x00, /* 2C right SPK mixer */
+ 0x00, /* 2D SPK control */
+ 0x00, /* 2E sidetone */
+ 0x00, /* 2F DAI1 playback level */
+
+ 0x00, /* 30 DAI1 playback level */
+ 0x00, /* 31 DAI2 playback level */
+ 0x00, /* 32 DAI2 playbakc level */
+ 0x00, /* 33 left ADC level */
+ 0x00, /* 34 right ADC level */
+ 0x00, /* 35 MIC1 level */
+ 0x00, /* 36 MIC2 level */
+ 0x00, /* 37 INA level */
+ 0x00, /* 38 INB level */
+ 0x00, /* 39 left HP volume */
+ 0x00, /* 3A right HP volume */
+ 0x00, /* 3B left REC volume */
+ 0x00, /* 3C right REC volume */
+ 0x00, /* 3D left SPK volume */
+ 0x00, /* 3E right SPK volume */
+ 0x00, /* 3F MIC config */
+
+ 0x00, /* 40 MIC threshold */
+ 0x00, /* 41 excursion limiter filter */
+ 0x00, /* 42 excursion limiter threshold */
+ 0x00, /* 43 ALC */
+ 0x00, /* 44 power limiter threshold */
+ 0x00, /* 45 power limiter config */
+ 0x00, /* 46 distortion limiter config */
+ 0x00, /* 47 audio input */
+ 0x00, /* 48 microphone */
+ 0x00, /* 49 level control */
+ 0x00, /* 4A bypass switches */
+ 0x00, /* 4B jack detect */
+ 0x00, /* 4C input enable */
+ 0x00, /* 4D output enable */
+ 0xF0, /* 4E bias control */
+ 0x00, /* 4F DAC power */
+
+ 0x0F, /* 50 DAC power */
+ 0x00, /* 51 system */
+ 0x00, /* 52 DAI1 EQ1 */
+ 0x00, /* 53 DAI1 EQ1 */
+ 0x00, /* 54 DAI1 EQ1 */
+ 0x00, /* 55 DAI1 EQ1 */
+ 0x00, /* 56 DAI1 EQ1 */
+ 0x00, /* 57 DAI1 EQ1 */
+ 0x00, /* 58 DAI1 EQ1 */
+ 0x00, /* 59 DAI1 EQ1 */
+ 0x00, /* 5A DAI1 EQ1 */
+ 0x00, /* 5B DAI1 EQ1 */
+ 0x00, /* 5C DAI1 EQ2 */
+ 0x00, /* 5D DAI1 EQ2 */
+ 0x00, /* 5E DAI1 EQ2 */
+ 0x00, /* 5F DAI1 EQ2 */
+
+ 0x00, /* 60 DAI1 EQ2 */
+ 0x00, /* 61 DAI1 EQ2 */
+ 0x00, /* 62 DAI1 EQ2 */
+ 0x00, /* 63 DAI1 EQ2 */
+ 0x00, /* 64 DAI1 EQ2 */
+ 0x00, /* 65 DAI1 EQ2 */
+ 0x00, /* 66 DAI1 EQ3 */
+ 0x00, /* 67 DAI1 EQ3 */
+ 0x00, /* 68 DAI1 EQ3 */
+ 0x00, /* 69 DAI1 EQ3 */
+ 0x00, /* 6A DAI1 EQ3 */
+ 0x00, /* 6B DAI1 EQ3 */
+ 0x00, /* 6C DAI1 EQ3 */
+ 0x00, /* 6D DAI1 EQ3 */
+ 0x00, /* 6E DAI1 EQ3 */
+ 0x00, /* 6F DAI1 EQ3 */
+
+ 0x00, /* 70 DAI1 EQ4 */
+ 0x00, /* 71 DAI1 EQ4 */
+ 0x00, /* 72 DAI1 EQ4 */
+ 0x00, /* 73 DAI1 EQ4 */
+ 0x00, /* 74 DAI1 EQ4 */
+ 0x00, /* 75 DAI1 EQ4 */
+ 0x00, /* 76 DAI1 EQ4 */
+ 0x00, /* 77 DAI1 EQ4 */
+ 0x00, /* 78 DAI1 EQ4 */
+ 0x00, /* 79 DAI1 EQ4 */
+ 0x00, /* 7A DAI1 EQ5 */
+ 0x00, /* 7B DAI1 EQ5 */
+ 0x00, /* 7C DAI1 EQ5 */
+ 0x00, /* 7D DAI1 EQ5 */
+ 0x00, /* 7E DAI1 EQ5 */
+ 0x00, /* 7F DAI1 EQ5 */
+
+ 0x00, /* 80 DAI1 EQ5 */
+ 0x00, /* 81 DAI1 EQ5 */
+ 0x00, /* 82 DAI1 EQ5 */
+ 0x00, /* 83 DAI1 EQ5 */
+ 0x00, /* 84 DAI2 EQ1 */
+ 0x00, /* 85 DAI2 EQ1 */
+ 0x00, /* 86 DAI2 EQ1 */
+ 0x00, /* 87 DAI2 EQ1 */
+ 0x00, /* 88 DAI2 EQ1 */
+ 0x00, /* 89 DAI2 EQ1 */
+ 0x00, /* 8A DAI2 EQ1 */
+ 0x00, /* 8B DAI2 EQ1 */
+ 0x00, /* 8C DAI2 EQ1 */
+ 0x00, /* 8D DAI2 EQ1 */
+ 0x00, /* 8E DAI2 EQ2 */
+ 0x00, /* 8F DAI2 EQ2 */
+
+ 0x00, /* 90 DAI2 EQ2 */
+ 0x00, /* 91 DAI2 EQ2 */
+ 0x00, /* 92 DAI2 EQ2 */
+ 0x00, /* 93 DAI2 EQ2 */
+ 0x00, /* 94 DAI2 EQ2 */
+ 0x00, /* 95 DAI2 EQ2 */
+ 0x00, /* 96 DAI2 EQ2 */
+ 0x00, /* 97 DAI2 EQ2 */
+ 0x00, /* 98 DAI2 EQ3 */
+ 0x00, /* 99 DAI2 EQ3 */
+ 0x00, /* 9A DAI2 EQ3 */
+ 0x00, /* 9B DAI2 EQ3 */
+ 0x00, /* 9C DAI2 EQ3 */
+ 0x00, /* 9D DAI2 EQ3 */
+ 0x00, /* 9E DAI2 EQ3 */
+ 0x00, /* 9F DAI2 EQ3 */
+
+ 0x00, /* A0 DAI2 EQ3 */
+ 0x00, /* A1 DAI2 EQ3 */
+ 0x00, /* A2 DAI2 EQ4 */
+ 0x00, /* A3 DAI2 EQ4 */
+ 0x00, /* A4 DAI2 EQ4 */
+ 0x00, /* A5 DAI2 EQ4 */
+ 0x00, /* A6 DAI2 EQ4 */
+ 0x00, /* A7 DAI2 EQ4 */
+ 0x00, /* A8 DAI2 EQ4 */
+ 0x00, /* A9 DAI2 EQ4 */
+ 0x00, /* AA DAI2 EQ4 */
+ 0x00, /* AB DAI2 EQ4 */
+ 0x00, /* AC DAI2 EQ5 */
+ 0x00, /* AD DAI2 EQ5 */
+ 0x00, /* AE DAI2 EQ5 */
+ 0x00, /* AF DAI2 EQ5 */
+
+ 0x00, /* B0 DAI2 EQ5 */
+ 0x00, /* B1 DAI2 EQ5 */
+ 0x00, /* B2 DAI2 EQ5 */
+ 0x00, /* B3 DAI2 EQ5 */
+ 0x00, /* B4 DAI2 EQ5 */
+ 0x00, /* B5 DAI2 EQ5 */
+ 0x00, /* B6 DAI1 biquad */
+ 0x00, /* B7 DAI1 biquad */
+ 0x00, /* B8 DAI1 biquad */
+ 0x00, /* B9 DAI1 biquad */
+ 0x00, /* BA DAI1 biquad */
+ 0x00, /* BB DAI1 biquad */
+ 0x00, /* BC DAI1 biquad */
+ 0x00, /* BD DAI1 biquad */
+ 0x00, /* BE DAI1 biquad */
+ 0x00, /* BF DAI1 biquad */
+
+ 0x00, /* C0 DAI2 biquad */
+ 0x00, /* C1 DAI2 biquad */
+ 0x00, /* C2 DAI2 biquad */
+ 0x00, /* C3 DAI2 biquad */
+ 0x00, /* C4 DAI2 biquad */
+ 0x00, /* C5 DAI2 biquad */
+ 0x00, /* C6 DAI2 biquad */
+ 0x00, /* C7 DAI2 biquad */
+ 0x00, /* C8 DAI2 biquad */
+ 0x00, /* C9 DAI2 biquad */
+ 0x00, /* CA */
+ 0x00, /* CB */
+ 0x00, /* CC */
+ 0x00, /* CD */
+ 0x00, /* CE */
+ 0x00, /* CF */
+
+ 0x00, /* D0 */
+ 0x00, /* D1 */
+ 0x00, /* D2 */
+ 0x00, /* D3 */
+ 0x00, /* D4 */
+ 0x00, /* D5 */
+ 0x00, /* D6 */
+ 0x00, /* D7 */
+ 0x00, /* D8 */
+ 0x00, /* D9 */
+ 0x00, /* DA */
+ 0x70, /* DB */
+ 0x00, /* DC */
+ 0x00, /* DD */
+ 0x00, /* DE */
+ 0x00, /* DF */
+
+ 0x00, /* E0 */
+ 0x00, /* E1 */
+ 0x00, /* E2 */
+ 0x00, /* E3 */
+ 0x00, /* E4 */
+ 0x00, /* E5 */
+ 0x00, /* E6 */
+ 0x00, /* E7 */
+ 0x00, /* E8 */
+ 0x00, /* E9 */
+ 0x00, /* EA */
+ 0x00, /* EB */
+ 0x00, /* EC */
+ 0x00, /* ED */
+ 0x00, /* EE */
+ 0x00, /* EF */
+
+ 0x00, /* F0 */
+ 0x00, /* F1 */
+ 0x00, /* F2 */
+ 0x00, /* F3 */
+ 0x00, /* F4 */
+ 0x00, /* F5 */
+ 0x00, /* F6 */
+ 0x00, /* F7 */
+ 0x00, /* F8 */
+ 0x00, /* F9 */
+ 0x00, /* FA */
+ 0x00, /* FB */
+ 0x00, /* FC */
+ 0x00, /* FD */
+ 0x00, /* FE */
+ 0x00, /* FF */
+};
+
+static struct {
+ int readable;
+ int writable;
+ int vol;
+} max98088_access[M98088_REG_CNT] = {
+ { 0xFF, 0xFF, 1 }, /* 00 IRQ status */
+ { 0xFF, 0x00, 1 }, /* 01 MIC status */
+ { 0xFF, 0x00, 1 }, /* 02 jack status */
+ { 0x1F, 0x1F, 1 }, /* 03 battery voltage */
+ { 0xFF, 0xFF, 0 }, /* 04 */
+ { 0xFF, 0xFF, 0 }, /* 05 */
+ { 0xFF, 0xFF, 0 }, /* 06 */
+ { 0xFF, 0xFF, 0 }, /* 07 */
+ { 0xFF, 0xFF, 0 }, /* 08 */
+ { 0xFF, 0xFF, 0 }, /* 09 */
+ { 0xFF, 0xFF, 0 }, /* 0A */
+ { 0xFF, 0xFF, 0 }, /* 0B */
+ { 0xFF, 0xFF, 0 }, /* 0C */
+ { 0xFF, 0xFF, 0 }, /* 0D */
+ { 0xFF, 0xFF, 0 }, /* 0E */
+ { 0xFF, 0xFF, 0 }, /* 0F interrupt enable */
+
+ { 0xFF, 0xFF, 0 }, /* 10 master clock */
+ { 0xFF, 0xFF, 0 }, /* 11 DAI1 clock mode */
+ { 0xFF, 0xFF, 0 }, /* 12 DAI1 clock control */
+ { 0xFF, 0xFF, 0 }, /* 13 DAI1 clock control */
+ { 0xFF, 0xFF, 0 }, /* 14 DAI1 format */
+ { 0xFF, 0xFF, 0 }, /* 15 DAI1 clock */
+ { 0xFF, 0xFF, 0 }, /* 16 DAI1 config */
+ { 0xFF, 0xFF, 0 }, /* 17 DAI1 TDM */
+ { 0xFF, 0xFF, 0 }, /* 18 DAI1 filters */
+ { 0xFF, 0xFF, 0 }, /* 19 DAI2 clock mode */
+ { 0xFF, 0xFF, 0 }, /* 1A DAI2 clock control */
+ { 0xFF, 0xFF, 0 }, /* 1B DAI2 clock control */
+ { 0xFF, 0xFF, 0 }, /* 1C DAI2 format */
+ { 0xFF, 0xFF, 0 }, /* 1D DAI2 clock */
+ { 0xFF, 0xFF, 0 }, /* 1E DAI2 config */
+ { 0xFF, 0xFF, 0 }, /* 1F DAI2 TDM */
+
+ { 0xFF, 0xFF, 0 }, /* 20 DAI2 filters */
+ { 0xFF, 0xFF, 0 }, /* 21 data config */
+ { 0xFF, 0xFF, 0 }, /* 22 DAC mixer */
+ { 0xFF, 0xFF, 0 }, /* 23 left ADC mixer */
+ { 0xFF, 0xFF, 0 }, /* 24 right ADC mixer */
+ { 0xFF, 0xFF, 0 }, /* 25 left HP mixer */
+ { 0xFF, 0xFF, 0 }, /* 26 right HP mixer */
+ { 0xFF, 0xFF, 0 }, /* 27 HP control */
+ { 0xFF, 0xFF, 0 }, /* 28 left REC mixer */
+ { 0xFF, 0xFF, 0 }, /* 29 right REC mixer */
+ { 0xFF, 0xFF, 0 }, /* 2A REC control */
+ { 0xFF, 0xFF, 0 }, /* 2B left SPK mixer */
+ { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */
+ { 0xFF, 0xFF, 0 }, /* 2D SPK control */
+ { 0xFF, 0xFF, 0 }, /* 2E sidetone */
+ { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */
+
+ { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */
+ { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */
+ { 0xFF, 0xFF, 0 }, /* 32 DAI2 playbakc level */
+ { 0xFF, 0xFF, 0 }, /* 33 left ADC level */
+ { 0xFF, 0xFF, 0 }, /* 34 right ADC level */
+ { 0xFF, 0xFF, 0 }, /* 35 MIC1 level */
+ { 0xFF, 0xFF, 0 }, /* 36 MIC2 level */
+ { 0xFF, 0xFF, 0 }, /* 37 INA level */
+ { 0xFF, 0xFF, 0 }, /* 38 INB level */
+ { 0xFF, 0xFF, 0 }, /* 39 left HP volume */
+ { 0xFF, 0xFF, 0 }, /* 3A right HP volume */
+ { 0xFF, 0xFF, 0 }, /* 3B left REC volume */
+ { 0xFF, 0xFF, 0 }, /* 3C right REC volume */
+ { 0xFF, 0xFF, 0 }, /* 3D left SPK volume */
+ { 0xFF, 0xFF, 0 }, /* 3E right SPK volume */
+ { 0xFF, 0xFF, 0 }, /* 3F MIC config */
+
+ { 0xFF, 0xFF, 0 }, /* 40 MIC threshold */
+ { 0xFF, 0xFF, 0 }, /* 41 excursion limiter filter */
+ { 0xFF, 0xFF, 0 }, /* 42 excursion limiter threshold */
+ { 0xFF, 0xFF, 0 }, /* 43 ALC */
+ { 0xFF, 0xFF, 0 }, /* 44 power limiter threshold */
+ { 0xFF, 0xFF, 0 }, /* 45 power limiter config */
+ { 0xFF, 0xFF, 0 }, /* 46 distortion limiter config */
+ { 0xFF, 0xFF, 0 }, /* 47 audio input */
+ { 0xFF, 0xFF, 0 }, /* 48 microphone */
+ { 0xFF, 0xFF, 0 }, /* 49 level control */
+ { 0xFF, 0xFF, 0 }, /* 4A bypass switches */
+ { 0xFF, 0xFF, 0 }, /* 4B jack detect */
+ { 0xFF, 0xFF, 0 }, /* 4C input enable */
+ { 0xFF, 0xFF, 0 }, /* 4D output enable */
+ { 0xFF, 0xFF, 0 }, /* 4E bias control */
+ { 0xFF, 0xFF, 0 }, /* 4F DAC power */
+
+ { 0xFF, 0xFF, 0 }, /* 50 DAC power */
+ { 0xFF, 0xFF, 0 }, /* 51 system */
+ { 0xFF, 0xFF, 0 }, /* 52 DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 53 DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 54 DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 55 DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 56 DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 57 DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 58 DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 59 DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 5A DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 5B DAI1 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 5C DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 5D DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 5E DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 5F DAI1 EQ2 */
+
+ { 0xFF, 0xFF, 0 }, /* 60 DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 61 DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 62 DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 63 DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 64 DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 65 DAI1 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 66 DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 67 DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 68 DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 69 DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 6A DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 6B DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 6C DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 6D DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 6E DAI1 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 6F DAI1 EQ3 */
+
+ { 0xFF, 0xFF, 0 }, /* 70 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 71 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 72 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 73 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 74 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 75 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 76 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 77 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 78 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 79 DAI1 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* 7A DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 7B DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 7C DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 7D DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 7E DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 7F DAI1 EQ5 */
+
+ { 0xFF, 0xFF, 0 }, /* 80 DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 81 DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 82 DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 83 DAI1 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* 84 DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 85 DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 86 DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 87 DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 88 DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 89 DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 8A DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 8B DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 8C DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 8D DAI2 EQ1 */
+ { 0xFF, 0xFF, 0 }, /* 8E DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 8F DAI2 EQ2 */
+
+ { 0xFF, 0xFF, 0 }, /* 90 DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 91 DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 92 DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 93 DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 94 DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 95 DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 96 DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 97 DAI2 EQ2 */
+ { 0xFF, 0xFF, 0 }, /* 98 DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 99 DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 9A DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 9B DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 9C DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 9D DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 9E DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* 9F DAI2 EQ3 */
+
+ { 0xFF, 0xFF, 0 }, /* A0 DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* A1 DAI2 EQ3 */
+ { 0xFF, 0xFF, 0 }, /* A2 DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* A3 DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* A4 DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* A5 DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* A6 DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* A7 DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* A8 DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* A9 DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* AA DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* AB DAI2 EQ4 */
+ { 0xFF, 0xFF, 0 }, /* AC DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* AD DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* AE DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* AF DAI2 EQ5 */
+
+ { 0xFF, 0xFF, 0 }, /* B0 DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* B1 DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* B2 DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* B3 DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* B4 DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* B5 DAI2 EQ5 */
+ { 0xFF, 0xFF, 0 }, /* B6 DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* B7 DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* B8 DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* B9 DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* BA DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* BB DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* BC DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* BD DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* BE DAI1 biquad */
+ { 0xFF, 0xFF, 0 }, /* BF DAI1 biquad */
+
+ { 0xFF, 0xFF, 0 }, /* C0 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C1 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C2 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C3 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C4 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C5 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C6 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C7 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C8 DAI2 biquad */
+ { 0xFF, 0xFF, 0 }, /* C9 DAI2 biquad */
+ { 0x00, 0x00, 0 }, /* CA */
+ { 0x00, 0x00, 0 }, /* CB */
+ { 0x00, 0x00, 0 }, /* CC */
+ { 0x00, 0x00, 0 }, /* CD */
+ { 0x00, 0x00, 0 }, /* CE */
+ { 0x00, 0x00, 0 }, /* CF */
+
+ { 0x00, 0x00, 0 }, /* D0 */
+ { 0x00, 0x00, 0 }, /* D1 */
+ { 0x00, 0x00, 0 }, /* D2 */
+ { 0x00, 0x00, 0 }, /* D3 */
+ { 0x00, 0x00, 0 }, /* D4 */
+ { 0x00, 0x00, 0 }, /* D5 */
+ { 0x00, 0x00, 0 }, /* D6 */
+ { 0x00, 0x00, 0 }, /* D7 */
+ { 0x00, 0x00, 0 }, /* D8 */
+ { 0x00, 0x00, 0 }, /* D9 */
+ { 0x00, 0x00, 0 }, /* DA */
+ { 0x00, 0x00, 0 }, /* DB */
+ { 0x00, 0x00, 0 }, /* DC */
+ { 0x00, 0x00, 0 }, /* DD */
+ { 0x00, 0x00, 0 }, /* DE */
+ { 0x00, 0x00, 0 }, /* DF */
+
+ { 0x00, 0x00, 0 }, /* E0 */
+ { 0x00, 0x00, 0 }, /* E1 */
+ { 0x00, 0x00, 0 }, /* E2 */
+ { 0x00, 0x00, 0 }, /* E3 */
+ { 0x00, 0x00, 0 }, /* E4 */
+ { 0x00, 0x00, 0 }, /* E5 */
+ { 0x00, 0x00, 0 }, /* E6 */
+ { 0x00, 0x00, 0 }, /* E7 */
+ { 0x00, 0x00, 0 }, /* E8 */
+ { 0x00, 0x00, 0 }, /* E9 */
+ { 0x00, 0x00, 0 }, /* EA */
+ { 0x00, 0x00, 0 }, /* EB */
+ { 0x00, 0x00, 0 }, /* EC */
+ { 0x00, 0x00, 0 }, /* ED */
+ { 0x00, 0x00, 0 }, /* EE */
+ { 0x00, 0x00, 0 }, /* EF */
+
+ { 0x00, 0x00, 0 }, /* F0 */
+ { 0x00, 0x00, 0 }, /* F1 */
+ { 0x00, 0x00, 0 }, /* F2 */
+ { 0x00, 0x00, 0 }, /* F3 */
+ { 0x00, 0x00, 0 }, /* F4 */
+ { 0x00, 0x00, 0 }, /* F5 */
+ { 0x00, 0x00, 0 }, /* F6 */
+ { 0x00, 0x00, 0 }, /* F7 */
+ { 0x00, 0x00, 0 }, /* F8 */
+ { 0x00, 0x00, 0 }, /* F9 */
+ { 0x00, 0x00, 0 }, /* FA */
+ { 0x00, 0x00, 0 }, /* FB */
+ { 0x00, 0x00, 0 }, /* FC */
+ { 0x00, 0x00, 0 }, /* FD */
+ { 0x00, 0x00, 0 }, /* FE */
+ { 0xFF, 0x00, 1 }, /* FF */
+};
+
+static int max98088_volatile_register(unsigned int reg)
+{
+ return max98088_access[reg].vol;
+}
+
+
+/*
+ * Load equalizer DSP coefficient configurations registers
+ */
+static void m98088_eq_band(struct snd_soc_codec *codec, unsigned int dai,
+ unsigned int band, u16 *coefs)
+{
+ unsigned int eq_reg;
+ unsigned int i;
+
+ BUG_ON(band > 4);
+ BUG_ON(dai > 1);
+
+ /* Load the base register address */
+ eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE;
+
+ /* Add the band address offset, note adjustment for word address */
+ eq_reg += band * (M98088_COEFS_PER_BAND << 1);
+
+ /* Step through the registers and coefs */
+ for (i = 0; i < M98088_COEFS_PER_BAND; i++) {
+ snd_soc_write(codec, eq_reg++, M98088_BYTE1(coefs[i]));
+ snd_soc_write(codec, eq_reg++, M98088_BYTE0(coefs[i]));
+ }
+}
+
+/*
+ * Excursion limiter modes
+ */
+static const char *max98088_exmode_texts[] = {
+ "Off", "100Hz", "400Hz", "600Hz", "800Hz", "1000Hz", "200-400Hz",
+ "400-600Hz", "400-800Hz",
+};
+
+static const unsigned int max98088_exmode_values[] = {
+ 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32
+};
+
+static const struct soc_enum max98088_exmode_enum =
+ SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127,
+ ARRAY_SIZE(max98088_exmode_texts),
+ max98088_exmode_texts,
+ max98088_exmode_values);
+static const struct snd_kcontrol_new max98088_exmode_controls =
+ SOC_DAPM_VALUE_ENUM("Route", max98088_exmode_enum);
+
+static const char *max98088_ex_thresh[] = { /* volts PP */
+ "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"};
+static const struct soc_enum max98088_ex_thresh_enum[] = {
+ SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8,
+ max98088_ex_thresh),
+};
+
+static const char *max98088_fltr_mode[] = {"Voice", "Music" };
+static const struct soc_enum max98088_filter_mode_enum[] = {
+ SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode),
+};
+
+static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" };
+
+static const struct soc_enum max98088_extmic_enum =
+ SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text);
+
+static const struct snd_kcontrol_new max98088_extmic_mux =
+ SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum);
+
+static const char *max98088_dai1_fltr[] = {
+ "Off", "fc=258/fs=16k", "fc=500/fs=16k",
+ "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"};
+static const struct soc_enum max98088_dai1_dac_filter_enum[] = {
+ SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr),
+};
+static const struct soc_enum max98088_dai1_adc_filter_enum[] = {
+ SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr),
+};
+
+static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ unsigned int sel = ucontrol->value.integer.value[0];
+
+ max98088->mic1pre = sel;
+ snd_soc_update_bits(codec, M98088_REG_35_LVL_MIC1, M98088_MICPRE_MASK,
+ (1+sel)<<M98088_MICPRE_SHIFT);
+
+ return 0;
+}
+
+static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = max98088->mic1pre;
+ return 0;
+}
+
+static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ unsigned int sel = ucontrol->value.integer.value[0];
+
+ max98088->mic2pre = sel;
+ snd_soc_update_bits(codec, M98088_REG_36_LVL_MIC2, M98088_MICPRE_MASK,
+ (1+sel)<<M98088_MICPRE_SHIFT);
+
+ return 0;
+}
+
+static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = max98088->mic2pre;
+ return 0;
+}
+
+static const unsigned int max98088_micboost_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
+};
+
+static const struct snd_kcontrol_new max98088_snd_controls[] = {
+
+ SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L,
+ M98088_REG_3A_LVL_HP_R, 0, 31, 0),
+ SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L,
+ M98088_REG_3E_LVL_SPK_R, 0, 31, 0),
+ SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L,
+ M98088_REG_3C_LVL_REC_R, 0, 31, 0),
+
+ SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L,
+ M98088_REG_3A_LVL_HP_R, 7, 1, 1),
+ SOC_DOUBLE_R("Speaker Switch", M98088_REG_3D_LVL_SPK_L,
+ M98088_REG_3E_LVL_SPK_R, 7, 1, 1),
+ SOC_DOUBLE_R("Receiver Switch", M98088_REG_3B_LVL_REC_L,
+ M98088_REG_3C_LVL_REC_R, 7, 1, 1),
+
+ SOC_SINGLE("MIC1 Volume", M98088_REG_35_LVL_MIC1, 0, 31, 1),
+ SOC_SINGLE("MIC2 Volume", M98088_REG_36_LVL_MIC2, 0, 31, 1),
+
+ SOC_SINGLE_EXT_TLV("MIC1 Boost Volume",
+ M98088_REG_35_LVL_MIC1, 5, 2, 0,
+ max98088_mic1pre_get, max98088_mic1pre_set,
+ max98088_micboost_tlv),
+ SOC_SINGLE_EXT_TLV("MIC2 Boost Volume",
+ M98088_REG_36_LVL_MIC2, 5, 2, 0,
+ max98088_mic2pre_get, max98088_mic2pre_set,
+ max98088_micboost_tlv),
+
+ SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1),
+ SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1),
+
+ SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0),
+ SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0),
+
+ SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0),
+ SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0),
+
+ SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0),
+ SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0),
+
+ SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum),
+
+ SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum),
+ SOC_ENUM("DAI1 DAC Filter", max98088_dai1_dac_filter_enum),
+ SOC_ENUM("DAI1 ADC Filter", max98088_dai1_adc_filter_enum),
+ SOC_SINGLE("DAI2 DC Block Switch", M98088_REG_20_DAI2_FILTERS,
+ 0, 1, 0),
+
+ SOC_SINGLE("ALC Switch", M98088_REG_43_SPKALC_COMP, 7, 1, 0),
+ SOC_SINGLE("ALC Threshold", M98088_REG_43_SPKALC_COMP, 0, 7, 0),
+ SOC_SINGLE("ALC Multiband", M98088_REG_43_SPKALC_COMP, 3, 1, 0),
+ SOC_SINGLE("ALC Release Time", M98088_REG_43_SPKALC_COMP, 4, 7, 0),
+
+ SOC_SINGLE("PWR Limiter Threshold", M98088_REG_44_PWRLMT_CFG,
+ 4, 15, 0),
+ SOC_SINGLE("PWR Limiter Weight", M98088_REG_44_PWRLMT_CFG, 0, 7, 0),
+ SOC_SINGLE("PWR Limiter Time1", M98088_REG_45_PWRLMT_TIME, 0, 15, 0),
+ SOC_SINGLE("PWR Limiter Time2", M98088_REG_45_PWRLMT_TIME, 4, 15, 0),
+
+ SOC_SINGLE("THD Limiter Threshold", M98088_REG_46_THDLMT_CFG, 4, 15, 0),
+ SOC_SINGLE("THD Limiter Time", M98088_REG_46_THDLMT_CFG, 0, 7, 0),
+};
+
+/* Left speaker mixer switch */
+static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0),
+ SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0),
+ SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0),
+ SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 2, 1, 0),
+ SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 3, 1, 0),
+ SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 4, 1, 0),
+};
+
+/* Right speaker mixer switch */
+static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0),
+ SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0),
+ SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0),
+ SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 2, 1, 0),
+ SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 3, 1, 0),
+ SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 4, 1, 0),
+};
+
+/* Left headphone mixer switch */
+static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0),
+ SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0),
+ SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0),
+ SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_25_MIX_HP_LEFT, 2, 1, 0),
+ SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_25_MIX_HP_LEFT, 3, 1, 0),
+ SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_25_MIX_HP_LEFT, 4, 1, 0),
+};
+
+/* Right headphone mixer switch */
+static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0),
+ SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0),
+ SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0),
+ SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_26_MIX_HP_RIGHT, 2, 1, 0),
+ SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_26_MIX_HP_RIGHT, 3, 1, 0),
+ SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_26_MIX_HP_RIGHT, 4, 1, 0),
+};
+
+/* Left earpiece/receiver mixer switch */
+static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
+ SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0),
+ SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0),
+ SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0),
+ SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_28_MIX_REC_LEFT, 2, 1, 0),
+ SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_28_MIX_REC_LEFT, 3, 1, 0),
+ SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_28_MIX_REC_LEFT, 4, 1, 0),
+};
+
+/* Right earpiece/receiver mixer switch */
+static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
+ SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0),
+ SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0),
+ SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0),
+ SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_29_MIX_REC_RIGHT, 2, 1, 0),
+ SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_29_MIX_REC_RIGHT, 3, 1, 0),
+ SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_29_MIX_REC_RIGHT, 4, 1, 0),
+};
+
+/* Left ADC mixer switch */
+static const struct snd_kcontrol_new max98088_left_ADC_mixer_controls[] = {
+ SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_23_MIX_ADC_LEFT, 7, 1, 0),
+ SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_23_MIX_ADC_LEFT, 6, 1, 0),
+ SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_23_MIX_ADC_LEFT, 3, 1, 0),
+ SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_23_MIX_ADC_LEFT, 2, 1, 0),
+ SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_23_MIX_ADC_LEFT, 1, 1, 0),
+ SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_23_MIX_ADC_LEFT, 0, 1, 0),
+};
+
+/* Right ADC mixer switch */
+static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = {
+ SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 7, 1, 0),
+ SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 6, 1, 0),
+ SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 3, 1, 0),
+ SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 2, 1, 0),
+ SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 1, 1, 0),
+ SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 0, 1, 0),
+};
+
+static int max98088_mic_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (w->reg == M98088_REG_35_LVL_MIC1) {
+ snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK,
+ (1+max98088->mic1pre)<<M98088_MICPRE_SHIFT);
+ } else {
+ snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK,
+ (1+max98088->mic2pre)<<M98088_MICPRE_SHIFT);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * The line inputs are 2-channel stereo inputs with the left
+ * and right channels sharing a common PGA power control signal.
+ */
+static int max98088_line_pga(struct snd_soc_dapm_widget *w,
+ int event, int line, u8 channel)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ u8 *state;
+
+ BUG_ON(!((channel == 1) || (channel == 2)));
+
+ switch (line) {
+ case LINE_INA:
+ state = &max98088->ina_state;
+ break;
+ case LINE_INB:
+ state = &max98088->inb_state;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ *state |= channel;
+ snd_soc_update_bits(codec, w->reg,
+ (1 << w->shift), (1 << w->shift));
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ *state &= ~channel;
+ if (*state == 0) {
+ snd_soc_update_bits(codec, w->reg,
+ (1 << w->shift), 0);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int max98088_pga_ina1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ return max98088_line_pga(w, event, LINE_INA, 1);
+}
+
+static int max98088_pga_ina2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ return max98088_line_pga(w, event, LINE_INA, 2);
+}
+
+static int max98088_pga_inb1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ return max98088_line_pga(w, event, LINE_INB, 1);
+}
+
+static int max98088_pga_inb2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ return max98088_line_pga(w, event, LINE_INB, 2);
+}
+
+static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = {
+
+ SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0),
+ SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0),
+
+ SND_SOC_DAPM_DAC("DACL1", "HiFi Playback",
+ M98088_REG_4D_PWR_EN_OUT, 1, 0),
+ SND_SOC_DAPM_DAC("DACR1", "HiFi Playback",
+ M98088_REG_4D_PWR_EN_OUT, 0, 0),
+ SND_SOC_DAPM_DAC("DACL2", "Aux Playback",
+ M98088_REG_4D_PWR_EN_OUT, 1, 0),
+ SND_SOC_DAPM_DAC("DACR2", "Aux Playback",
+ M98088_REG_4D_PWR_EN_OUT, 0, 0),
+
+ SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HP Right Out", M98088_REG_4D_PWR_EN_OUT,
+ 6, 0, NULL, 0),
+
+ SND_SOC_DAPM_PGA("SPK Left Out", M98088_REG_4D_PWR_EN_OUT,
+ 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SPK Right Out", M98088_REG_4D_PWR_EN_OUT,
+ 4, 0, NULL, 0),
+
+ SND_SOC_DAPM_PGA("REC Left Out", M98088_REG_4D_PWR_EN_OUT,
+ 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("REC Right Out", M98088_REG_4D_PWR_EN_OUT,
+ 2, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0,
+ &max98088_extmic_mux),
+
+ SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
+ &max98088_left_hp_mixer_controls[0],
+ ARRAY_SIZE(max98088_left_hp_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0,
+ &max98088_right_hp_mixer_controls[0],
+ ARRAY_SIZE(max98088_right_hp_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left SPK Mixer", SND_SOC_NOPM, 0, 0,
+ &max98088_left_speaker_mixer_controls[0],
+ ARRAY_SIZE(max98088_left_speaker_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Right SPK Mixer", SND_SOC_NOPM, 0, 0,
+ &max98088_right_speaker_mixer_controls[0],
+ ARRAY_SIZE(max98088_right_speaker_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left REC Mixer", SND_SOC_NOPM, 0, 0,
+ &max98088_left_rec_mixer_controls[0],
+ ARRAY_SIZE(max98088_left_rec_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Right REC Mixer", SND_SOC_NOPM, 0, 0,
+ &max98088_right_rec_mixer_controls[0],
+ ARRAY_SIZE(max98088_right_rec_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
+ &max98088_left_ADC_mixer_controls[0],
+ ARRAY_SIZE(max98088_left_ADC_mixer_controls)),
+
+ SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
+ &max98088_right_ADC_mixer_controls[0],
+ ARRAY_SIZE(max98088_right_ADC_mixer_controls)),
+
+ SND_SOC_DAPM_PGA_E("MIC1 Input", M98088_REG_35_LVL_MIC1,
+ 5, 0, NULL, 0, max98088_mic_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("MIC2 Input", M98088_REG_36_LVL_MIC2,
+ 5, 0, NULL, 0, max98088_mic_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("INA1 Input", M98088_REG_4C_PWR_EN_IN,
+ 7, 0, NULL, 0, max98088_pga_ina1_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("INA2 Input", M98088_REG_4C_PWR_EN_IN,
+ 7, 0, NULL, 0, max98088_pga_ina2_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("INB1 Input", M98088_REG_4C_PWR_EN_IN,
+ 6, 0, NULL, 0, max98088_pga_inb1_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("INB2 Input", M98088_REG_4C_PWR_EN_IN,
+ 6, 0, NULL, 0, max98088_pga_inb2_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0),
+
+ SND_SOC_DAPM_MUX("EX Limiter Mode", SND_SOC_NOPM, 0, 0,
+ &max98088_exmode_controls),
+
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+ SND_SOC_DAPM_OUTPUT("SPKL"),
+ SND_SOC_DAPM_OUTPUT("SPKR"),
+ SND_SOC_DAPM_OUTPUT("RECL"),
+ SND_SOC_DAPM_OUTPUT("RECR"),
+
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("MIC2"),
+ SND_SOC_DAPM_INPUT("INA1"),
+ SND_SOC_DAPM_INPUT("INA2"),
+ SND_SOC_DAPM_INPUT("INB1"),
+ SND_SOC_DAPM_INPUT("INB2"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Left headphone output mixer */
+ {"Left HP Mixer", "Left DAC1 Switch", "DACL1"},
+ {"Left HP Mixer", "Left DAC2 Switch", "DACL2"},
+ {"Left HP Mixer", "Right DAC1 Switch", "DACR1"},
+ {"Left HP Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"},
+ {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"},
+ {"Left HP Mixer", "INA1 Switch", "INA1 Input"},
+ {"Left HP Mixer", "INA2 Switch", "INA2 Input"},
+ {"Left HP Mixer", "INB1 Switch", "INB1 Input"},
+ {"Left HP Mixer", "INB2 Switch", "INB2 Input"},
+
+ /* Right headphone output mixer */
+ {"Right HP Mixer", "Left DAC1 Switch", "DACL1"},
+ {"Right HP Mixer", "Left DAC2 Switch", "DACL2" },
+ {"Right HP Mixer", "Right DAC1 Switch", "DACR1"},
+ {"Right HP Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"},
+ {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"},
+ {"Right HP Mixer", "INA1 Switch", "INA1 Input"},
+ {"Right HP Mixer", "INA2 Switch", "INA2 Input"},
+ {"Right HP Mixer", "INB1 Switch", "INB1 Input"},
+ {"Right HP Mixer", "INB2 Switch", "INB2 Input"},
+
+ /* Left speaker output mixer */
+ {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"},
+ {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"},
+ {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"},
+ {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"},
+ {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"},
+ {"Left SPK Mixer", "INA1 Switch", "INA1 Input"},
+ {"Left SPK Mixer", "INA2 Switch", "INA2 Input"},
+ {"Left SPK Mixer", "INB1 Switch", "INB1 Input"},
+ {"Left SPK Mixer", "INB2 Switch", "INB2 Input"},
+
+ /* Right speaker output mixer */
+ {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"},
+ {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"},
+ {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"},
+ {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"},
+ {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"},
+ {"Right SPK Mixer", "INA1 Switch", "INA1 Input"},
+ {"Right SPK Mixer", "INA2 Switch", "INA2 Input"},
+ {"Right SPK Mixer", "INB1 Switch", "INB1 Input"},
+ {"Right SPK Mixer", "INB2 Switch", "INB2 Input"},
+
+ /* Earpiece/Receiver output mixer */
+ {"Left REC Mixer", "Left DAC1 Switch", "DACL1"},
+ {"Left REC Mixer", "Left DAC2 Switch", "DACL2"},
+ {"Left REC Mixer", "Right DAC1 Switch", "DACR1"},
+ {"Left REC Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"},
+ {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"},
+ {"Left REC Mixer", "INA1 Switch", "INA1 Input"},
+ {"Left REC Mixer", "INA2 Switch", "INA2 Input"},
+ {"Left REC Mixer", "INB1 Switch", "INB1 Input"},
+ {"Left REC Mixer", "INB2 Switch", "INB2 Input"},
+
+ /* Earpiece/Receiver output mixer */
+ {"Right REC Mixer", "Left DAC1 Switch", "DACL1"},
+ {"Right REC Mixer", "Left DAC2 Switch", "DACL2"},
+ {"Right REC Mixer", "Right DAC1 Switch", "DACR1"},
+ {"Right REC Mixer", "Right DAC2 Switch", "DACR2"},
+ {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"},
+ {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"},
+ {"Right REC Mixer", "INA1 Switch", "INA1 Input"},
+ {"Right REC Mixer", "INA2 Switch", "INA2 Input"},
+ {"Right REC Mixer", "INB1 Switch", "INB1 Input"},
+ {"Right REC Mixer", "INB2 Switch", "INB2 Input"},
+
+ {"HP Left Out", NULL, "Left HP Mixer"},
+ {"HP Right Out", NULL, "Right HP Mixer"},
+ {"SPK Left Out", NULL, "Left SPK Mixer"},
+ {"SPK Right Out", NULL, "Right SPK Mixer"},
+ {"REC Left Out", NULL, "Left REC Mixer"},
+ {"REC Right Out", NULL, "Right REC Mixer"},
+
+ {"HPL", NULL, "HP Left Out"},
+ {"HPR", NULL, "HP Right Out"},
+ {"SPKL", NULL, "SPK Left Out"},
+ {"SPKR", NULL, "SPK Right Out"},
+ {"RECL", NULL, "REC Left Out"},
+ {"RECR", NULL, "REC Right Out"},
+
+ /* Left ADC input mixer */
+ {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"},
+ {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"},
+ {"Left ADC Mixer", "INA1 Switch", "INA1 Input"},
+ {"Left ADC Mixer", "INA2 Switch", "INA2 Input"},
+ {"Left ADC Mixer", "INB1 Switch", "INB1 Input"},
+ {"Left ADC Mixer", "INB2 Switch", "INB2 Input"},
+
+ /* Right ADC input mixer */
+ {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"},
+ {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"},
+ {"Right ADC Mixer", "INA1 Switch", "INA1 Input"},
+ {"Right ADC Mixer", "INA2 Switch", "INA2 Input"},
+ {"Right ADC Mixer", "INB1 Switch", "INB1 Input"},
+ {"Right ADC Mixer", "INB2 Switch", "INB2 Input"},
+
+ /* Inputs */
+ {"ADCL", NULL, "Left ADC Mixer"},
+ {"ADCR", NULL, "Right ADC Mixer"},
+ {"INA1 Input", NULL, "INA1"},
+ {"INA2 Input", NULL, "INA2"},
+ {"INB1 Input", NULL, "INB1"},
+ {"INB2 Input", NULL, "INB2"},
+ {"MIC1 Input", NULL, "MIC1"},
+ {"MIC2 Input", NULL, "MIC2"},
+};
+
+static int max98088_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, max98088_dapm_widgets,
+ ARRAY_SIZE(max98088_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+ snd_soc_add_controls(codec, max98088_snd_controls,
+ ARRAY_SIZE(max98088_snd_controls));
+
+ snd_soc_dapm_new_widgets(codec);
+ return 0;
+}
+
+/* codec mclk clock divider coefficients */
+static const struct {
+ u32 rate;
+ u8 sr;
+} rate_table[] = {
+ {8000, 0x10},
+ {11025, 0x20},
+ {16000, 0x30},
+ {22050, 0x40},
+ {24000, 0x50},
+ {32000, 0x60},
+ {44100, 0x70},
+ {48000, 0x80},
+ {88200, 0x90},
+ {96000, 0xA0},
+};
+
+static inline int rate_value(int rate, u8 *value)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
+ if (rate_table[i].rate >= rate) {
+ *value = rate_table[i].sr;
+ return 0;
+ }
+ }
+ *value = rate_table[0].sr;
+ return -EINVAL;
+}
+
+static int max98088_dai1_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_cdata *cdata;
+ unsigned long long ni;
+ unsigned int rate;
+ u8 regval;
+
+ cdata = &max98088->dai[0];
+
+ rate = params_rate(params);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
+ M98088_DAI_WS, 0);
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
+ M98088_DAI_WS, M98088_DAI_WS);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0);
+
+ if (rate_value(rate, &regval))
+ return -EINVAL;
+
+ snd_soc_update_bits(codec, M98088_REG_11_DAI1_CLKMODE,
+ M98088_CLKMODE_MASK, regval);
+ cdata->rate = rate;
+
+ /* Configure NI when operating as master */
+ if (snd_soc_read(codec, M98088_REG_14_DAI1_FORMAT)
+ & M98088_DAI_MAS) {
+ if (max98088->sysclk == 0) {
+ dev_err(codec->dev, "Invalid system clock frequency\n");
+ return -EINVAL;
+ }
+ ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
+ * (unsigned long long int)rate;
+ do_div(ni, (unsigned long long int)max98088->sysclk);
+ snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI,
+ (ni >> 8) & 0x7F);
+ snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO,
+ ni & 0xFF);
+ }
+
+ /* Update sample rate mode */
+ if (rate < 50000)
+ snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS,
+ M98088_DAI_DHF, 0);
+ else
+ snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS,
+ M98088_DAI_DHF, M98088_DAI_DHF);
+
+ snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN,
+ M98088_SHDNRUN);
+
+ return 0;
+}
+
+static int max98088_dai2_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_cdata *cdata;
+ unsigned long long ni;
+ unsigned int rate;
+ u8 regval;
+
+ cdata = &max98088->dai[1];
+
+ rate = params_rate(params);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
+ M98088_DAI_WS, 0);
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
+ M98088_DAI_WS, M98088_DAI_WS);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0);
+
+ if (rate_value(rate, &regval))
+ return -EINVAL;
+
+ snd_soc_update_bits(codec, M98088_REG_19_DAI2_CLKMODE,
+ M98088_CLKMODE_MASK, regval);
+ cdata->rate = rate;
+
+ /* Configure NI when operating as master */
+ if (snd_soc_read(codec, M98088_REG_1C_DAI2_FORMAT)
+ & M98088_DAI_MAS) {
+ if (max98088->sysclk == 0) {
+ dev_err(codec->dev, "Invalid system clock frequency\n");
+ return -EINVAL;
+ }
+ ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
+ * (unsigned long long int)rate;
+ do_div(ni, (unsigned long long int)max98088->sysclk);
+ snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI,
+ (ni >> 8) & 0x7F);
+ snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO,
+ ni & 0xFF);
+ }
+
+ /* Update sample rate mode */
+ if (rate < 50000)
+ snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS,
+ M98088_DAI_DHF, 0);
+ else
+ snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS,
+ M98088_DAI_DHF, M98088_DAI_DHF);
+
+ snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN,
+ M98088_SHDNRUN);
+
+ return 0;
+}
+
+static int max98088_dai_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+ /* Requested clock frequency is already setup */
+ if (freq == max98088->sysclk)
+ return 0;
+
+ max98088->sysclk = freq; /* remember current sysclk */
+
+ /* Setup clocks for slave mode, and using the PLL
+ * PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
+ * 0x02 (when master clk is 20MHz to 30MHz)..
+ */
+ if ((freq >= 10000000) && (freq < 20000000)) {
+ snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x10);
+ } else if ((freq >= 20000000) && (freq < 30000000)) {
+ snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x20);
+ } else {
+ dev_err(codec->dev, "Invalid master clock frequency\n");
+ return -EINVAL;
+ }
+
+ if (snd_soc_read(codec, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) {
+ snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS,
+ M98088_SHDNRUN, 0);
+ snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS,
+ M98088_SHDNRUN, M98088_SHDNRUN);
+ }
+
+ dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq);
+
+ max98088->sysclk = freq;
+ return 0;
+}
+
+static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_cdata *cdata;
+ u8 reg15val;
+ u8 reg14val = 0;
+
+ cdata = &max98088->dai[0];
+
+ if (fmt != cdata->fmt) {
+ cdata->fmt = fmt;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* Slave mode PLL */
+ snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI,
+ 0x80);
+ snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO,
+ 0x00);
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* Set to master mode */
+ reg14val |= M98088_DAI_MAS;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ case SND_SOC_DAIFMT_CBM_CFS:
+ default:
+ dev_err(codec->dev, "Clock mode unsupported");
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ reg14val |= M98088_DAI_DLY;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ reg14val |= M98088_DAI_WCI;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ reg14val |= M98088_DAI_BCI;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ reg14val |= M98088_DAI_BCI|M98088_DAI_WCI;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
+ M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI |
+ M98088_DAI_WCI, reg14val);
+
+ reg15val = M98088_DAI_BSEL64;
+ if (max98088->digmic)
+ reg15val |= M98088_DAI_OSR64;
+ snd_soc_write(codec, M98088_REG_15_DAI1_CLOCK, reg15val);
+ }
+
+ return 0;
+}
+
+static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_cdata *cdata;
+ u8 reg1Cval = 0;
+
+ cdata = &max98088->dai[1];
+
+ if (fmt != cdata->fmt) {
+ cdata->fmt = fmt;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* Slave mode PLL */
+ snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI,
+ 0x80);
+ snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO,
+ 0x00);
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* Set to master mode */
+ reg1Cval |= M98088_DAI_MAS;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ case SND_SOC_DAIFMT_CBM_CFS:
+ default:
+ dev_err(codec->dev, "Clock mode unsupported");
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ reg1Cval |= M98088_DAI_DLY;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ reg1Cval |= M98088_DAI_WCI;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ reg1Cval |= M98088_DAI_BCI;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
+ M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI |
+ M98088_DAI_WCI, reg1Cval);
+
+ snd_soc_write(codec, M98088_REG_1D_DAI2_CLOCK,
+ M98088_DAI_BSEL64);
+ }
+
+ return 0;
+}
+
+static void max98088_sync_cache(struct snd_soc_codec *codec)
+{
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ if (!codec->cache_sync)
+ return;
+
+ codec->cache_only = 0;
+
+ /* write back cached values if they're writeable and
+ * different from the hardware default.
+ */
+ for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) {
+ if (!max98088_access[i].writable)
+ continue;
+
+ if (max98088->reg_cache[i] == max98088_reg[i])
+ continue;
+
+ snd_soc_write(codec, i, max98088->reg_cache[i]);
+ }
+
+ codec->cache_sync = 0;
+}
+
+static int max98088_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF)
+ max98088_sync_cache(codec);
+
+ snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
+ M98088_MBEN, M98088_MBEN);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
+ M98088_MBEN, 0);
+ codec->cache_sync = 1;
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+#define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
+#define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops max98088_dai1_ops = {
+ .set_sysclk = max98088_dai_set_sysclk,
+ .set_fmt = max98088_dai1_set_fmt,
+ .hw_params = max98088_dai1_hw_params,
+};
+
+static struct snd_soc_dai_ops max98088_dai2_ops = {
+ .set_sysclk = max98088_dai_set_sysclk,
+ .set_fmt = max98088_dai2_set_fmt,
+ .hw_params = max98088_dai2_hw_params,
+};
+
+static struct snd_soc_dai_driver max98088_dai[] = {
+{
+ .name = "HiFi",
+ .playback = {
+ .stream_name = "HiFi Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98088_RATES,
+ .formats = MAX98088_FORMATS,
+ },
+ .capture = {
+ .stream_name = "HiFi Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98088_RATES,
+ .formats = MAX98088_FORMATS,
+ },
+ .ops = &max98088_dai1_ops,
+},
+{
+ .name = "Aux",
+ .playback = {
+ .stream_name = "Aux Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MAX98088_RATES,
+ .formats = MAX98088_FORMATS,
+ },
+ .ops = &max98088_dai2_ops,
+}
+};
+
+static int max98088_get_channel(const char *name)
+{
+ if (strcmp(name, "EQ1 Mode") == 0)
+ return 0;
+ if (strcmp(name, "EQ2 Mode") == 0)
+ return 1;
+ return -EINVAL;
+}
+
+static void max98088_setup_eq1(struct snd_soc_codec *codec)
+{
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_pdata *pdata = max98088->pdata;
+ struct max98088_eq_cfg *coef_set;
+ int best, best_val, save, i, sel, fs;
+ struct max98088_cdata *cdata;
+
+ cdata = &max98088->dai[0];
+
+ if (!pdata || !max98088->eq_textcnt)
+ return;
+
+ /* Find the selected configuration with nearest sample rate */
+ fs = cdata->rate;
+ sel = cdata->eq_sel;
+
+ best = 0;
+ best_val = INT_MAX;
+ for (i = 0; i < pdata->eq_cfgcnt; i++) {
+ if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 &&
+ abs(pdata->eq_cfg[i].rate - fs) < best_val) {
+ best = i;
+ best_val = abs(pdata->eq_cfg[i].rate - fs);
+ }
+ }
+
+ dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n",
+ pdata->eq_cfg[best].name,
+ pdata->eq_cfg[best].rate, fs);
+
+ /* Disable EQ while configuring, and save current on/off state */
+ save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL);
+ snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0);
+
+ coef_set = &pdata->eq_cfg[sel];
+
+ m98088_eq_band(codec, 0, 0, coef_set->band1);
+ m98088_eq_band(codec, 0, 1, coef_set->band2);
+ m98088_eq_band(codec, 0, 2, coef_set->band3);
+ m98088_eq_band(codec, 0, 3, coef_set->band4);
+ m98088_eq_band(codec, 0, 4, coef_set->band5);
+
+ /* Restore the original on/off state */
+ snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, save);
+}
+
+static void max98088_setup_eq2(struct snd_soc_codec *codec)
+{
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_pdata *pdata = max98088->pdata;
+ struct max98088_eq_cfg *coef_set;
+ int best, best_val, save, i, sel, fs;
+ struct max98088_cdata *cdata;
+
+ cdata = &max98088->dai[1];
+
+ if (!pdata || !max98088->eq_textcnt)
+ return;
+
+ /* Find the selected configuration with nearest sample rate */
+ fs = cdata->rate;
+
+ sel = cdata->eq_sel;
+ best = 0;
+ best_val = INT_MAX;
+ for (i = 0; i < pdata->eq_cfgcnt; i++) {
+ if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 &&
+ abs(pdata->eq_cfg[i].rate - fs) < best_val) {
+ best = i;
+ best_val = abs(pdata->eq_cfg[i].rate - fs);
+ }
+ }
+
+ dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n",
+ pdata->eq_cfg[best].name,
+ pdata->eq_cfg[best].rate, fs);
+
+ /* Disable EQ while configuring, and save current on/off state */
+ save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL);
+ snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0);
+
+ coef_set = &pdata->eq_cfg[sel];
+
+ m98088_eq_band(codec, 1, 0, coef_set->band1);
+ m98088_eq_band(codec, 1, 1, coef_set->band2);
+ m98088_eq_band(codec, 1, 2, coef_set->band3);
+ m98088_eq_band(codec, 1, 3, coef_set->band4);
+ m98088_eq_band(codec, 1, 4, coef_set->band5);
+
+ /* Restore the original on/off state */
+ snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN,
+ save);
+}
+
+static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_pdata *pdata = max98088->pdata;
+ int channel = max98088_get_channel(kcontrol->id.name);
+ struct max98088_cdata *cdata;
+ int sel = ucontrol->value.integer.value[0];
+
+ cdata = &max98088->dai[channel];
+
+ if (sel >= pdata->eq_cfgcnt)
+ return -EINVAL;
+
+ cdata->eq_sel = sel;
+
+ switch (channel) {
+ case 0:
+ max98088_setup_eq1(codec);
+ break;
+ case 1:
+ max98088_setup_eq2(codec);
+ break;
+ }
+
+ return 0;
+}
+
+static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ int channel = max98088_get_channel(kcontrol->id.name);
+ struct max98088_cdata *cdata;
+
+ cdata = &max98088->dai[channel];
+ ucontrol->value.enumerated.item[0] = cdata->eq_sel;
+ return 0;
+}
+
+static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
+{
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_pdata *pdata = max98088->pdata;
+ struct max98088_eq_cfg *cfg;
+ unsigned int cfgcnt;
+ int i, j;
+ const char **t;
+ int ret;
+
+ struct snd_kcontrol_new controls[] = {
+ SOC_ENUM_EXT("EQ1 Mode",
+ max98088->eq_enum,
+ max98088_get_eq_enum,
+ max98088_put_eq_enum),
+ SOC_ENUM_EXT("EQ2 Mode",
+ max98088->eq_enum,
+ max98088_get_eq_enum,
+ max98088_put_eq_enum),
+ };
+
+ cfg = pdata->eq_cfg;
+ cfgcnt = pdata->eq_cfgcnt;
+
+ /* Setup an array of texts for the equalizer enum.
+ * This is based on Mark Brown's equalizer driver code.
+ */
+ max98088->eq_textcnt = 0;
+ max98088->eq_texts = NULL;
+ for (i = 0; i < cfgcnt; i++) {
+ for (j = 0; j < max98088->eq_textcnt; j++) {
+ if (strcmp(cfg[i].name, max98088->eq_texts[j]) == 0)
+ break;
+ }
+
+ if (j != max98088->eq_textcnt)
+ continue;
+
+ /* Expand the array */
+ t = krealloc(max98088->eq_texts,
+ sizeof(char *) * (max98088->eq_textcnt + 1),
+ GFP_KERNEL);
+ if (t == NULL)
+ continue;
+
+ /* Store the new entry */
+ t[max98088->eq_textcnt] = cfg[i].name;
+ max98088->eq_textcnt++;
+ max98088->eq_texts = t;
+ }
+
+ /* Now point the soc_enum to .texts array items */
+ max98088->eq_enum.texts = max98088->eq_texts;
+ max98088->eq_enum.max = max98088->eq_textcnt;
+
+ ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ if (ret != 0)
+ dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
+}
+
+static void max98088_handle_pdata(struct snd_soc_codec *codec)
+{
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_pdata *pdata = max98088->pdata;
+ u8 regval = 0;
+
+ if (!pdata) {
+ dev_dbg(codec->dev, "No platform data\n");
+ return;
+ }
+
+ /* Configure mic for analog/digital mic mode */
+ if (pdata->digmic_left_mode)
+ regval |= M98088_DIGMIC_L;
+
+ if (pdata->digmic_right_mode)
+ regval |= M98088_DIGMIC_R;
+
+ max98088->digmic = (regval ? 1 : 0);
+
+ snd_soc_write(codec, M98088_REG_48_CFG_MIC, regval);
+
+ /* Configure receiver output */
+ regval = ((pdata->receiver_mode) ? M98088_REC_LINEMODE : 0);
+ snd_soc_update_bits(codec, M98088_REG_2A_MIC_REC_CNTL,
+ M98088_REC_LINEMODE_MASK, regval);
+
+ /* Configure equalizers */
+ if (pdata->eq_cfgcnt)
+ max98088_handle_eq_pdata(codec);
+}
+
+#ifdef CONFIG_PM
+static int max98088_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+ max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int max98088_resume(struct snd_soc_codec *codec)
+{
+ max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+#else
+#define max98088_suspend NULL
+#define max98088_resume NULL
+#endif
+
+static int max98088_probe(struct snd_soc_codec *codec)
+{
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+ struct max98088_cdata *cdata;
+ int ret = 0;
+
+ codec->cache_sync = 1;
+ memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ /* initalize private data */
+
+ max98088->sysclk = (unsigned)-1;
+ max98088->eq_textcnt = 0;
+
+ cdata = &max98088->dai[0];
+ cdata->rate = (unsigned)-1;
+ cdata->fmt = (unsigned)-1;
+ cdata->eq_sel = 0;
+
+ cdata = &max98088->dai[1];
+ cdata->rate = (unsigned)-1;
+ cdata->fmt = (unsigned)-1;
+ cdata->eq_sel = 0;
+
+ max98088->ina_state = 0;
+ max98088->inb_state = 0;
+ max98088->ex_mode = 0;
+ max98088->digmic = 0;
+ max98088->mic1pre = 0;
+ max98088->mic2pre = 0;
+
+ ret = snd_soc_read(codec, M98088_REG_FF_REV_ID);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to read device revision: %d\n",
+ ret);
+ goto err_access;
+ }
+ dev_info(codec->dev, "revision %c\n", ret + 'A');
+
+ snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV);
+
+ /* initialize registers cache to hardware default */
+ max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00);
+
+ snd_soc_write(codec, M98088_REG_22_MIX_DAC,
+ M98088_DAI1L_TO_DACL|M98088_DAI2L_TO_DACL|
+ M98088_DAI1R_TO_DACR|M98088_DAI2R_TO_DACR);
+
+ snd_soc_write(codec, M98088_REG_4E_BIAS_CNTL, 0xF0);
+ snd_soc_write(codec, M98088_REG_50_DAC_BIAS2, 0x0F);
+
+ snd_soc_write(codec, M98088_REG_16_DAI1_IOCFG,
+ M98088_S1NORMAL|M98088_SDATA);
+
+ snd_soc_write(codec, M98088_REG_1E_DAI2_IOCFG,
+ M98088_S2NORMAL|M98088_SDATA);
+
+ max98088_handle_pdata(codec);
+
+ max98088_add_widgets(codec);
+
+err_access:
+ return ret;
+}
+
+static int max98088_remove(struct snd_soc_codec *codec)
+{
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+ max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ kfree(max98088->eq_texts);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
+ .probe = max98088_probe,
+ .remove = max98088_remove,
+ .suspend = max98088_suspend,
+ .resume = max98088_resume,
+ .set_bias_level = max98088_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(max98088_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = max98088_reg,
+ .volatile_register = max98088_volatile_register,
+};
+
+static int max98088_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct max98088_priv *max98088;
+ int ret;
+
+ max98088 = kzalloc(sizeof(struct max98088_priv), GFP_KERNEL);
+ if (max98088 == NULL)
+ return -ENOMEM;
+
+ max98088->devtype = id->driver_data;
+
+ i2c_set_clientdata(i2c, max98088);
+ max98088->control_data = i2c;
+ max98088->pdata = i2c->dev.platform_data;
+
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_max98088, &max98088_dai[0], 2);
+ if (ret < 0)
+ kfree(max98088);
+ return ret;
+}
+
+static int __devexit max98088_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+static const struct i2c_device_id max98088_i2c_id[] = {
+ { "max98088", MAX98088 },
+ { "max98089", MAX98089 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
+
+static struct i2c_driver max98088_i2c_driver = {
+ .driver = {
+ .name = "max98088",
+ .owner = THIS_MODULE,
+ },
+ .probe = max98088_i2c_probe,
+ .remove = __devexit_p(max98088_i2c_remove),
+ .id_table = max98088_i2c_id,
+};
+
+static int __init max98088_init(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&max98088_i2c_driver);
+ if (ret)
+ pr_err("Failed to register max98088 I2C driver: %d\n", ret);
+
+ return ret;
+}
+module_init(max98088_init);
+
+static void __exit max98088_exit(void)
+{
+ i2c_del_driver(&max98088_i2c_driver);
+}
+module_exit(max98088_exit);
+
+MODULE_DESCRIPTION("ALSA SoC MAX98088 driver");
+MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98088.h b/sound/soc/codecs/max98088.h
new file mode 100644
index 000000000000..56554c797fef
--- /dev/null
+++ b/sound/soc/codecs/max98088.h
@@ -0,0 +1,193 @@
+/*
+ * max98088.h -- MAX98088 ALSA SoC Audio driver
+ *
+ * Copyright 2010 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MAX98088_H
+#define _MAX98088_H
+
+/*
+ * MAX98088 Registers Definition
+ */
+#define M98088_REG_00_IRQ_STATUS 0x00
+#define M98088_REG_01_MIC_STATUS 0x01
+#define M98088_REG_02_JACK_STAUS 0x02
+#define M98088_REG_03_BATTERY_VOLTAGE 0x03
+#define M98088_REG_0F_IRQ_ENABLE 0x0F
+#define M98088_REG_10_SYS_CLK 0x10
+#define M98088_REG_11_DAI1_CLKMODE 0x11
+#define M98088_REG_12_DAI1_CLKCFG_HI 0x12
+#define M98088_REG_13_DAI1_CLKCFG_LO 0x13
+#define M98088_REG_14_DAI1_FORMAT 0x14
+#define M98088_REG_15_DAI1_CLOCK 0x15
+#define M98088_REG_16_DAI1_IOCFG 0x16
+#define M98088_REG_17_DAI1_TDM 0x17
+#define M98088_REG_18_DAI1_FILTERS 0x18
+#define M98088_REG_19_DAI2_CLKMODE 0x19
+#define M98088_REG_1A_DAI2_CLKCFG_HI 0x1A
+#define M98088_REG_1B_DAI2_CLKCFG_LO 0x1B
+#define M98088_REG_1C_DAI2_FORMAT 0x1C
+#define M98088_REG_1D_DAI2_CLOCK 0x1D
+#define M98088_REG_1E_DAI2_IOCFG 0x1E
+#define M98088_REG_1F_DAI2_TDM 0x1F
+#define M98088_REG_20_DAI2_FILTERS 0x20
+#define M98088_REG_21_SRC 0x21
+#define M98088_REG_22_MIX_DAC 0x22
+#define M98088_REG_23_MIX_ADC_LEFT 0x23
+#define M98088_REG_24_MIX_ADC_RIGHT 0x24
+#define M98088_REG_25_MIX_HP_LEFT 0x25
+#define M98088_REG_26_MIX_HP_RIGHT 0x26
+#define M98088_REG_27_MIX_HP_CNTL 0x27
+#define M98088_REG_28_MIX_REC_LEFT 0x28
+#define M98088_REG_29_MIX_REC_RIGHT 0x29
+#define M98088_REG_2A_MIC_REC_CNTL 0x2A
+#define M98088_REG_2B_MIX_SPK_LEFT 0x2B
+#define M98088_REG_2C_MIX_SPK_RIGHT 0x2C
+#define M98088_REG_2D_MIX_SPK_CNTL 0x2D
+#define M98088_REG_2E_LVL_SIDETONE 0x2E
+#define M98088_REG_2F_LVL_DAI1_PLAY 0x2F
+#define M98088_REG_30_LVL_DAI1_PLAY_EQ 0x30
+#define M98088_REG_31_LVL_DAI2_PLAY 0x31
+#define M98088_REG_32_LVL_DAI2_PLAY_EQ 0x32
+#define M98088_REG_33_LVL_ADC_L 0x33
+#define M98088_REG_34_LVL_ADC_R 0x34
+#define M98088_REG_35_LVL_MIC1 0x35
+#define M98088_REG_36_LVL_MIC2 0x36
+#define M98088_REG_37_LVL_INA 0x37
+#define M98088_REG_38_LVL_INB 0x38
+#define M98088_REG_39_LVL_HP_L 0x39
+#define M98088_REG_3A_LVL_HP_R 0x3A
+#define M98088_REG_3B_LVL_REC_L 0x3B
+#define M98088_REG_3C_LVL_REC_R 0x3C
+#define M98088_REG_3D_LVL_SPK_L 0x3D
+#define M98088_REG_3E_LVL_SPK_R 0x3E
+#define M98088_REG_3F_MICAGC_CFG 0x3F
+#define M98088_REG_40_MICAGC_THRESH 0x40
+#define M98088_REG_41_SPKDHP 0x41
+#define M98088_REG_42_SPKDHP_THRESH 0x42
+#define M98088_REG_43_SPKALC_COMP 0x43
+#define M98088_REG_44_PWRLMT_CFG 0x44
+#define M98088_REG_45_PWRLMT_TIME 0x45
+#define M98088_REG_46_THDLMT_CFG 0x46
+#define M98088_REG_47_CFG_AUDIO_IN 0x47
+#define M98088_REG_48_CFG_MIC 0x48
+#define M98088_REG_49_CFG_LEVEL 0x49
+#define M98088_REG_4A_CFG_BYPASS 0x4A
+#define M98088_REG_4B_CFG_JACKDET 0x4B
+#define M98088_REG_4C_PWR_EN_IN 0x4C
+#define M98088_REG_4D_PWR_EN_OUT 0x4D
+#define M98088_REG_4E_BIAS_CNTL 0x4E
+#define M98088_REG_4F_DAC_BIAS1 0x4F
+#define M98088_REG_50_DAC_BIAS2 0x50
+#define M98088_REG_51_PWR_SYS 0x51
+#define M98088_REG_52_DAI1_EQ_BASE 0x52
+#define M98088_REG_84_DAI2_EQ_BASE 0x84
+#define M98088_REG_B6_DAI1_BIQUAD_BASE 0xB6
+#define M98088_REG_C0_DAI2_BIQUAD_BASE 0xC0
+#define M98088_REG_FF_REV_ID 0xFF
+
+#define M98088_REG_CNT (0xFF+1)
+
+/* MAX98088 Registers Bit Fields */
+
+/* M98088_REG_11_DAI1_CLKMODE, M98088_REG_19_DAI2_CLKMODE */
+ #define M98088_CLKMODE_MASK 0xFF
+
+/* M98088_REG_14_DAI1_FORMAT, M98088_REG_1C_DAI2_FORMAT */
+ #define M98088_DAI_MAS (1<<7)
+ #define M98088_DAI_WCI (1<<6)
+ #define M98088_DAI_BCI (1<<5)
+ #define M98088_DAI_DLY (1<<4)
+ #define M98088_DAI_TDM (1<<2)
+ #define M98088_DAI_FSW (1<<1)
+ #define M98088_DAI_WS (1<<0)
+
+/* M98088_REG_15_DAI1_CLOCK, M98088_REG_1D_DAI2_CLOCK */
+ #define M98088_DAI_BSEL64 (1<<0)
+ #define M98088_DAI_OSR64 (1<<6)
+
+/* M98088_REG_16_DAI1_IOCFG, M98088_REG_1E_DAI2_IOCFG */
+ #define M98088_S1NORMAL (1<<6)
+ #define M98088_S2NORMAL (2<<6)
+ #define M98088_SDATA (3<<0)
+
+/* M98088_REG_18_DAI1_FILTERS, M98088_REG_20_DAI2_FILTERS */
+ #define M98088_DAI_DHF (1<<3)
+
+/* M98088_REG_22_MIX_DAC */
+ #define M98088_DAI1L_TO_DACL (1<<7)
+ #define M98088_DAI1R_TO_DACL (1<<6)
+ #define M98088_DAI2L_TO_DACL (1<<5)
+ #define M98088_DAI2R_TO_DACL (1<<4)
+ #define M98088_DAI1L_TO_DACR (1<<3)
+ #define M98088_DAI1R_TO_DACR (1<<2)
+ #define M98088_DAI2L_TO_DACR (1<<1)
+ #define M98088_DAI2R_TO_DACR (1<<0)
+
+/* M98088_REG_2A_MIC_REC_CNTL */
+ #define M98088_REC_LINEMODE (1<<7)
+ #define M98088_REC_LINEMODE_MASK (1<<7)
+
+/* M98088_REG_35_LVL_MIC1, M98088_REG_36_LVL_MIC2 */
+ #define M98088_MICPRE_MASK (3<<5)
+ #define M98088_MICPRE_SHIFT 5
+
+/* M98088_REG_3A_LVL_HP_R */
+ #define M98088_HP_MUTE (1<<7)
+
+/* M98088_REG_3C_LVL_REC_R */
+ #define M98088_REC_MUTE (1<<7)
+
+/* M98088_REG_3E_LVL_SPK_R */
+ #define M98088_SP_MUTE (1<<7)
+
+/* M98088_REG_48_CFG_MIC */
+ #define M98088_EXTMIC_MASK (3<<0)
+ #define M98088_DIGMIC_L (1<<5)
+ #define M98088_DIGMIC_R (1<<4)
+
+/* M98088_REG_49_CFG_LEVEL */
+ #define M98088_VSEN (1<<6)
+ #define M98088_ZDEN (1<<5)
+ #define M98088_EQ2EN (1<<1)
+ #define M98088_EQ1EN (1<<0)
+
+/* M98088_REG_4C_PWR_EN_IN */
+ #define M98088_INAEN (1<<7)
+ #define M98088_INBEN (1<<6)
+ #define M98088_MBEN (1<<3)
+ #define M98088_ADLEN (1<<1)
+ #define M98088_ADREN (1<<0)
+
+/* M98088_REG_4D_PWR_EN_OUT */
+ #define M98088_HPLEN (1<<7)
+ #define M98088_HPREN (1<<6)
+ #define M98088_HPEN ((1<<7)|(1<<6))
+ #define M98088_SPLEN (1<<5)
+ #define M98088_SPREN (1<<4)
+ #define M98088_RECEN (1<<3)
+ #define M98088_DALEN (1<<1)
+ #define M98088_DAREN (1<<0)
+
+/* M98088_REG_51_PWR_SYS */
+ #define M98088_SHDNRUN (1<<7)
+ #define M98088_PERFMODE (1<<3)
+ #define M98088_HPPLYBACK (1<<2)
+ #define M98088_PWRSV8K (1<<1)
+ #define M98088_PWRSV (1<<0)
+
+/* Line inputs */
+#define LINE_INA 0
+#define LINE_INB 1
+
+#define M98088_COEFS_PER_BAND 5
+
+#define M98088_BYTE1(w) ((w >> 8) & 0xff)
+#define M98088_BYTE0(w) (w & 0xff)
+
+#endif
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index 5a5f187a2657..bd8f26e41602 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -32,8 +32,8 @@
#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
-struct snd_soc_dai pcm3008_dai = {
- .name = "PCM3008 HiFi",
+static struct snd_soc_dai_driver pcm3008_dai = {
+ .name = "pcm3008-hifi",
.playback = {
.stream_name = "PCM3008 Playback",
.channels_min = 1,
@@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
};
-EXPORT_SYMBOL_GPL(pcm3008_dai);
static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
{
@@ -59,38 +58,13 @@ static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
gpio_free(setup->pdda_pin);
}
-static int pcm3008_soc_probe(struct platform_device *pdev)
+static int pcm3008_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct pcm3008_setup_data *setup = socdev->codec_data;
+ struct pcm3008_setup_data *setup = codec->dev->platform_data;
int ret = 0;
printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
- socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (!socdev->card->codec)
- return -ENOMEM;
-
- codec = socdev->card->codec;
- mutex_init(&codec->mutex);
-
- codec->name = "PCM3008";
- codec->owner = THIS_MODULE;
- codec->dai = &pcm3008_dai;
- codec->num_dai = 1;
- codec->write = NULL;
- codec->read = NULL;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- /* Register PCMs. */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "pcm3008: failed to create pcms\n");
- goto pcm_err;
- }
-
/* DEM1 DEM0 DE-EMPHASIS_MODE
* Low Low De-emphasis 44.1 kHz ON
* Low High De-emphasis OFF
@@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
gpio_err:
pcm3008_gpio_free(setup);
-pcm_err:
- kfree(socdev->card->codec);
return ret;
}
-static int pcm3008_soc_remove(struct platform_device *pdev)
+static int pcm3008_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
- struct pcm3008_setup_data *setup = socdev->codec_data;
-
- if (!codec)
- return 0;
+ struct pcm3008_setup_data *setup = codec->dev->platform_data;
pcm3008_gpio_free(setup);
- snd_soc_free_pcms(socdev);
- kfree(socdev->card->codec);
-
return 0;
}
#ifdef CONFIG_PM
-static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct pcm3008_setup_data *setup = socdev->codec_data;
+ struct pcm3008_setup_data *setup = codec->dev->platform_data;
gpio_set_value(setup->pdad_pin, 0);
gpio_set_value(setup->pdda_pin, 0);
@@ -164,10 +127,9 @@ static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
return 0;
}
-static int pcm3008_soc_resume(struct platform_device *pdev)
+static int pcm3008_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct pcm3008_setup_data *setup = socdev->codec_data;
+ struct pcm3008_setup_data *setup = codec->dev->platform_data;
gpio_set_value(setup->pdad_pin, 1);
gpio_set_value(setup->pdda_pin, 1);
@@ -179,23 +141,45 @@ static int pcm3008_soc_resume(struct platform_device *pdev)
#define pcm3008_soc_resume NULL
#endif
-struct snd_soc_codec_device soc_codec_dev_pcm3008 = {
+static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
.probe = pcm3008_soc_probe,
.remove = pcm3008_soc_remove,
.suspend = pcm3008_soc_suspend,
.resume = pcm3008_soc_resume,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008);
-static int __init pcm3008_init(void)
+static int __devinit pcm3008_codec_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_pcm3008, &pcm3008_dai, 1);
+}
+
+static int __devexit pcm3008_codec_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+MODULE_ALIAS("platform:pcm3008-codec");
+
+static struct platform_driver pcm3008_codec_driver = {
+ .probe = pcm3008_codec_probe,
+ .remove = __devexit_p(pcm3008_codec_remove),
+ .driver = {
+ .name = "pcm3008-codec",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pcm3008_modinit(void)
{
- return snd_soc_register_dai(&pcm3008_dai);
+ return platform_driver_register(&pcm3008_codec_driver);
}
-module_init(pcm3008_init);
+module_init(pcm3008_modinit);
static void __exit pcm3008_exit(void)
{
- snd_soc_unregister_dai(&pcm3008_dai);
+ platform_driver_unregister(&pcm3008_codec_driver);
}
module_exit(pcm3008_exit);
diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h
index d04e87d3c060..7e5489ab4812 100644
--- a/sound/soc/codecs/pcm3008.h
+++ b/sound/soc/codecs/pcm3008.h
@@ -19,7 +19,4 @@ struct pcm3008_setup_data {
unsigned pdda_pin;
};
-extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
-extern struct snd_soc_dai pcm3008_dai;
-
#endif
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
index 9119836051a4..4c32b54913ad 100644
--- a/sound/soc/codecs/spdif_transciever.c
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -21,57 +21,16 @@
#include <sound/pcm.h>
#include <sound/initval.h>
-#include "spdif_transciever.h"
-
MODULE_LICENSE("GPL");
#define STUB_RATES SNDRV_PCM_RATE_8000_96000
#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
-static struct snd_soc_codec *spdif_dit_codec;
-
-static int spdif_dit_codec_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret;
-
- if (spdif_dit_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = spdif_dit_codec;
- codec = spdif_dit_codec;
-
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto err_create_pcms;
- }
-
- return 0;
-
-err_create_pcms:
- return ret;
-}
-
-static int spdif_dit_codec_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
-
- return 0;
-}
-struct snd_soc_codec_device soc_codec_dev_spdif_dit = {
- .probe = spdif_dit_codec_probe,
- .remove = spdif_dit_codec_remove,
-}; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit);
+static struct snd_soc_codec_driver soc_codec_spdif_dit;
-struct snd_soc_dai dit_stub_dai = {
- .name = "DIT",
+static struct snd_soc_dai_driver dit_stub_dai = {
+ .name = "dit-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -80,65 +39,16 @@ struct snd_soc_dai dit_stub_dai = {
.formats = STUB_FORMATS,
},
};
-EXPORT_SYMBOL_GPL(dit_stub_dai);
static int spdif_dit_probe(struct platform_device *pdev)
{
- struct snd_soc_codec *codec;
- int ret;
-
- if (spdif_dit_codec) {
- dev_err(&pdev->dev, "Another Codec is registered\n");
- ret = -EINVAL;
- goto err_reg_codec;
- }
-
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- codec->dev = &pdev->dev;
-
- mutex_init(&codec->mutex);
-
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "spdif-dit";
- codec->owner = THIS_MODULE;
- codec->dai = &dit_stub_dai;
- codec->num_dai = 1;
-
- spdif_dit_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err_reg_codec;
- }
-
- dit_stub_dai.dev = &pdev->dev;
- ret = snd_soc_register_dai(&dit_stub_dai);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to register dai: %d\n", ret);
- goto err_reg_dai;
- }
-
- return 0;
-
-err_reg_dai:
- snd_soc_unregister_codec(codec);
-err_reg_codec:
- kfree(spdif_dit_codec);
- return ret;
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit,
+ &dit_stub_dai, 1);
}
static int spdif_dit_remove(struct platform_device *pdev)
{
- snd_soc_unregister_dai(&dit_stub_dai);
- snd_soc_unregister_codec(spdif_dit_codec);
- kfree(spdif_dit_codec);
- spdif_dit_codec = NULL;
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h
deleted file mode 100644
index 1e102124f546..000000000000
--- a/sound/soc/codecs/spdif_transciever.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * ALSA SoC DIT/DIR driver header
- *
- * Author: Steve Chen, <schen@mvista.com>
- * Copyright: (C) 2008 MontaVista Software, Inc., <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef CODEC_STUBS_H
-#define CODEC_STUBS_H
-
-extern struct snd_soc_codec_device soc_codec_dev_spdif_dit;
-extern struct snd_soc_dai dit_stub_dai;
-
-#endif /* CODEC_STUBS_H */
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index b47ed4f6ab20..6f38d619bf8a 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -45,11 +45,11 @@
#define SSM2602_VERSION "0.1"
-struct snd_soc_codec_device soc_codec_dev_ssm2602;
-
/* codec private data */
struct ssm2602_priv {
unsigned int sysclk;
+ enum snd_soc_control_type control_type;
+ void *control_data;
struct snd_pcm_substream *master_substream;
struct snd_pcm_substream *slave_substream;
};
@@ -276,8 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
{
u16 srate;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c = codec->control_data;
u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
@@ -321,8 +320,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c = codec->control_data;
struct snd_pcm_runtime *master_runtime;
@@ -360,8 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
/* set active */
ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
@@ -372,8 +369,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
/* deactivate */
@@ -518,8 +514,8 @@ static struct snd_soc_dai_ops ssm2602_dai_ops = {
.set_fmt = ssm2602_set_dai_fmt,
};
-struct snd_soc_dai ssm2602_dai = {
- .name = "SSM2602",
+static struct snd_soc_dai_driver ssm2602_dai = {
+ .name = "ssm2602-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -534,21 +530,15 @@ struct snd_soc_dai ssm2602_dai = {
.formats = SSM2602_FORMATS,},
.ops = &ssm2602_dai_ops,
};
-EXPORT_SYMBOL_GPL(ssm2602_dai);
-static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state)
+static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int ssm2602_resume(struct platform_device *pdev)
+static int ssm2602_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -563,36 +553,17 @@ static int ssm2602_resume(struct platform_device *pdev)
return 0;
}
-/*
- * initialise the ssm2602 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int ssm2602_init(struct snd_soc_device *socdev)
+static int ssm2602_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = socdev->card->codec;
- int reg, ret = 0;
-
- codec->name = "SSM2602";
- codec->owner = THIS_MODULE;
- codec->read = ssm2602_read_reg_cache;
- codec->write = ssm2602_write;
- codec->set_bias_level = ssm2602_set_bias_level;
- codec->dai = &ssm2602_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = sizeof(ssm2602_reg);
- codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg),
- GFP_KERNEL);
- if (codec->reg_cache == NULL)
- return -ENOMEM;
+ struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0, reg;
+
+ pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
+
+ codec->control_data = ssm2602->control_data;
ssm2602_reset(codec);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- pr_err("ssm2602: failed to create pcms\n");
- goto pcm_err;
- }
/*power on device*/
ssm2602_write(codec, SSM2602_ACTIVE, 0);
/* set the update bits */
@@ -614,13 +585,27 @@ static int ssm2602_init(struct snd_soc_device *socdev)
ssm2602_add_widgets(codec);
return ret;
+}
-pcm_err:
- kfree(codec->reg_cache);
- return ret;
+/* remove everything here */
+static int ssm2602_remove(struct snd_soc_codec *codec)
+{
+ ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
-static struct snd_soc_device *ssm2602_socdev;
+static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
+ .probe = ssm2602_probe,
+ .remove = ssm2602_remove,
+ .suspend = ssm2602_suspend,
+ .resume = ssm2602_resume,
+ .read = ssm2602_read_reg_cache,
+ .write = ssm2602_write,
+ .set_bias_level = ssm2602_set_bias_level,
+ .reg_cache_size = sizeof(ssm2602_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = ssm2602_reg,
+};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/*
@@ -632,24 +617,28 @@ static struct snd_soc_device *ssm2602_socdev;
static int ssm2602_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
- struct snd_soc_device *socdev = ssm2602_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct ssm2602_priv *ssm2602;
int ret;
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
+ ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
+ if (ssm2602 == NULL)
+ return -ENOMEM;
- ret = ssm2602_init(socdev);
- if (ret < 0)
- pr_err("failed to initialise SSM2602\n");
+ i2c_set_clientdata(i2c, ssm2602);
+ ssm2602->control_data = i2c;
+ ssm2602->control_type = SND_SOC_I2C;
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_ssm2602, &ssm2602_dai, 1);
+ if (ret < 0)
+ kfree(ssm2602);
return ret;
}
static int ssm2602_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -658,130 +647,39 @@ static const struct i2c_device_id ssm2602_i2c_id[] = {
{ }
};
MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
+
/* corgi i2c codec control layer */
static struct i2c_driver ssm2602_i2c_driver = {
.driver = {
- .name = "SSM2602 I2C Codec",
+ .name = "ssm2602-codec",
.owner = THIS_MODULE,
},
.probe = ssm2602_i2c_probe,
.remove = ssm2602_i2c_remove,
.id_table = ssm2602_i2c_id,
};
-
-static int ssm2602_add_i2c_device(struct platform_device *pdev,
- const struct ssm2602_setup_data *setup)
-{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- int ret;
-
- ret = i2c_add_driver(&ssm2602_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = setup->i2c_address;
- strlcpy(info.type, "ssm2602", I2C_NAME_SIZE);
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n",
- setup->i2c_bus);
- goto err_driver;
- }
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
- return 0;
-err_driver:
- i2c_del_driver(&ssm2602_i2c_driver);
- return -ENODEV;
-}
#endif
-static int ssm2602_probe(struct platform_device *pdev)
+
+static int __init ssm2602_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct ssm2602_setup_data *setup;
- struct snd_soc_codec *codec;
- struct ssm2602_priv *ssm2602;
int ret = 0;
-
- pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
- if (ssm2602 == NULL) {
- kfree(codec);
- return -ENOMEM;
- }
-
- snd_soc_codec_set_drvdata(codec, ssm2602);
- socdev->card->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- ssm2602_socdev = socdev;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- codec->hw_write = (hw_write_t)i2c_master_send;
- ret = ssm2602_add_i2c_device(pdev, setup);
+ ret = i2c_add_driver(&ssm2602_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n",
+ ret);
}
-#else
- /* other interfaces */
#endif
return ret;
}
+module_init(ssm2602_modinit);
-/* remove everything here */
-static int ssm2602_remove(struct platform_device *pdev)
+static void __exit ssm2602_exit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec->control_data)
- ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_unregister_device(codec->control_data);
i2c_del_driver(&ssm2602_i2c_driver);
#endif
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_ssm2602 = {
- .probe = ssm2602_probe,
- .remove = ssm2602_remove,
- .suspend = ssm2602_suspend,
- .resume = ssm2602_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602);
-
-static int __init ssm2602_modinit(void)
-{
- return snd_soc_register_dai(&ssm2602_dai);
-}
-module_init(ssm2602_modinit);
-
-static void __exit ssm2602_exit(void)
-{
- snd_soc_unregister_dai(&ssm2602_dai);
}
module_exit(ssm2602_exit);
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h
index f344e6d76e31..42a47d0f8e25 100644
--- a/sound/soc/codecs/ssm2602.h
+++ b/sound/soc/codecs/ssm2602.h
@@ -124,7 +124,4 @@ struct ssm2602_setup_data {
unsigned short i2c_address;
};
-extern struct snd_soc_dai ssm2602_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ssm2602;
-
#endif
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index ee86568545c2..061f9e5a497b 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -25,7 +25,6 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
-#include <sound/soc-of-simple.h>
#include "stac9766.h"
@@ -257,20 +256,15 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
return 0;
}
-static int stac9766_codec_suspend(struct platform_device *pdev,
+static int stac9766_codec_suspend(struct snd_soc_codec *codec,
pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int stac9766_codec_resume(struct platform_device *pdev)
+static int stac9766_codec_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
u16 id, reset;
reset = 0;
@@ -300,10 +294,9 @@ static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
.prepare = ac97_digital_prepare,
};
-struct snd_soc_dai stac9766_dai[] = {
+static struct snd_soc_dai_driver stac9766_dai[] = {
{
- .name = "stac9766 analog",
- .id = 0,
+ .name = "stac9766-hifi-analog",
.ac97_control = 1,
/* stream cababilities */
@@ -325,8 +318,7 @@ struct snd_soc_dai stac9766_dai[] = {
.ops = &stac9766_dai_ops_analog,
},
{
- .name = "stac9766 IEC958",
- .id = 1,
+ .name = "stac9766-hifi-IEC958",
.ac97_control = 1,
/* stream cababilities */
@@ -342,57 +334,24 @@ struct snd_soc_dai stac9766_dai[] = {
.ops = &stac9766_dai_ops_digital,
}
};
-EXPORT_SYMBOL_GPL(stac9766_dai);
-static int stac9766_codec_probe(struct platform_device *pdev)
+static int stac9766_codec_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
int ret = 0;
printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION);
- socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (socdev->card->codec == NULL)
- return -ENOMEM;
- codec = socdev->card->codec;
- mutex_init(&codec->mutex);
-
- codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg),
- GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- ret = -ENOMEM;
- goto cache_err;
- }
- codec->reg_cache_size = sizeof(stac9766_reg);
- codec->reg_cache_step = 2;
-
- codec->name = "STAC9766";
- codec->owner = THIS_MODULE;
- codec->dai = stac9766_dai;
- codec->num_dai = ARRAY_SIZE(stac9766_dai);
- codec->write = stac9766_ac97_write;
- codec->read = stac9766_ac97_read;
- codec->set_bias_level = stac9766_set_bias_level;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0)
goto codec_err;
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0)
- goto pcm_err;
-
/* do a cold reset for the controller and then try
* a warm reset followed by an optional cold reset for codec */
stac9766_reset(codec, 0);
ret = stac9766_reset(codec, 1);
if (ret < 0) {
printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n");
- goto reset_err;
+ goto codec_err;
}
stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -402,40 +361,64 @@ static int stac9766_codec_probe(struct platform_device *pdev)
return 0;
-reset_err:
- snd_soc_free_pcms(socdev);
-pcm_err:
- snd_soc_free_ac97_codec(codec);
codec_err:
- kfree(snd_soc_codec_get_drvdata(codec));
-cache_err:
- kfree(socdev->card->codec);
- socdev->card->codec = NULL;
+ snd_soc_free_ac97_codec(codec);
return ret;
}
-static int stac9766_codec_remove(struct platform_device *pdev)
+static int stac9766_codec_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec == NULL)
- return 0;
-
- snd_soc_free_pcms(socdev);
snd_soc_free_ac97_codec(codec);
- kfree(codec->reg_cache);
- kfree(codec);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_stac9766 = {
+static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
+ .write = stac9766_ac97_write,
+ .read = stac9766_ac97_read,
+ .set_bias_level = stac9766_set_bias_level,
.probe = stac9766_codec_probe,
.remove = stac9766_codec_remove,
.suspend = stac9766_codec_suspend,
.resume = stac9766_codec_resume,
+ .reg_cache_size = sizeof(stac9766_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_step = 2,
+ .reg_cache_default = stac9766_reg,
+};
+
+static __devinit int stac9766_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai));
+}
+
+static int __devexit stac9766_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver stac9766_codec_driver = {
+ .driver = {
+ .name = "stac9766-codec",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = stac9766_probe,
+ .remove = __devexit_p(stac9766_remove),
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766);
+
+static int __init stac9766_init(void)
+{
+ return platform_driver_register(&stac9766_codec_driver);
+}
+module_init(stac9766_init);
+
+static void __exit stac9766_exit(void)
+{
+ platform_driver_unregister(&stac9766_codec_driver);
+}
+module_exit(stac9766_exit);
MODULE_DESCRIPTION("ASoC stac9766 driver");
MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
diff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h
index 65642eb8393e..c726f907e2c0 100644
--- a/sound/soc/codecs/stac9766.h
+++ b/sound/soc/codecs/stac9766.h
@@ -14,8 +14,4 @@
#define STAC9766_DAI_AC97_ANALOG 0
#define STAC9766_DAI_AC97_DIGITAL 1
-extern struct snd_soc_dai stac9766_dai[];
-extern struct snd_soc_codec_device soc_codec_dev_stac9766;
-
-
#endif
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 0a4b0fef3355..e8652b1ae326 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -240,7 +240,8 @@ static const struct snd_soc_dapm_route intercon[] = {
/* AIC23 driver data */
struct aic23 {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
int mclk;
int requested_adc;
int requested_dac;
@@ -404,11 +405,10 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 iface_reg;
int ret;
- struct aic23 *aic23 = container_of(codec, struct aic23, codec);
+ struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
u32 sample_rate_adc = aic23->requested_adc;
u32 sample_rate_dac = aic23->requested_dac;
u32 sample_rate = params_rate(params);
@@ -452,8 +452,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
/* set active */
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
@@ -465,9 +464,8 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
- struct aic23 *aic23 = container_of(codec, struct aic23, codec);
+ struct snd_soc_codec *codec = rtd->codec;
+ struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
/* deactivate */
if (!codec->active) {
@@ -546,8 +544,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct aic23 *aic23 = container_of(codec, struct aic23, codec);
+ struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai);
aic23->mclk = freq;
return 0;
}
@@ -594,8 +591,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
.set_sysclk = tlv320aic23_set_dai_sysclk,
};
-struct snd_soc_dai tlv320aic23_dai = {
- .name = "tlv320aic23",
+static struct snd_soc_dai_driver tlv320aic23_dai = {
+ .name = "tlv320aic23-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -610,23 +607,17 @@ struct snd_soc_dai tlv320aic23_dai = {
.formats = AIC23_FORMATS,},
.ops = &tlv320aic23_dai_ops,
};
-EXPORT_SYMBOL_GPL(tlv320aic23_dai);
-static int tlv320aic23_suspend(struct platform_device *pdev,
+static int tlv320aic23_suspend(struct snd_soc_codec *codec,
pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int tlv320aic23_resume(struct platform_device *pdev)
+static int tlv320aic23_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
u16 reg;
/* Sync reg_cache with the hardware */
@@ -639,39 +630,19 @@ static int tlv320aic23_resume(struct platform_device *pdev)
return 0;
}
-/*
- * initialise the AIC23 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int tlv320aic23_init(struct snd_soc_device *socdev)
+static int tlv320aic23_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = socdev->card->codec;
- int ret = 0;
- u16 reg;
+ struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
+ int reg;
- codec->name = "tlv320aic23";
- codec->owner = THIS_MODULE;
- codec->read = tlv320aic23_read_reg_cache;
- codec->write = tlv320aic23_write;
- codec->set_bias_level = tlv320aic23_set_bias_level;
- codec->dai = &tlv320aic23_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
- codec->reg_cache =
- kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
- if (codec->reg_cache == NULL)
- return -ENOMEM;
+ printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
+ codec->control_data = aic23->control_data;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ codec->hw_read = NULL;
/* Reset codec */
tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
- goto pcm_err;
- }
-
/* power on device */
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -707,13 +678,27 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
ARRAY_SIZE(tlv320aic23_snd_controls));
tlv320aic23_add_widgets(codec);
- return ret;
+ return 0;
+}
-pcm_err:
- kfree(codec->reg_cache);
- return ret;
+static int tlv320aic23_remove(struct snd_soc_codec *codec)
+{
+ tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
-static struct snd_soc_device *tlv320aic23_socdev;
+
+static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
+ .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = tlv320aic23_reg,
+ .probe = tlv320aic23_probe,
+ .remove = tlv320aic23_remove,
+ .suspend = tlv320aic23_suspend,
+ .resume = tlv320aic23_resume,
+ .read = tlv320aic23_read_reg_cache,
+ .write = tlv320aic23_write,
+ .set_bias_level = tlv320aic23_set_bias_level,
+};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/*
@@ -723,31 +708,30 @@ static struct snd_soc_device *tlv320aic23_socdev;
static int tlv320aic23_codec_probe(struct i2c_client *i2c,
const struct i2c_device_id *i2c_id)
{
- struct snd_soc_device *socdev = tlv320aic23_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct aic23 *aic23;
int ret;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EINVAL;
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
+ aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
+ if (aic23 == NULL)
+ return -ENOMEM;
- ret = tlv320aic23_init(socdev);
- if (ret < 0) {
- printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n");
- goto err;
- }
- return ret;
+ i2c_set_clientdata(i2c, aic23);
+ aic23->control_data = i2c;
+ aic23->control_type = SND_SOC_I2C;
-err:
- kfree(codec);
- kfree(i2c);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
+ if (ret < 0)
+ kfree(aic23);
return ret;
}
static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
{
- put_device(&i2c->dev);
+ snd_soc_unregister_codec(&i2c->dev);
+ kfree(i2c_get_clientdata(i2c));
return 0;
}
@@ -760,7 +744,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
static struct i2c_driver tlv320aic23_i2c_driver = {
.driver = {
- .name = "tlv320aic23",
+ .name = "tlv320aic23-codec",
},
.probe = tlv320aic23_codec_probe,
.remove = __exit_p(tlv320aic23_i2c_remove),
@@ -769,71 +753,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = {
#endif
-static int tlv320aic23_probe(struct platform_device *pdev)
+static int __init tlv320aic23_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct aic23 *aic23;
- int ret = 0;
-
- printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
-
- aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
- if (aic23 == NULL)
- return -ENOMEM;
- codec = &aic23->codec;
- socdev->card->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- tlv320aic23_socdev = socdev;
+ int ret;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- codec->hw_write = (hw_write_t) i2c_master_send;
- codec->hw_read = NULL;
ret = i2c_add_driver(&tlv320aic23_i2c_driver);
- if (ret != 0)
- printk(KERN_ERR "can't add i2c driver");
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n",
+ ret);
+ }
#endif
return ret;
}
+module_init(tlv320aic23_modinit);
-static int tlv320aic23_remove(struct platform_device *pdev)
+static void __exit tlv320aic23_exit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
- struct aic23 *aic23 = container_of(codec, struct aic23, codec);
-
- if (codec->control_data)
- tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&tlv320aic23_i2c_driver);
#endif
- kfree(codec->reg_cache);
- kfree(aic23);
-
- return 0;
-}
-struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
- .probe = tlv320aic23_probe,
- .remove = tlv320aic23_remove,
- .suspend = tlv320aic23_suspend,
- .resume = tlv320aic23_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
-
-static int __init tlv320aic23_modinit(void)
-{
- return snd_soc_register_dai(&tlv320aic23_dai);
-}
-module_init(tlv320aic23_modinit);
-
-static void __exit tlv320aic23_exit(void)
-{
- snd_soc_unregister_dai(&tlv320aic23_dai);
}
module_exit(tlv320aic23_exit);
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
index 79d1faf8e570..e804120bd3da 100644
--- a/sound/soc/codecs/tlv320aic23.h
+++ b/sound/soc/codecs/tlv320aic23.h
@@ -116,7 +116,4 @@
#define TLV320AIC23_SIDETONE_12 0x080
#define TLV320AIC23_SIDETONE_18 0x0c0
-extern struct snd_soc_dai tlv320aic23_dai;
-extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23;
-
#endif /* _TLV320AIC23_H */
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index f0e00fd4b435..6b7d71ec0004 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -19,7 +19,6 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
-#include <sound/soc-of-simple.h>
#include <sound/initval.h>
#include "tlv320aic26.h"
@@ -130,8 +129,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
int fsref, divisor, wlen, pval, jval, dval, qval;
u16 reg;
@@ -278,8 +276,8 @@ static struct snd_soc_dai_ops aic26_dai_ops = {
.set_fmt = aic26_set_fmt,
};
-struct snd_soc_dai aic26_dai = {
- .name = "tlv320aic26",
+static struct snd_soc_dai_driver aic26_dai = {
+ .name = "tlv320aic26-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -296,7 +294,6 @@ struct snd_soc_dai aic26_dai = {
},
.ops = &aic26_dai_ops,
};
-EXPORT_SYMBOL_GPL(aic26_dai);
/* ---------------------------------------------------------------------
* ALSA controls
@@ -319,61 +316,6 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = {
};
/* ---------------------------------------------------------------------
- * SoC CODEC portion of driver: probe and release routines
- */
-static int aic26_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct aic26 *aic26;
- int ret, err;
-
- dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n");
- dev_dbg(&pdev->dev, "socdev=%p\n", socdev);
- dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data);
-
- /* Fetch the relevant aic26 private data here (it's already been
- * stored in the .codec pointer) */
- aic26 = socdev->codec_data;
- if (aic26 == NULL) {
- dev_err(&pdev->dev, "aic26: missing codec pointer\n");
- return -ENODEV;
- }
- codec = &aic26->codec;
- socdev->card->codec = codec;
-
- dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n",
- &pdev->dev, socdev->dev);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "aic26: failed to create pcms\n");
- return -ENODEV;
- }
-
- /* register controls */
- dev_dbg(&pdev->dev, "Registering controls\n");
- err = snd_soc_add_controls(codec, aic26_snd_controls,
- ARRAY_SIZE(aic26_snd_controls));
- WARN_ON(err < 0);
-
- return 0;
-}
-
-static int aic26_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- snd_soc_free_pcms(socdev);
- return 0;
-}
-
-struct snd_soc_codec_device aic26_soc_codec_dev = {
- .probe = aic26_probe,
- .remove = aic26_remove,
-};
-EXPORT_SYMBOL_GPL(aic26_soc_codec_dev);
-
-/* ---------------------------------------------------------------------
* SPI device portion of driver: sysfs files for debugging
*/
@@ -409,95 +351,95 @@ static ssize_t aic26_keyclick_set(struct device *dev,
static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
/* ---------------------------------------------------------------------
- * SPI device portion of driver: probe and release routines and SPI
- * driver registration.
+ * SoC CODEC portion of driver: probe and release routines
*/
-static int aic26_spi_probe(struct spi_device *spi)
+static int aic26_probe(struct snd_soc_codec *codec)
{
- struct aic26 *aic26;
- int ret, i, reg;
-
- dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
-
- /* Allocate driver data */
- aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
- if (!aic26)
- return -ENOMEM;
-
- /* Initialize the driver data */
- aic26->spi = spi;
- dev_set_drvdata(&spi->dev, aic26);
+ struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
+ int ret, err, i, reg;
- /* Setup what we can in the codec structure so that the register
- * access functions will work as expected. More will be filled
- * out when it is probed by the SoC CODEC part of this driver */
- snd_soc_codec_set_drvdata(&aic26->codec, aic26);
- aic26->codec.name = "aic26";
- aic26->codec.owner = THIS_MODULE;
- aic26->codec.dai = &aic26_dai;
- aic26->codec.num_dai = 1;
- aic26->codec.read = aic26_reg_read;
- aic26->codec.write = aic26_reg_write;
- aic26->master = 1;
- mutex_init(&aic26->codec.mutex);
- INIT_LIST_HEAD(&aic26->codec.dapm_widgets);
- INIT_LIST_HEAD(&aic26->codec.dapm_paths);
- aic26->codec.reg_cache_size = AIC26_NUM_REGS;
- aic26->codec.reg_cache = aic26->reg_cache;
-
- aic26_dai.dev = &spi->dev;
- ret = snd_soc_register_dai(&aic26_dai);
- if (ret != 0) {
- dev_err(&spi->dev, "Failed to register DAI: %d\n", ret);
- kfree(aic26);
- return ret;
- }
+ dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n");
/* Reset the codec to power on defaults */
- aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00);
+ aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00);
/* Power up CODEC */
- aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0);
+ aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0);
/* Audio Control 3 (master mode, fsref rate) */
- reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3);
+ reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3);
reg &= ~0xf800;
reg |= 0x0800; /* set master mode */
- aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg);
+ aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
/* Fill register cache */
for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++)
- aic26_reg_read(&aic26->codec, i);
+ aic26_reg_read(codec, i);
/* Register the sysfs files for debugging */
/* Create SysFS files */
- ret = device_create_file(&spi->dev, &dev_attr_keyclick);
+ ret = device_create_file(codec->dev, &dev_attr_keyclick);
if (ret)
- dev_info(&spi->dev, "error creating sysfs files\n");
+ dev_info(codec->dev, "error creating sysfs files\n");
-#if defined(CONFIG_SND_SOC_OF_SIMPLE)
- /* Tell the of_soc helper about this codec */
- of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai,
- spi->dev.archdata.of_node);
-#endif
+ /* register controls */
+ dev_dbg(codec->dev, "Registering controls\n");
+ err = snd_soc_add_controls(codec, aic26_snd_controls,
+ ARRAY_SIZE(aic26_snd_controls));
+ WARN_ON(err < 0);
- dev_dbg(&spi->dev, "SPI device initialized\n");
return 0;
}
-static int aic26_spi_remove(struct spi_device *spi)
+static struct snd_soc_codec_driver aic26_soc_codec_dev = {
+ .probe = aic26_probe,
+ .read = aic26_reg_read,
+ .write = aic26_reg_write,
+ .reg_cache_size = AIC26_NUM_REGS,
+ .reg_word_size = sizeof(u16),
+};
+
+/* ---------------------------------------------------------------------
+ * SPI device portion of driver: probe and release routines and SPI
+ * driver registration.
+ */
+static int aic26_spi_probe(struct spi_device *spi)
{
- struct aic26 *aic26 = dev_get_drvdata(&spi->dev);
+ struct aic26 *aic26;
+ int ret;
- snd_soc_unregister_dai(&aic26_dai);
- kfree(aic26);
+ dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
+
+ /* Allocate driver data */
+ aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
+ if (!aic26)
+ return -ENOMEM;
+ /* Initialize the driver data */
+ aic26->spi = spi;
+ dev_set_drvdata(&spi->dev, aic26);
+ aic26->master = 1;
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &aic26_soc_codec_dev, &aic26_dai, 1);
+ if (ret < 0)
+ kfree(aic26);
+ return ret;
+
+ dev_dbg(&spi->dev, "SPI device initialized\n");
+ return 0;
+}
+
+static int aic26_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver aic26_spi = {
.driver = {
- .name = "tlv320aic26",
+ .name = "tlv320aic26-codec",
.owner = THIS_MODULE,
},
.probe = aic26_spi_probe,
diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h
index 786ba16c945f..62b1f2261429 100644
--- a/sound/soc/codecs/tlv320aic26.h
+++ b/sound/soc/codecs/tlv320aic26.h
@@ -90,7 +90,4 @@ enum aic26_wlen {
AIC26_WLEN_32 = 3 << 10,
};
-extern struct snd_soc_dai aic26_dai;
-extern struct snd_soc_codec_device aic26_soc_codec_dev;
-
#endif /* _TLV320AIC16_H_ */
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 71a69908ccf6..77b8f9ae29be 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -12,11 +12,11 @@
*
* Notes:
* The AIC3X is a driver for a low power stereo audio
- * codecs aic31, aic32, aic33.
+ * codecs aic31, aic32, aic33, aic3007.
*
* It supports full aic33 codec functionality.
- * The compatibility with aic32, aic31 is as follows:
- * aic32 | aic31
+ * The compatibility with aic32, aic31 and aic3007 is as follows:
+ * aic32/aic3007 | aic31
* ---------------------------------------
* MONO_LOUT -> N/A | MONO_LOUT -> N/A
* | IN1L -> LINE1L
@@ -61,13 +61,29 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
"DRVDD", /* ADC Analog and Output Driver Voltage */
};
+struct aic3x_priv;
+
+struct aic3x_disable_nb {
+ struct notifier_block nb;
+ struct aic3x_priv *aic3x;
+};
+
/* codec private data */
struct aic3x_priv {
- struct snd_soc_codec codec;
+ struct snd_soc_codec *codec;
struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
+ struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
+ enum snd_soc_control_type control_type;
+ struct aic3x_setup_data *setup;
+ void *control_data;
unsigned int sysclk;
int master;
int gpio_reset;
+ int power;
+#define AIC3X_MODEL_3X 0
+#define AIC3X_MODEL_33 1
+#define AIC3X_MODEL_3007 2
+ u16 model;
};
/*
@@ -106,62 +122,23 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
};
/*
- * read aic3x register cache
+ * read from the aic3x register space. Only use for this function is if
+ * wanting to read volatile bits from those registers that has both read-only
+ * and read/write bits. All other cases should use snd_soc_read.
*/
-static inline unsigned int aic3x_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
+static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
+ u8 *value)
{
u8 *cache = codec->reg_cache;
- if (reg >= AIC3X_CACHEREGNUM)
- return -1;
- return cache[reg];
-}
-/*
- * write aic3x register cache
- */
-static inline void aic3x_write_reg_cache(struct snd_soc_codec *codec,
- u8 reg, u8 value)
-{
- u8 *cache = codec->reg_cache;
+ if (codec->cache_only)
+ return -EINVAL;
if (reg >= AIC3X_CACHEREGNUM)
- return;
- cache[reg] = value;
-}
-
-/*
- * write to the aic3x register space
- */
-static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 data[2];
-
- /* data is
- * D15..D8 aic3x register offset
- * D7...D0 register data
- */
- data[0] = reg & 0xff;
- data[1] = value & 0xff;
-
- aic3x_write_reg_cache(codec, data[0], data[1]);
- if (codec->hw_write(codec->control_data, data, 2) == 2)
- return 0;
- else
- return -EIO;
-}
-
-/*
- * read from the aic3x register space
- */
-static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
- u8 *value)
-{
- *value = reg & 0xff;
+ return -1;
- value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]);
+ *value = codec->hw_read(codec, reg);
+ cache[reg] = *value;
- aic3x_write_reg_cache(codec, reg, *value);
return 0;
}
@@ -286,64 +263,102 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
SOC_DOUBLE_R_TLV("PCM Playback Volume",
LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv),
+ /*
+ * Output controls that map to output mixer switches. Note these are
+ * only for swapped L-to-R and R-to-L routes. See below stereo controls
+ * for direct L-to-L and R-to-R routes.
+ */
+ SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume",
+ LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume",
+ PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume",
+ DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
+
+ SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume",
+ LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume",
+ PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume",
+ DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
+
+ SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume",
+ LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume",
+ PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume",
+ DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
+
+ SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume",
+ LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume",
+ PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume",
+ DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
+
+ SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume",
+ LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume",
+ PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume",
+ DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
+
+ SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume",
+ LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume",
+ PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
+ SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume",
+ DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
+
+ /* Stereo output controls for direct L-to-L and R-to-R routes */
+ SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume",
+ LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL,
+ 0, 118, 1, output_stage_tlv),
+ SOC_DOUBLE_R_TLV("Line PGA Bypass Volume",
+ PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL,
+ 0, 118, 1, output_stage_tlv),
SOC_DOUBLE_R_TLV("Line DAC Playback Volume",
DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL,
0, 118, 1, output_stage_tlv),
- SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0),
- SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0),
- SOC_DOUBLE_R_TLV("LineL DAC Playback Volume",
- DACL1_2_LLOPM_VOL, DACR1_2_LLOPM_VOL,
- 0, 118, 1, output_stage_tlv),
- SOC_SINGLE_TLV("LineL Left PGA Bypass Playback Volume",
- PGAL_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
- SOC_SINGLE_TLV("LineR Right PGA Bypass Playback Volume",
- PGAR_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
- SOC_DOUBLE_R_TLV("LineL Line2 Bypass Playback Volume",
- LINE2L_2_LLOPM_VOL, LINE2R_2_LLOPM_VOL,
+
+ SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume",
+ LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
0, 118, 1, output_stage_tlv),
- SOC_DOUBLE_R_TLV("LineR Line2 Bypass Playback Volume",
- LINE2L_2_RLOPM_VOL, LINE2R_2_RLOPM_VOL,
+ SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume",
+ PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
0, 118, 1, output_stage_tlv),
-
SOC_DOUBLE_R_TLV("Mono DAC Playback Volume",
DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL,
0, 118, 1, output_stage_tlv),
- SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
- SOC_DOUBLE_R_TLV("Mono PGA Bypass Playback Volume",
- PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
+
+ SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume",
+ LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
0, 118, 1, output_stage_tlv),
- SOC_DOUBLE_R_TLV("Mono Line2 Bypass Playback Volume",
- LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
+ SOC_DOUBLE_R_TLV("HP PGA Bypass Volume",
+ PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
0, 118, 1, output_stage_tlv),
-
SOC_DOUBLE_R_TLV("HP DAC Playback Volume",
DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL,
0, 118, 1, output_stage_tlv),
- SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
- 0x01, 0),
- SOC_DOUBLE_R_TLV("HP Right PGA Bypass Playback Volume",
- PGAR_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
+
+ SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume",
+ LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
0, 118, 1, output_stage_tlv),
- SOC_SINGLE_TLV("HPL PGA Bypass Playback Volume",
- PGAL_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
- SOC_SINGLE_TLV("HPR PGA Bypass Playback Volume",
- PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
- SOC_DOUBLE_R_TLV("HP Line2 Bypass Playback Volume",
- LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
+ SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume",
+ PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL,
0, 118, 1, output_stage_tlv),
-
SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume",
DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL,
0, 118, 1, output_stage_tlv),
- SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
+
+ /* Output pin mute controls */
+ SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
+ 0x01, 0),
+ SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
+ SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
+ 0x01, 0),
+ SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
0x01, 0),
- SOC_SINGLE_TLV("HPLCOM PGA Bypass Playback Volume",
- PGAL_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
- SOC_SINGLE_TLV("HPRCOM PGA Bypass Playback Volume",
- PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
- SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Playback Volume",
- LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
- 0, 118, 1, output_stage_tlv),
/*
* Note: enable Automatic input Gain Controller with care. It can
@@ -359,6 +374,14 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
};
+/*
+ * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0);
+
+static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl =
+ SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv);
+
/* Left DAC Mux */
static const struct snd_kcontrol_new aic3x_left_dac_mux_controls =
SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]);
@@ -375,22 +398,74 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LHPCOM_ENUM]);
static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls =
SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]);
-/* Left DAC_L1 Mixer */
-static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
+/* Left Line Mixer */
+static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
};
-/* Right DAC_R1 Mixer */
-static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
+/* Right Line Mixer */
+static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
+};
+
+/* Mono Mixer */
+static const struct snd_kcontrol_new aic3x_mono_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
+};
+
+/* Left HP Mixer */
+static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLOUT_VOL, 7, 1, 0),
+};
+
+/* Right HP Mixer */
+static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
+};
+
+/* Left HPCOM Mixer */
+static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLCOM_VOL, 7, 1, 0),
+};
+
+/* Right HPCOM Mixer */
+static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
};
/* Left PGA Mixer */
@@ -427,54 +502,11 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LINE2L_ENUM]);
static const struct snd_kcontrol_new aic3x_right_line2_mux_controls =
SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]);
-/* Left PGA Bypass Mixer */
-static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
-};
-
-/* Right PGA Bypass Mixer */
-static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
-};
-
-/* Left Line2 Bypass Mixer */
-static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
-};
-
-/* Right Line2 Bypass Mixer */
-static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
-};
-
static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
/* Left DAC to Left Outputs */
SND_SOC_DAPM_DAC("Left DAC", "Left Playback", DAC_PWR, 7, 0),
SND_SOC_DAPM_MUX("Left DAC Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_dac_mux_controls),
- SND_SOC_DAPM_MIXER("Left DAC_L1 Mixer", SND_SOC_NOPM, 0, 0,
- &aic3x_left_dac_mixer_controls[0],
- ARRAY_SIZE(aic3x_left_dac_mixer_controls)),
SND_SOC_DAPM_MUX("Left HPCOM Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_hpcom_mux_controls),
SND_SOC_DAPM_PGA("Left Line Out", LLOPM_CTRL, 0, 0, NULL, 0),
@@ -485,9 +517,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
SND_SOC_DAPM_DAC("Right DAC", "Right Playback", DAC_PWR, 6, 0),
SND_SOC_DAPM_MUX("Right DAC Mux", SND_SOC_NOPM, 0, 0,
&aic3x_right_dac_mux_controls),
- SND_SOC_DAPM_MIXER("Right DAC_R1 Mixer", SND_SOC_NOPM, 0, 0,
- &aic3x_right_dac_mixer_controls[0],
- ARRAY_SIZE(aic3x_right_dac_mixer_controls)),
SND_SOC_DAPM_MUX("Right HPCOM Mux", SND_SOC_NOPM, 0, 0,
&aic3x_right_hpcom_mux_controls),
SND_SOC_DAPM_PGA("Right Line Out", RLOPM_CTRL, 0, 0, NULL, 0),
@@ -551,25 +580,28 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD",
MICBIAS_CTRL, 6, 3, 3, 0),
- /* Left PGA to Left Output bypass */
- SND_SOC_DAPM_MIXER("Left PGA Bypass Mixer", SND_SOC_NOPM, 0, 0,
- &aic3x_left_pga_bp_mixer_controls[0],
- ARRAY_SIZE(aic3x_left_pga_bp_mixer_controls)),
-
- /* Right PGA to Right Output bypass */
- SND_SOC_DAPM_MIXER("Right PGA Bypass Mixer", SND_SOC_NOPM, 0, 0,
- &aic3x_right_pga_bp_mixer_controls[0],
- ARRAY_SIZE(aic3x_right_pga_bp_mixer_controls)),
-
- /* Left Line2 to Left Output bypass */
- SND_SOC_DAPM_MIXER("Left Line2 Bypass Mixer", SND_SOC_NOPM, 0, 0,
- &aic3x_left_line2_bp_mixer_controls[0],
- ARRAY_SIZE(aic3x_left_line2_bp_mixer_controls)),
-
- /* Right Line2 to Right Output bypass */
- SND_SOC_DAPM_MIXER("Right Line2 Bypass Mixer", SND_SOC_NOPM, 0, 0,
- &aic3x_right_line2_bp_mixer_controls[0],
- ARRAY_SIZE(aic3x_right_line2_bp_mixer_controls)),
+ /* Output mixers */
+ SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0,
+ &aic3x_left_line_mixer_controls[0],
+ ARRAY_SIZE(aic3x_left_line_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0,
+ &aic3x_right_line_mixer_controls[0],
+ ARRAY_SIZE(aic3x_right_line_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
+ &aic3x_mono_mixer_controls[0],
+ ARRAY_SIZE(aic3x_mono_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
+ &aic3x_left_hp_mixer_controls[0],
+ ARRAY_SIZE(aic3x_left_hp_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0,
+ &aic3x_right_hp_mixer_controls[0],
+ ARRAY_SIZE(aic3x_right_hp_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Left HPCOM Mixer", SND_SOC_NOPM, 0, 0,
+ &aic3x_left_hpcom_mixer_controls[0],
+ ARRAY_SIZE(aic3x_left_hpcom_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right HPCOM Mixer", SND_SOC_NOPM, 0, 0,
+ &aic3x_right_hpcom_mixer_controls[0],
+ ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)),
SND_SOC_DAPM_OUTPUT("LLOUT"),
SND_SOC_DAPM_OUTPUT("RLOUT"),
@@ -585,69 +617,26 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("LINE1R"),
SND_SOC_DAPM_INPUT("LINE2L"),
SND_SOC_DAPM_INPUT("LINE2R"),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
- /* Left Output */
- {"Left DAC Mux", "DAC_L1", "Left DAC"},
- {"Left DAC Mux", "DAC_L2", "Left DAC"},
- {"Left DAC Mux", "DAC_L3", "Left DAC"},
-
- {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"},
- {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"},
- {"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"},
- {"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"},
- {"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"},
- {"Left Line Out", NULL, "Left DAC Mux"},
- {"Left HP Out", NULL, "Left DAC Mux"},
-
- {"Left HPCOM Mux", "differential of HPLOUT", "Left DAC_L1 Mixer"},
- {"Left HPCOM Mux", "constant VCM", "Left DAC_L1 Mixer"},
- {"Left HPCOM Mux", "single-ended", "Left DAC_L1 Mixer"},
-
- {"Left Line Out", NULL, "Left DAC_L1 Mixer"},
- {"Mono Out", NULL, "Left DAC_L1 Mixer"},
- {"Left HP Out", NULL, "Left DAC_L1 Mixer"},
- {"Left HP Com", NULL, "Left HPCOM Mux"},
-
- {"LLOUT", NULL, "Left Line Out"},
- {"LLOUT", NULL, "Left Line Out"},
- {"HPLOUT", NULL, "Left HP Out"},
- {"HPLCOM", NULL, "Left HP Com"},
- /* Right Output */
- {"Right DAC Mux", "DAC_R1", "Right DAC"},
- {"Right DAC Mux", "DAC_R2", "Right DAC"},
- {"Right DAC Mux", "DAC_R3", "Right DAC"},
-
- {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"},
- {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"},
- {"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"},
- {"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"},
- {"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"},
- {"Right Line Out", NULL, "Right DAC Mux"},
- {"Right HP Out", NULL, "Right DAC Mux"},
-
- {"Right HPCOM Mux", "differential of HPROUT", "Right DAC_R1 Mixer"},
- {"Right HPCOM Mux", "constant VCM", "Right DAC_R1 Mixer"},
- {"Right HPCOM Mux", "single-ended", "Right DAC_R1 Mixer"},
- {"Right HPCOM Mux", "differential of HPLCOM", "Right DAC_R1 Mixer"},
- {"Right HPCOM Mux", "external feedback", "Right DAC_R1 Mixer"},
-
- {"Right Line Out", NULL, "Right DAC_R1 Mixer"},
- {"Mono Out", NULL, "Right DAC_R1 Mixer"},
- {"Right HP Out", NULL, "Right DAC_R1 Mixer"},
- {"Right HP Com", NULL, "Right HPCOM Mux"},
+ /*
+ * Virtual output pin to detection block inside codec. This can be
+ * used to keep codec bias on if gpio or detection features are needed.
+ * Force pin on or construct a path with an input jack and mic bias
+ * widgets.
+ */
+ SND_SOC_DAPM_OUTPUT("Detection"),
+};
- {"RLOUT", NULL, "Right Line Out"},
- {"RLOUT", NULL, "Right Line Out"},
- {"HPROUT", NULL, "Right HP Out"},
- {"HPRCOM", NULL, "Right HP Com"},
+static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = {
+ /* Class-D outputs */
+ SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Right Class-D Out", CLASSD_CTRL, 2, 0, NULL, 0),
- /* Mono Output */
- {"MONO_LOUT", NULL, "Mono Out"},
- {"MONO_LOUT", NULL, "Mono Out"},
+ SND_SOC_DAPM_OUTPUT("SPOP"),
+ SND_SOC_DAPM_OUTPUT("SPOM"),
+};
+static const struct snd_soc_dapm_route intercon[] = {
/* Left Input */
{"Left Line1L Mux", "single-ended", "LINE1L"},
{"Left Line1L Mux", "differential", "LINE1L"},
@@ -680,74 +669,6 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right ADC", NULL, "Right PGA Mixer"},
{"Right ADC", NULL, "GPIO1 dmic modclk"},
- /* Left PGA Bypass */
- {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"},
-
- {"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"},
- {"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"},
- {"Left HPCOM Mux", "single-ended", "Left PGA Bypass Mixer"},
-
- {"Left Line Out", NULL, "Left PGA Bypass Mixer"},
- {"Mono Out", NULL, "Left PGA Bypass Mixer"},
- {"Left HP Out", NULL, "Left PGA Bypass Mixer"},
-
- /* Right PGA Bypass */
- {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"},
-
- {"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"},
- {"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"},
- {"Right HPCOM Mux", "single-ended", "Right PGA Bypass Mixer"},
- {"Right HPCOM Mux", "differential of HPLCOM", "Right PGA Bypass Mixer"},
- {"Right HPCOM Mux", "external feedback", "Right PGA Bypass Mixer"},
-
- {"Right Line Out", NULL, "Right PGA Bypass Mixer"},
- {"Mono Out", NULL, "Right PGA Bypass Mixer"},
- {"Right HP Out", NULL, "Right PGA Bypass Mixer"},
-
- /* Left Line2 Bypass */
- {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"},
- {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"},
- {"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"},
- {"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"},
- {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"},
-
- {"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"},
- {"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"},
- {"Left HPCOM Mux", "single-ended", "Left Line2 Bypass Mixer"},
-
- {"Left Line Out", NULL, "Left Line2 Bypass Mixer"},
- {"Mono Out", NULL, "Left Line2 Bypass Mixer"},
- {"Left HP Out", NULL, "Left Line2 Bypass Mixer"},
-
- /* Right Line2 Bypass */
- {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"},
- {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"},
- {"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"},
- {"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"},
- {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"},
-
- {"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"},
- {"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"},
- {"Right HPCOM Mux", "single-ended", "Right Line2 Bypass Mixer"},
- {"Right HPCOM Mux", "differential of HPLCOM", "Right Line2 Bypass Mixer"},
- {"Right HPCOM Mux", "external feedback", "Right Line2 Bypass Mixer"},
-
- {"Right Line Out", NULL, "Right Line2 Bypass Mixer"},
- {"Mono Out", NULL, "Right Line2 Bypass Mixer"},
- {"Right HP Out", NULL, "Right Line2 Bypass Mixer"},
-
/*
* Logical path between digital mic enable and GPIO1 modulator clock
* output function
@@ -755,16 +676,131 @@ static const struct snd_soc_dapm_route intercon[] = {
{"GPIO1 dmic modclk", NULL, "DMic Rate 128"},
{"GPIO1 dmic modclk", NULL, "DMic Rate 64"},
{"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
+
+ /* Left DAC Output */
+ {"Left DAC Mux", "DAC_L1", "Left DAC"},
+ {"Left DAC Mux", "DAC_L2", "Left DAC"},
+ {"Left DAC Mux", "DAC_L3", "Left DAC"},
+
+ /* Right DAC Output */
+ {"Right DAC Mux", "DAC_R1", "Right DAC"},
+ {"Right DAC Mux", "DAC_R2", "Right DAC"},
+ {"Right DAC Mux", "DAC_R3", "Right DAC"},
+
+ /* Left Line Output */
+ {"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+ {"Left Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+ {"Left Line Mixer", "DACL1 Switch", "Left DAC Mux"},
+ {"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+ {"Left Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+ {"Left Line Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+ {"Left Line Out", NULL, "Left Line Mixer"},
+ {"Left Line Out", NULL, "Left DAC Mux"},
+ {"LLOUT", NULL, "Left Line Out"},
+
+ /* Right Line Output */
+ {"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+ {"Right Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+ {"Right Line Mixer", "DACL1 Switch", "Left DAC Mux"},
+ {"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+ {"Right Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+ {"Right Line Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+ {"Right Line Out", NULL, "Right Line Mixer"},
+ {"Right Line Out", NULL, "Right DAC Mux"},
+ {"RLOUT", NULL, "Right Line Out"},
+
+ /* Mono Output */
+ {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+ {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+ {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"},
+ {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+ {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+ {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+ {"Mono Out", NULL, "Mono Mixer"},
+ {"MONO_LOUT", NULL, "Mono Out"},
+
+ /* Left HP Output */
+ {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+ {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+ {"Left HP Mixer", "DACL1 Switch", "Left DAC Mux"},
+ {"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+ {"Left HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+ {"Left HP Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+ {"Left HP Out", NULL, "Left HP Mixer"},
+ {"Left HP Out", NULL, "Left DAC Mux"},
+ {"HPLOUT", NULL, "Left HP Out"},
+
+ /* Right HP Output */
+ {"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+ {"Right HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+ {"Right HP Mixer", "DACL1 Switch", "Left DAC Mux"},
+ {"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+ {"Right HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+ {"Right HP Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+ {"Right HP Out", NULL, "Right HP Mixer"},
+ {"Right HP Out", NULL, "Right DAC Mux"},
+ {"HPROUT", NULL, "Right HP Out"},
+
+ /* Left HPCOM Output */
+ {"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+ {"Left HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+ {"Left HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"},
+ {"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+ {"Left HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+ {"Left HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+ {"Left HPCOM Mux", "differential of HPLOUT", "Left HP Mixer"},
+ {"Left HPCOM Mux", "constant VCM", "Left HPCOM Mixer"},
+ {"Left HPCOM Mux", "single-ended", "Left HPCOM Mixer"},
+ {"Left HP Com", NULL, "Left HPCOM Mux"},
+ {"HPLCOM", NULL, "Left HP Com"},
+
+ /* Right HPCOM Output */
+ {"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+ {"Right HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+ {"Right HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"},
+ {"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+ {"Right HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+ {"Right HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+ {"Right HPCOM Mux", "differential of HPROUT", "Right HP Mixer"},
+ {"Right HPCOM Mux", "constant VCM", "Right HPCOM Mixer"},
+ {"Right HPCOM Mux", "single-ended", "Right HPCOM Mixer"},
+ {"Right HPCOM Mux", "differential of HPLCOM", "Left HPCOM Mixer"},
+ {"Right HPCOM Mux", "external feedback", "Right HPCOM Mixer"},
+ {"Right HP Com", NULL, "Right HPCOM Mux"},
+ {"HPRCOM", NULL, "Right HP Com"},
+};
+
+static const struct snd_soc_dapm_route intercon_3007[] = {
+ /* Class-D outputs */
+ {"Left Class-D Out", NULL, "Left Line Out"},
+ {"Right Class-D Out", NULL, "Left Line Out"},
+ {"SPOP", NULL, "Left Class-D Out"},
+ {"SPOM", NULL, "Right Class-D Out"},
};
static int aic3x_add_widgets(struct snd_soc_codec *codec)
{
+ struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+
snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
ARRAY_SIZE(aic3x_dapm_widgets));
/* set up audio path interconnects */
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+ if (aic3x->model == AIC3X_MODEL_3007) {
+ snd_soc_dapm_new_controls(codec, aic3007_dapm_widgets,
+ ARRAY_SIZE(aic3007_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, intercon_3007, ARRAY_SIZE(intercon_3007));
+ }
+
return 0;
}
@@ -773,8 +809,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec =rtd->codec;
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
@@ -783,8 +818,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
int clk;
/* select data word length */
- data =
- aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
+ data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
break;
@@ -798,7 +832,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
data |= (0x03 << 4);
break;
}
- aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data);
+ snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, data);
/* Fsref can be 44100 or 48000 */
fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000;
@@ -813,17 +847,17 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
if (bypass_pll) {
pll_q &= 0xf;
- aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
- aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
+ snd_soc_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
+ snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
/* disable PLL if it is bypassed */
- reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
- aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
+ reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+ snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
} else {
- aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
+ snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
/* enable PLL when it is used */
- reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
- aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
+ reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+ snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
}
/* Route Left DAC to left channel input and
@@ -832,7 +866,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000;
if (params_rate(params) >= 64000)
data |= DUAL_RATE_MODE;
- aic3x_write(codec, AIC3X_CODEC_DATAPATH_REG, data);
+ snd_soc_write(codec, AIC3X_CODEC_DATAPATH_REG, data);
/* codec sample rate select */
data = (fsref * 20) / params_rate(params);
@@ -841,7 +875,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
data /= 5;
data -= 2;
data |= (data << 4);
- aic3x_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data);
+ snd_soc_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data);
if (bypass_pll)
return 0;
@@ -910,13 +944,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
}
found:
- data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
- aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT));
- aic3x_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG, pll_r << PLLR_SHIFT);
- aic3x_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT);
- aic3x_write(codec, AIC3X_PLL_PROGC_REG, (pll_d >> 6) << PLLD_MSB_SHIFT);
- aic3x_write(codec, AIC3X_PLL_PROGD_REG,
- (pll_d & 0x3F) << PLLD_LSB_SHIFT);
+ data = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+ snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
+ data | (pll_p << PLLP_SHIFT));
+ snd_soc_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG,
+ pll_r << PLLR_SHIFT);
+ snd_soc_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT);
+ snd_soc_write(codec, AIC3X_PLL_PROGC_REG,
+ (pll_d >> 6) << PLLD_MSB_SHIFT);
+ snd_soc_write(codec, AIC3X_PLL_PROGD_REG,
+ (pll_d & 0x3F) << PLLD_LSB_SHIFT);
return 0;
}
@@ -924,15 +961,15 @@ found:
static int aic3x_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- u8 ldac_reg = aic3x_read_reg_cache(codec, LDAC_VOL) & ~MUTE_ON;
- u8 rdac_reg = aic3x_read_reg_cache(codec, RDAC_VOL) & ~MUTE_ON;
+ u8 ldac_reg = snd_soc_read(codec, LDAC_VOL) & ~MUTE_ON;
+ u8 rdac_reg = snd_soc_read(codec, RDAC_VOL) & ~MUTE_ON;
if (mute) {
- aic3x_write(codec, LDAC_VOL, ldac_reg | MUTE_ON);
- aic3x_write(codec, RDAC_VOL, rdac_reg | MUTE_ON);
+ snd_soc_write(codec, LDAC_VOL, ldac_reg | MUTE_ON);
+ snd_soc_write(codec, RDAC_VOL, rdac_reg | MUTE_ON);
} else {
- aic3x_write(codec, LDAC_VOL, ldac_reg);
- aic3x_write(codec, RDAC_VOL, rdac_reg);
+ snd_soc_write(codec, LDAC_VOL, ldac_reg);
+ snd_soc_write(codec, RDAC_VOL, rdac_reg);
}
return 0;
@@ -956,8 +993,8 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
u8 iface_areg, iface_breg;
int delay = 0;
- iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
- iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
+ iface_areg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
+ iface_breg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -996,13 +1033,98 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
/* set iface */
- aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg);
- aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg);
- aic3x_write(codec, AIC3X_ASD_INTF_CTRLC, delay);
+ snd_soc_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg);
+ snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg);
+ snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, delay);
+
+ return 0;
+}
+
+static int aic3x_init_3007(struct snd_soc_codec *codec)
+{
+ u8 tmp1, tmp2, *cache = codec->reg_cache;
+
+ /*
+ * There is no need to cache writes to undocumented page 0xD but
+ * respective page 0 register cache entries must be preserved
+ */
+ tmp1 = cache[0xD];
+ tmp2 = cache[0x8];
+ /* Class-D speaker driver init; datasheet p. 46 */
+ snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
+ snd_soc_write(codec, 0xD, 0x0D);
+ snd_soc_write(codec, 0x8, 0x5C);
+ snd_soc_write(codec, 0x8, 0x5D);
+ snd_soc_write(codec, 0x8, 0x5C);
+ snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
+ cache[0xD] = tmp1;
+ cache[0x8] = tmp2;
return 0;
}
+static int aic3x_regulator_event(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct aic3x_disable_nb *disable_nb =
+ container_of(nb, struct aic3x_disable_nb, nb);
+ struct aic3x_priv *aic3x = disable_nb->aic3x;
+
+ if (event & REGULATOR_EVENT_DISABLE) {
+ /*
+ * Put codec to reset and require cache sync as at least one
+ * of the supplies was disabled
+ */
+ if (aic3x->gpio_reset >= 0)
+ gpio_set_value(aic3x->gpio_reset, 0);
+ aic3x->codec->cache_sync = 1;
+ }
+
+ return 0;
+}
+
+static int aic3x_set_power(struct snd_soc_codec *codec, int power)
+{
+ struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+ int i, ret;
+ u8 *cache = codec->reg_cache;
+
+ if (power) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
+ aic3x->supplies);
+ if (ret)
+ goto out;
+ aic3x->power = 1;
+ /*
+ * Reset release and cache sync is necessary only if some
+ * supply was off or if there were cached writes
+ */
+ if (!codec->cache_sync)
+ goto out;
+
+ if (aic3x->gpio_reset >= 0) {
+ udelay(1);
+ gpio_set_value(aic3x->gpio_reset, 1);
+ }
+
+ /* Sync reg_cache with the hardware */
+ codec->cache_only = 0;
+ for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++)
+ snd_soc_write(codec, i, cache[i]);
+ if (aic3x->model == AIC3X_MODEL_3007)
+ aic3x_init_3007(codec);
+ codec->cache_sync = 0;
+ } else {
+ aic3x->power = 0;
+ /* HW writes are needless when bias is off */
+ codec->cache_only = 1;
+ ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
+ aic3x->supplies);
+ }
+out:
+ return ret;
+}
+
static int aic3x_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -1013,23 +1135,29 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
- if (aic3x->master) {
+ if (codec->bias_level == SND_SOC_BIAS_STANDBY &&
+ aic3x->master) {
/* enable pll */
- reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
- aic3x_write(codec, AIC3X_PLL_PROGA_REG,
- reg | PLL_ENABLE);
+ reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+ snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
+ reg | PLL_ENABLE);
}
break;
case SND_SOC_BIAS_STANDBY:
- /* fall through and disable pll */
- case SND_SOC_BIAS_OFF:
- if (aic3x->master) {
+ if (!aic3x->power)
+ aic3x_set_power(codec, 1);
+ if (codec->bias_level == SND_SOC_BIAS_PREPARE &&
+ aic3x->master) {
/* disable pll */
- reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
- aic3x_write(codec, AIC3X_PLL_PROGA_REG,
- reg & ~PLL_ENABLE);
+ reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+ snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
+ reg & ~PLL_ENABLE);
}
break;
+ case SND_SOC_BIAS_OFF:
+ if (aic3x->power)
+ aic3x_set_power(codec, 0);
+ break;
}
codec->bias_level = level;
@@ -1040,15 +1168,15 @@ void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
{
u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
u8 bit = gpio ? 3: 0;
- u8 val = aic3x_read_reg_cache(codec, reg) & ~(1 << bit);
- aic3x_write(codec, reg, val | (!!state << bit));
+ u8 val = snd_soc_read(codec, reg) & ~(1 << bit);
+ snd_soc_write(codec, reg, val | (!!state << bit));
}
EXPORT_SYMBOL_GPL(aic3x_set_gpio);
int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
{
u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
- u8 val, bit = gpio ? 2: 1;
+ u8 val = 0, bit = gpio ? 2 : 1;
aic3x_read(codec, reg, &val);
return (val >> bit) & 1;
@@ -1070,13 +1198,13 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
if (detect & AIC3X_HEADSET_DETECT_MASK)
val |= AIC3X_HEADSET_DETECT_ENABLED;
- aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
+ snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
}
EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
int aic3x_headset_detected(struct snd_soc_codec *codec)
{
- u8 val;
+ u8 val = 0;
aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
return (val >> 4) & 1;
}
@@ -1084,7 +1212,7 @@ EXPORT_SYMBOL_GPL(aic3x_headset_detected);
int aic3x_button_pressed(struct snd_soc_codec *codec)
{
- u8 val;
+ u8 val = 0;
aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
return (val >> 5) & 1;
}
@@ -1101,8 +1229,8 @@ static struct snd_soc_dai_ops aic3x_dai_ops = {
.set_fmt = aic3x_set_dai_fmt,
};
-struct snd_soc_dai aic3x_dai = {
- .name = "tlv320aic3x",
+static struct snd_soc_dai_driver aic3x_dai = {
+ .name = "tlv320aic3x-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -1116,34 +1244,18 @@ struct snd_soc_dai aic3x_dai = {
.rates = AIC3X_RATES,
.formats = AIC3X_FORMATS,},
.ops = &aic3x_dai_ops,
+ .symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(aic3x_dai);
-static int aic3x_suspend(struct platform_device *pdev, pm_message_t state)
+static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int aic3x_resume(struct platform_device *pdev)
+static int aic3x_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
- int i;
- u8 data[2];
- u8 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++) {
- data[0] = i;
- data[1] = cache[i];
- codec->hw_write(codec->control_data, data, 2);
- }
-
aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -1155,152 +1267,203 @@ static int aic3x_resume(struct platform_device *pdev)
*/
static int aic3x_init(struct snd_soc_codec *codec)
{
+ struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
int reg;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "tlv320aic3x";
- codec->owner = THIS_MODULE;
- codec->read = aic3x_read_reg_cache;
- codec->write = aic3x_write;
- codec->set_bias_level = aic3x_set_bias_level;
- codec->dai = &aic3x_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(aic3x_reg);
- codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL);
- if (codec->reg_cache == NULL)
- return -ENOMEM;
-
- aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
- aic3x_write(codec, AIC3X_RESET, SOFT_RESET);
+ snd_soc_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
+ snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
/* DAC default volume and mute */
- aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON);
- aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON);
+ snd_soc_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON);
+ snd_soc_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON);
/* DAC to HP default volume and route to Output mixer */
- aic3x_write(codec, DACL1_2_HPLOUT_VOL, DEFAULT_VOL | ROUTE_ON);
- aic3x_write(codec, DACR1_2_HPROUT_VOL, DEFAULT_VOL | ROUTE_ON);
- aic3x_write(codec, DACL1_2_HPLCOM_VOL, DEFAULT_VOL | ROUTE_ON);
- aic3x_write(codec, DACR1_2_HPRCOM_VOL, DEFAULT_VOL | ROUTE_ON);
+ snd_soc_write(codec, DACL1_2_HPLOUT_VOL, DEFAULT_VOL | ROUTE_ON);
+ snd_soc_write(codec, DACR1_2_HPROUT_VOL, DEFAULT_VOL | ROUTE_ON);
+ snd_soc_write(codec, DACL1_2_HPLCOM_VOL, DEFAULT_VOL | ROUTE_ON);
+ snd_soc_write(codec, DACR1_2_HPRCOM_VOL, DEFAULT_VOL | ROUTE_ON);
/* DAC to Line Out default volume and route to Output mixer */
- aic3x_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
- aic3x_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+ snd_soc_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+ snd_soc_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
/* DAC to Mono Line Out default volume and route to Output mixer */
- aic3x_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
- aic3x_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+ snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+ snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
/* unmute all outputs */
- reg = aic3x_read_reg_cache(codec, LLOPM_CTRL);
- aic3x_write(codec, LLOPM_CTRL, reg | UNMUTE);
- reg = aic3x_read_reg_cache(codec, RLOPM_CTRL);
- aic3x_write(codec, RLOPM_CTRL, reg | UNMUTE);
- reg = aic3x_read_reg_cache(codec, MONOLOPM_CTRL);
- aic3x_write(codec, MONOLOPM_CTRL, reg | UNMUTE);
- reg = aic3x_read_reg_cache(codec, HPLOUT_CTRL);
- aic3x_write(codec, HPLOUT_CTRL, reg | UNMUTE);
- reg = aic3x_read_reg_cache(codec, HPROUT_CTRL);
- aic3x_write(codec, HPROUT_CTRL, reg | UNMUTE);
- reg = aic3x_read_reg_cache(codec, HPLCOM_CTRL);
- aic3x_write(codec, HPLCOM_CTRL, reg | UNMUTE);
- reg = aic3x_read_reg_cache(codec, HPRCOM_CTRL);
- aic3x_write(codec, HPRCOM_CTRL, reg | UNMUTE);
+ reg = snd_soc_read(codec, LLOPM_CTRL);
+ snd_soc_write(codec, LLOPM_CTRL, reg | UNMUTE);
+ reg = snd_soc_read(codec, RLOPM_CTRL);
+ snd_soc_write(codec, RLOPM_CTRL, reg | UNMUTE);
+ reg = snd_soc_read(codec, MONOLOPM_CTRL);
+ snd_soc_write(codec, MONOLOPM_CTRL, reg | UNMUTE);
+ reg = snd_soc_read(codec, HPLOUT_CTRL);
+ snd_soc_write(codec, HPLOUT_CTRL, reg | UNMUTE);
+ reg = snd_soc_read(codec, HPROUT_CTRL);
+ snd_soc_write(codec, HPROUT_CTRL, reg | UNMUTE);
+ reg = snd_soc_read(codec, HPLCOM_CTRL);
+ snd_soc_write(codec, HPLCOM_CTRL, reg | UNMUTE);
+ reg = snd_soc_read(codec, HPRCOM_CTRL);
+ snd_soc_write(codec, HPRCOM_CTRL, reg | UNMUTE);
/* ADC default volume and unmute */
- aic3x_write(codec, LADC_VOL, DEFAULT_GAIN);
- aic3x_write(codec, RADC_VOL, DEFAULT_GAIN);
+ snd_soc_write(codec, LADC_VOL, DEFAULT_GAIN);
+ snd_soc_write(codec, RADC_VOL, DEFAULT_GAIN);
/* By default route Line1 to ADC PGA mixer */
- aic3x_write(codec, LINE1L_2_LADC_CTRL, 0x0);
- aic3x_write(codec, LINE1R_2_RADC_CTRL, 0x0);
+ snd_soc_write(codec, LINE1L_2_LADC_CTRL, 0x0);
+ snd_soc_write(codec, LINE1R_2_RADC_CTRL, 0x0);
/* PGA to HP Bypass default volume, disconnect from Output Mixer */
- aic3x_write(codec, PGAL_2_HPLOUT_VOL, DEFAULT_VOL);
- aic3x_write(codec, PGAR_2_HPROUT_VOL, DEFAULT_VOL);
- aic3x_write(codec, PGAL_2_HPLCOM_VOL, DEFAULT_VOL);
- aic3x_write(codec, PGAR_2_HPRCOM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, PGAL_2_HPLOUT_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, PGAR_2_HPROUT_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, PGAL_2_HPLCOM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, PGAR_2_HPRCOM_VOL, DEFAULT_VOL);
/* PGA to Line Out default volume, disconnect from Output Mixer */
- aic3x_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
- aic3x_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
/* PGA to Mono Line Out default volume, disconnect from Output Mixer */
- aic3x_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
- aic3x_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
/* Line2 to HP Bypass default volume, disconnect from Output Mixer */
- aic3x_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
- aic3x_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
- aic3x_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
- aic3x_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
/* Line2 Line Out default volume, disconnect from Output Mixer */
- aic3x_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
- aic3x_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
/* Line2 to Mono Out default volume, disconnect from Output Mixer */
- aic3x_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
- aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
+ snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
- /* off, with power on */
- aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ if (aic3x->model == AIC3X_MODEL_3007) {
+ aic3x_init_3007(codec);
+ snd_soc_write(codec, CLASSD_CTRL, 0);
+ }
return 0;
}
-static struct snd_soc_codec *aic3x_codec;
-
-static int aic3x_register(struct snd_soc_codec *codec)
+static int aic3x_probe(struct snd_soc_codec *codec)
{
- int ret;
+ struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+ int ret, i;
+
+ codec->control_data = aic3x->control_data;
+ aic3x->codec = codec;
+ codec->idle_bias_off = 1;
- ret = aic3x_init(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to initialise device\n");
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- aic3x_codec = codec;
+ if (aic3x->gpio_reset >= 0) {
+ ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
+ if (ret != 0)
+ goto err_gpio;
+ gpio_direction_output(aic3x->gpio_reset, 0);
+ }
- ret = snd_soc_register_codec(codec);
- if (ret) {
- dev_err(codec->dev, "Failed to register codec\n");
- return ret;
+ for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
+ aic3x->supplies[i].supply = aic3x_supply_names[i];
+
+ ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
+ aic3x->supplies);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ goto err_get;
+ }
+ for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
+ aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
+ aic3x->disable_nb[i].aic3x = aic3x;
+ ret = regulator_register_notifier(aic3x->supplies[i].consumer,
+ &aic3x->disable_nb[i].nb);
+ if (ret) {
+ dev_err(codec->dev,
+ "Failed to request regulator notifier: %d\n",
+ ret);
+ goto err_notif;
+ }
}
- ret = snd_soc_register_dai(&aic3x_dai);
- if (ret) {
- dev_err(codec->dev, "Failed to register dai\n");
- snd_soc_unregister_codec(codec);
- return ret;
+ codec->cache_only = 1;
+ aic3x_init(codec);
+
+ if (aic3x->setup) {
+ /* setup GPIO functions */
+ snd_soc_write(codec, AIC3X_GPIO1_REG,
+ (aic3x->setup->gpio_func[0] & 0xf) << 4);
+ snd_soc_write(codec, AIC3X_GPIO2_REG,
+ (aic3x->setup->gpio_func[1] & 0xf) << 4);
}
+ snd_soc_add_controls(codec, aic3x_snd_controls,
+ ARRAY_SIZE(aic3x_snd_controls));
+ if (aic3x->model == AIC3X_MODEL_3007)
+ snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
+
+ aic3x_add_widgets(codec);
+
return 0;
+
+err_notif:
+ while (i--)
+ regulator_unregister_notifier(aic3x->supplies[i].consumer,
+ &aic3x->disable_nb[i].nb);
+ regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
+err_get:
+ if (aic3x->gpio_reset >= 0)
+ gpio_free(aic3x->gpio_reset);
+err_gpio:
+ kfree(aic3x);
+ return ret;
}
-static int aic3x_unregister(struct aic3x_priv *aic3x)
+static int aic3x_remove(struct snd_soc_codec *codec)
{
- aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF);
-
- snd_soc_unregister_dai(&aic3x_dai);
- snd_soc_unregister_codec(&aic3x->codec);
+ struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+ int i;
+ aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
if (aic3x->gpio_reset >= 0) {
gpio_set_value(aic3x->gpio_reset, 0);
gpio_free(aic3x->gpio_reset);
}
- regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
+ for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
+ regulator_unregister_notifier(aic3x->supplies[i].consumer,
+ &aic3x->disable_nb[i].nb);
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
- kfree(aic3x);
- aic3x_codec = NULL;
-
return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
+ .set_bias_level = aic3x_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(aic3x_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = aic3x_reg,
+ .probe = aic3x_probe,
+ .remove = aic3x_remove,
+ .suspend = aic3x_suspend,
+ .resume = aic3x_resume,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/*
* AIC3X 2 wire address can be up to 4 devices with device addresses
* 0x18, 0x19, 0x1A, 0x1B
*/
+static const struct i2c_device_id aic3x_i2c_id[] = {
+ [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
+ [AIC3X_MODEL_33] = { "tlv320aic33", 0 },
+ [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
+
/*
* If the i2c layer weren't so broken, we could pass this kind of data
* around
@@ -1308,10 +1471,10 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
static int aic3x_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
- struct snd_soc_codec *codec;
- struct aic3x_priv *aic3x;
struct aic3x_pdata *pdata = i2c->dev.platform_data;
- int ret, i;
+ struct aic3x_priv *aic3x;
+ int ret;
+ const struct i2c_device_id *tbl;
aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
if (aic3x == NULL) {
@@ -1319,75 +1482,41 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
}
- codec = &aic3x->codec;
- codec->dev = &i2c->dev;
- snd_soc_codec_set_drvdata(codec, aic3x);
- codec->control_data = i2c;
- codec->hw_write = (hw_write_t) i2c_master_send;
+ aic3x->control_data = i2c;
+ aic3x->control_type = SND_SOC_I2C;
i2c_set_clientdata(i2c, aic3x);
-
- aic3x->gpio_reset = -1;
- if (pdata && pdata->gpio_reset >= 0) {
- ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset");
- if (ret != 0)
- goto err_gpio;
+ if (pdata) {
aic3x->gpio_reset = pdata->gpio_reset;
- gpio_direction_output(aic3x->gpio_reset, 0);
- }
-
- for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
- aic3x->supplies[i].supply = aic3x_supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
- aic3x->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err_get;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
- aic3x->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_enable;
+ aic3x->setup = pdata->setup;
+ } else {
+ aic3x->gpio_reset = -1;
}
- if (aic3x->gpio_reset >= 0) {
- udelay(1);
- gpio_set_value(aic3x->gpio_reset, 1);
+ for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
+ if (!strcmp(tbl->name, id->name))
+ break;
}
+ aic3x->model = tbl - aic3x_i2c_id;
- return aic3x_register(codec);
-
-err_enable:
- regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
-err_get:
- if (aic3x->gpio_reset >= 0)
- gpio_free(aic3x->gpio_reset);
-err_gpio:
- kfree(aic3x);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_aic3x, &aic3x_dai, 1);
+ if (ret < 0)
+ kfree(aic3x);
return ret;
}
static int aic3x_i2c_remove(struct i2c_client *client)
{
- struct aic3x_priv *aic3x = i2c_get_clientdata(client);
-
- return aic3x_unregister(aic3x);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
+ return 0;
}
-static const struct i2c_device_id aic3x_i2c_id[] = {
- { "tlv320aic3x", 0 },
- { "tlv320aic33", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
-
/* machine i2c codec control layer */
static struct i2c_driver aic3x_i2c_driver = {
.driver = {
- .name = "aic3x I2C Codec",
+ .name = "tlv320aic3x-codec",
.owner = THIS_MODULE,
},
.probe = aic3x_i2c_probe,
@@ -1409,90 +1538,27 @@ static inline void aic3x_i2c_exit(void)
{
i2c_del_driver(&aic3x_i2c_driver);
}
-#else
-static inline void aic3x_i2c_init(void) { }
-static inline void aic3x_i2c_exit(void) { }
#endif
-static int aic3x_probe(struct platform_device *pdev)
+static int __init aic3x_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct aic3x_setup_data *setup;
- struct snd_soc_codec *codec;
int ret = 0;
-
- codec = aic3x_codec;
- if (!codec) {
- dev_err(&pdev->dev, "Codec not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = codec;
- setup = socdev->codec_data;
-
- if (setup) {
- /* setup GPIO functions */
- aic3x_write(codec, AIC3X_GPIO1_REG,
- (setup->gpio_func[0] & 0xf) << 4);
- aic3x_write(codec, AIC3X_GPIO2_REG,
- (setup->gpio_func[1] & 0xf) << 4);
- }
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "aic3x: failed to create pcms\n");
- goto pcm_err;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&aic3x_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n",
+ ret);
}
-
- snd_soc_add_controls(codec, aic3x_snd_controls,
- ARRAY_SIZE(aic3x_snd_controls));
-
- aic3x_add_widgets(codec);
-
- return ret;
-
-pcm_err:
- kfree(codec->reg_cache);
+#endif
return ret;
}
-
-static int aic3x_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- /* power down chip */
- if (codec->control_data)
- aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- kfree(codec->reg_cache);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_aic3x = {
- .probe = aic3x_probe,
- .remove = aic3x_remove,
- .suspend = aic3x_suspend,
- .resume = aic3x_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
-
-static int __init aic3x_modinit(void)
-{
- aic3x_i2c_init();
-
- return 0;
-}
module_init(aic3x_modinit);
static void __exit aic3x_exit(void)
{
- aic3x_i2c_exit();
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&aic3x_i2c_driver);
+#endif
}
module_exit(aic3x_exit);
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 9af1c886213c..06a19784b162 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -81,50 +81,63 @@
/* DAC Digital control registers */
#define LDAC_VOL 43
#define RDAC_VOL 44
-/* High Power Output control registers */
+/* Left High Power Output control registers */
#define LINE2L_2_HPLOUT_VOL 45
-#define LINE2R_2_HPROUT_VOL 62
#define PGAL_2_HPLOUT_VOL 46
-#define PGAL_2_HPROUT_VOL 60
-#define PGAR_2_HPLOUT_VOL 49
-#define PGAR_2_HPROUT_VOL 63
#define DACL1_2_HPLOUT_VOL 47
-#define DACR1_2_HPROUT_VOL 64
+#define LINE2R_2_HPLOUT_VOL 48
+#define PGAR_2_HPLOUT_VOL 49
+#define DACR1_2_HPLOUT_VOL 50
#define HPLOUT_CTRL 51
-#define HPROUT_CTRL 65
-/* High Power COM control registers */
+/* Left High Power COM control registers */
#define LINE2L_2_HPLCOM_VOL 52
-#define LINE2R_2_HPRCOM_VOL 69
#define PGAL_2_HPLCOM_VOL 53
+#define DACL1_2_HPLCOM_VOL 54
+#define LINE2R_2_HPLCOM_VOL 55
#define PGAR_2_HPLCOM_VOL 56
+#define DACR1_2_HPLCOM_VOL 57
+#define HPLCOM_CTRL 58
+/* Right High Power Output control registers */
+#define LINE2L_2_HPROUT_VOL 59
+#define PGAL_2_HPROUT_VOL 60
+#define DACL1_2_HPROUT_VOL 61
+#define LINE2R_2_HPROUT_VOL 62
+#define PGAR_2_HPROUT_VOL 63
+#define DACR1_2_HPROUT_VOL 64
+#define HPROUT_CTRL 65
+/* Right High Power COM control registers */
+#define LINE2L_2_HPRCOM_VOL 66
#define PGAL_2_HPRCOM_VOL 67
+#define DACL1_2_HPRCOM_VOL 68
+#define LINE2R_2_HPRCOM_VOL 69
#define PGAR_2_HPRCOM_VOL 70
-#define DACL1_2_HPLCOM_VOL 54
#define DACR1_2_HPRCOM_VOL 71
-#define HPLCOM_CTRL 58
#define HPRCOM_CTRL 72
/* Mono Line Output Plus/Minus control registers */
#define LINE2L_2_MONOLOPM_VOL 73
-#define LINE2R_2_MONOLOPM_VOL 76
#define PGAL_2_MONOLOPM_VOL 74
-#define PGAR_2_MONOLOPM_VOL 77
#define DACL1_2_MONOLOPM_VOL 75
+#define LINE2R_2_MONOLOPM_VOL 76
+#define PGAR_2_MONOLOPM_VOL 77
#define DACR1_2_MONOLOPM_VOL 78
#define MONOLOPM_CTRL 79
-/* Line Output Plus/Minus control registers */
+/* Class-D speaker driver on tlv320aic3007 */
+#define CLASSD_CTRL 73
+/* Left Line Output Plus/Minus control registers */
#define LINE2L_2_LLOPM_VOL 80
-#define LINE2L_2_RLOPM_VOL 87
-#define LINE2R_2_LLOPM_VOL 83
-#define LINE2R_2_RLOPM_VOL 90
#define PGAL_2_LLOPM_VOL 81
-#define PGAL_2_RLOPM_VOL 88
-#define PGAR_2_LLOPM_VOL 84
-#define PGAR_2_RLOPM_VOL 91
#define DACL1_2_LLOPM_VOL 82
-#define DACL1_2_RLOPM_VOL 89
-#define DACR1_2_RLOPM_VOL 92
+#define LINE2R_2_LLOPM_VOL 83
+#define PGAR_2_LLOPM_VOL 84
#define DACR1_2_LLOPM_VOL 85
#define LLOPM_CTRL 86
+/* Right Line Output Plus/Minus control registers */
+#define LINE2L_2_RLOPM_VOL 87
+#define PGAL_2_RLOPM_VOL 88
+#define DACL1_2_RLOPM_VOL 89
+#define LINE2R_2_RLOPM_VOL 90
+#define PGAR_2_RLOPM_VOL 91
+#define DACR1_2_RLOPM_VOL 92
#define RLOPM_CTRL 93
/* GPIO/IRQ registers */
#define AIC3X_STICKY_IRQ_FLAGS_REG 96
@@ -199,42 +212,6 @@
/* Default input volume */
#define DEFAULT_GAIN 0x20
-/* GPIO API */
-enum {
- AIC3X_GPIO1_FUNC_DISABLED = 0,
- AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1,
- AIC3X_GPIO1_FUNC_CLOCK_MUX = 2,
- AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3,
- AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4,
- AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5,
- AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6,
- AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7,
- AIC3X_GPIO1_FUNC_INPUT = 8,
- AIC3X_GPIO1_FUNC_OUTPUT = 9,
- AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10,
- AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11,
- AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12,
- AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13,
- AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14,
- AIC3X_GPIO1_FUNC_ALL_IRQ = 16
-};
-
-enum {
- AIC3X_GPIO2_FUNC_DISABLED = 0,
- AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2,
- AIC3X_GPIO2_FUNC_INPUT = 3,
- AIC3X_GPIO2_FUNC_OUTPUT = 4,
- AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5,
- AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8,
- AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9,
- AIC3X_GPIO2_FUNC_ALL_IRQ = 10,
- AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11,
- AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12,
- AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13,
- AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14,
- AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15
-};
-
void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
@@ -281,11 +258,4 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
int aic3x_headset_detected(struct snd_soc_codec *codec);
int aic3x_button_pressed(struct snd_soc_codec *codec);
-struct aic3x_setup_data {
- unsigned int gpio_func[2];
-};
-
-extern struct snd_soc_dai aic3x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_aic3x;
-
#endif /* _AIC3X_H */
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 8651b01ed223..c5ab8c805771 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -58,7 +58,7 @@
(1000000000 / ((rate * 1000) / samples))
#define US_TO_SAMPLES(rate, us) \
- (rate / (1000000 / us))
+ (rate / (1000000 / (us < 1000000 ? us : 1000000)))
#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
@@ -66,8 +66,6 @@
static void dac33_calculate_times(struct snd_pcm_substream *substream);
static int dac33_prepare_chip(struct snd_pcm_substream *substream);
-static struct snd_soc_codec *tlv320dac33_codec;
-
enum dac33_state {
DAC33_IDLE = 0,
DAC33_PREFILL,
@@ -93,7 +91,7 @@ struct tlv320dac33_priv {
struct mutex mutex;
struct workqueue_struct *dac33_wq;
struct work_struct work;
- struct snd_soc_codec codec;
+ struct snd_soc_codec *codec;
struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES];
struct snd_pcm_substream *substream;
int power_gpio;
@@ -128,6 +126,8 @@ struct tlv320dac33_priv {
unsigned int uthr;
enum dac33_state state;
+ enum snd_soc_control_type control_type;
+ void *control_data;
};
static const u8 dac33_reg[DAC33_CACHEREGNUM] = {
@@ -200,7 +200,7 @@ static int dac33_read(struct snd_soc_codec *codec, unsigned int reg,
u8 *value)
{
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
- int val;
+ int val, ret = 0;
*value = reg & 0xff;
@@ -210,6 +210,7 @@ static int dac33_read(struct snd_soc_codec *codec, unsigned int reg,
if (val < 0) {
dev_err(codec->dev, "Read failed (%d)\n", val);
value[0] = dac33_read_reg_cache(codec, reg);
+ ret = val;
} else {
value[0] = val;
dac33_write_reg_cache(codec, reg, val);
@@ -218,7 +219,7 @@ static int dac33_read(struct snd_soc_codec *codec, unsigned int reg,
value[0] = dac33_read_reg_cache(codec, reg);
}
- return 0;
+ return ret;
}
static int dac33_write(struct snd_soc_codec *codec, unsigned int reg,
@@ -329,13 +330,18 @@ static void dac33_init_chip(struct snd_soc_codec *codec)
dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL));
}
-static inline void dac33_read_id(struct snd_soc_codec *codec)
+static inline int dac33_read_id(struct snd_soc_codec *codec)
{
+ int i, ret = 0;
u8 reg;
- dac33_read(codec, DAC33_DEVICE_ID_MSB, &reg);
- dac33_read(codec, DAC33_DEVICE_ID_LSB, &reg);
- dac33_read(codec, DAC33_DEVICE_REV_ID, &reg);
+ for (i = 0; i < 3; i++) {
+ ret = dac33_read(codec, DAC33_DEVICE_ID_MSB + i, &reg);
+ if (ret < 0)
+ break;
+ }
+
+ return ret;
}
static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
@@ -524,6 +530,22 @@ static const struct soc_enum dac33_fifo_mode_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts),
dac33_fifo_mode_texts);
+/* L/R Line Output Gain */
+static const char *lr_lineout_gain_texts[] = {
+ "Line -12dB DAC 0dB", "Line -6dB DAC 6dB",
+ "Line 0dB DAC 12dB", "Line 6dB DAC 18dB",
+};
+
+static const struct soc_enum l_lineout_gain_enum =
+ SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0,
+ ARRAY_SIZE(lr_lineout_gain_texts),
+ lr_lineout_gain_texts);
+
+static const struct soc_enum r_lineout_gain_enum =
+ SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0,
+ ARRAY_SIZE(lr_lineout_gain_texts),
+ lr_lineout_gain_texts);
+
/*
* DACL/R digital volume control:
* from 0 dB to -63.5 in 0.5 dB steps
@@ -541,6 +563,8 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = {
DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1),
SOC_DOUBLE_R("Line to Line Out Volume",
DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
+ SOC_ENUM("Left Line Output Gain", l_lineout_gain_enum),
+ SOC_ENUM("Right Line Output Gain", r_lineout_gain_enum),
};
static const struct snd_kcontrol_new dac33_mode_snd_controls[] = {
@@ -650,9 +674,8 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,
static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
{
- struct snd_soc_codec *codec;
-
- codec = &dac33->codec;
+ struct snd_soc_codec *codec = dac33->codec;
+ unsigned int delay;
switch (dac33->fifo_mode) {
case DAC33_FIFO_MODE1:
@@ -668,8 +691,9 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
dac33_write16(codec, DAC33_PREFILL_MSB,
DAC33_THRREG(dac33->alarm_threshold));
/* Enable Alarm Threshold IRQ with a delay */
- udelay(SAMPLES_TO_US(dac33->burst_rate,
- dac33->alarm_threshold));
+ delay = SAMPLES_TO_US(dac33->burst_rate,
+ dac33->alarm_threshold) + 1000;
+ usleep_range(delay, delay + 500);
dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT);
break;
case DAC33_FIFO_MODE7:
@@ -695,9 +719,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33)
{
- struct snd_soc_codec *codec;
-
- codec = &dac33->codec;
+ struct snd_soc_codec *codec = dac33->codec;
switch (dac33->fifo_mode) {
case DAC33_FIFO_MODE1:
@@ -726,7 +748,7 @@ static void dac33_work(struct work_struct *work)
u8 reg;
dac33 = container_of(work, struct tlv320dac33_priv, work);
- codec = &dac33->codec;
+ codec = dac33->codec;
mutex_lock(&dac33->mutex);
switch (dac33->state) {
@@ -771,11 +793,11 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev)
static void dac33_oscwait(struct snd_soc_codec *codec)
{
- int timeout = 20;
+ int timeout = 60;
u8 reg;
do {
- msleep(1);
+ usleep_range(1000, 2000);
dac33_read(codec, DAC33_INT_OSC_STATUS, &reg);
} while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--);
if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL)
@@ -787,8 +809,7 @@ static int dac33_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
/* Stream started, save the substream pointer */
@@ -801,8 +822,7 @@ static void dac33_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
dac33->substream = NULL;
@@ -817,8 +837,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
/* Check parameters for validity */
switch (params_rate(params)) {
@@ -856,8 +875,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
static int dac33_prepare_chip(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
unsigned int oscset, ratioset, pwr_ctrl, reg_tmp;
u8 aictrl_a, aictrl_b, fifoctrl_a;
@@ -1049,8 +1067,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
static void dac33_calculate_times(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
unsigned int period_size = substream->runtime->period_size;
unsigned int rate = substream->runtime->rate;
@@ -1065,6 +1082,9 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
/* Number of samples under i2c latency */
dac33->alarm_threshold = US_TO_SAMPLES(rate,
dac33->mode1_latency);
+ nsample_limit = DAC33_BUFFER_SIZE_SAMPLES -
+ dac33->alarm_threshold;
+
if (dac33->auto_fifo_config) {
if (period_size <= dac33->alarm_threshold)
/*
@@ -1075,6 +1095,8 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
((dac33->alarm_threshold / period_size) +
(dac33->alarm_threshold % period_size ?
1 : 0));
+ else if (period_size > nsample_limit)
+ dac33->nsample = nsample_limit;
else
dac33->nsample = period_size;
} else {
@@ -1086,8 +1108,7 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream)
*/
dac33->nsample_max = substream->runtime->buffer_size -
period_size;
- nsample_limit = DAC33_BUFFER_SIZE_SAMPLES -
- dac33->alarm_threshold;
+
if (dac33->nsample_max > nsample_limit)
dac33->nsample_max = nsample_limit;
@@ -1129,8 +1150,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
@@ -1163,8 +1183,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
unsigned long long t0, t1, t_now;
unsigned int time_delta, uthr;
@@ -1389,24 +1408,52 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
-static int dac33_soc_probe(struct platform_device *pdev)
+static int dac33_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct tlv320dac33_priv *dac33;
+ struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
- BUG_ON(!tlv320dac33_codec);
+ codec->control_data = dac33->control_data;
+ codec->hw_write = (hw_write_t) i2c_master_send;
+ codec->idle_bias_off = 1;
+ dac33->codec = codec;
- codec = tlv320dac33_codec;
- socdev->card->codec = codec;
- dac33 = snd_soc_codec_get_drvdata(codec);
+ /* Read the tlv320dac33 ID registers */
+ ret = dac33_hard_power(codec, 1);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to power up codec: %d\n", ret);
+ goto err_power;
+ }
+ ret = dac33_read_id(codec);
+ dac33_hard_power(codec, 0);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms\n");
- goto pcm_err;
+ dev_err(codec->dev, "Failed to read chip ID: %d\n", ret);
+ ret = -ENODEV;
+ goto err_power;
+ }
+
+ /* Check if the IRQ number is valid and request it */
+ if (dac33->irq >= 0) {
+ ret = request_irq(dac33->irq, dac33_interrupt_handler,
+ IRQF_TRIGGER_RISING | IRQF_DISABLED,
+ codec->name, codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
+ dac33->irq, ret);
+ dac33->irq = -1;
+ }
+ if (dac33->irq != -1) {
+ /* Setup work queue */
+ dac33->dac33_wq =
+ create_singlethread_workqueue("tlv320dac33");
+ if (dac33->dac33_wq == NULL) {
+ free_irq(dac33->irq, codec);
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&dac33->work, dac33_work);
+ }
}
snd_soc_add_controls(codec, dac33_snd_controls,
@@ -1420,56 +1467,51 @@ static int dac33_soc_probe(struct platform_device *pdev)
snd_soc_add_controls(codec, dac33_fifo_snd_controls,
ARRAY_SIZE(dac33_fifo_snd_controls));
}
-
dac33_add_widgets(codec);
- return 0;
-
-pcm_err:
- dac33_hard_power(codec, 0);
+err_power:
return ret;
}
-static int dac33_soc_remove(struct platform_device *pdev)
+static int dac33_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
+ if (dac33->irq >= 0) {
+ free_irq(dac33->irq, dac33->codec);
+ destroy_workqueue(dac33->dac33_wq);
+ }
return 0;
}
-static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state)
+static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int dac33_soc_resume(struct platform_device *pdev)
+static int dac33_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = {
+static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
+ .read = dac33_read_reg_cache,
+ .write = dac33_write_locked,
+ .set_bias_level = dac33_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(dac33_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = dac33_reg,
.probe = dac33_soc_probe,
.remove = dac33_soc_remove,
.suspend = dac33_soc_suspend,
.resume = dac33_soc_resume,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
@@ -1485,8 +1527,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = {
.set_fmt = dac33_set_dai_fmt,
};
-struct snd_soc_dai dac33_dai = {
- .name = "tlv320dac33",
+static struct snd_soc_dai_driver dac33_dai = {
+ .name = "tlv320dac33-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -1495,14 +1537,12 @@ struct snd_soc_dai dac33_dai = {
.formats = DAC33_FORMATS,},
.ops = &dac33_dai_ops,
};
-EXPORT_SYMBOL_GPL(dac33_dai);
static int __devinit dac33_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tlv320dac33_platform_data *pdata;
struct tlv320dac33_priv *dac33;
- struct snd_soc_codec *codec;
int ret, i;
if (client->dev.platform_data == NULL) {
@@ -1515,33 +1555,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
if (dac33 == NULL)
return -ENOMEM;
- codec = &dac33->codec;
- snd_soc_codec_set_drvdata(codec, dac33);
- codec->control_data = client;
-
- mutex_init(&codec->mutex);
+ dac33->control_data = client;
mutex_init(&dac33->mutex);
spin_lock_init(&dac33->lock);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "tlv320dac33";
- codec->owner = THIS_MODULE;
- codec->read = dac33_read_reg_cache;
- codec->write = dac33_write_locked;
- codec->hw_write = (hw_write_t) i2c_master_send;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = dac33_set_bias_level;
- codec->idle_bias_off = 1;
- codec->dai = &dac33_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(dac33_reg);
- codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg),
- GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- ret = -ENOMEM;
- goto error_reg;
- }
i2c_set_clientdata(client, dac33);
@@ -1561,125 +1577,59 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
/* Disable FIFO use by default */
dac33->fifo_mode = DAC33_FIFO_BYPASS;
- tlv320dac33_codec = codec;
-
- codec->dev = &client->dev;
- dac33_dai.dev = codec->dev;
-
/* Check if the reset GPIO number is valid and request it */
if (dac33->power_gpio >= 0) {
ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset");
if (ret < 0) {
- dev_err(codec->dev,
+ dev_err(&client->dev,
"Failed to request reset GPIO (%d)\n",
dac33->power_gpio);
- snd_soc_unregister_dai(&dac33_dai);
- snd_soc_unregister_codec(codec);
- goto error_gpio;
+ goto err_gpio;
}
gpio_direction_output(dac33->power_gpio, 0);
}
- /* Check if the IRQ number is valid and request it */
- if (dac33->irq >= 0) {
- ret = request_irq(dac33->irq, dac33_interrupt_handler,
- IRQF_TRIGGER_RISING | IRQF_DISABLED,
- codec->name, codec);
- if (ret < 0) {
- dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
- dac33->irq, ret);
- dac33->irq = -1;
- }
- if (dac33->irq != -1) {
- /* Setup work queue */
- dac33->dac33_wq =
- create_singlethread_workqueue("tlv320dac33");
- if (dac33->dac33_wq == NULL) {
- free_irq(dac33->irq, &dac33->codec);
- ret = -ENOMEM;
- goto error_wq;
- }
-
- INIT_WORK(&dac33->work, dac33_work);
- }
- }
-
for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++)
dac33->supplies[i].supply = dac33_supply_names[i];
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies),
+ ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies),
dac33->supplies);
if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ dev_err(&client->dev, "Failed to request supplies: %d\n", ret);
goto err_get;
}
- /* Read the tlv320dac33 ID registers */
- ret = dac33_hard_power(codec, 1);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to power up codec: %d\n", ret);
- goto error_codec;
- }
- dac33_read_id(codec);
- dac33_hard_power(codec, 0);
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto error_codec;
- }
-
- ret = snd_soc_register_dai(&dac33_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- snd_soc_unregister_codec(codec);
- goto error_codec;
- }
+ ret = snd_soc_register_codec(&client->dev,
+ &soc_codec_dev_tlv320dac33, &dac33_dai, 1);
+ if (ret < 0)
+ goto err_register;
return ret;
-
-error_codec:
+err_register:
regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
err_get:
- if (dac33->irq >= 0) {
- free_irq(dac33->irq, &dac33->codec);
- destroy_workqueue(dac33->dac33_wq);
- }
-error_wq:
if (dac33->power_gpio >= 0)
gpio_free(dac33->power_gpio);
-error_gpio:
- kfree(codec->reg_cache);
-error_reg:
- tlv320dac33_codec = NULL;
+err_gpio:
kfree(dac33);
-
return ret;
}
static int __devexit dac33_i2c_remove(struct i2c_client *client)
{
- struct tlv320dac33_priv *dac33;
-
- dac33 = i2c_get_clientdata(client);
+ struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);
if (unlikely(dac33->chip_power))
- dac33_hard_power(&dac33->codec, 0);
+ dac33_hard_power(dac33->codec, 0);
if (dac33->power_gpio >= 0)
gpio_free(dac33->power_gpio);
- if (dac33->irq >= 0)
- free_irq(dac33->irq, &dac33->codec);
regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
- destroy_workqueue(dac33->dac33_wq);
- snd_soc_unregister_dai(&dac33_dai);
- snd_soc_unregister_codec(&dac33->codec);
- kfree(dac33->codec.reg_cache);
+ snd_soc_unregister_codec(&client->dev);
kfree(dac33);
- tlv320dac33_codec = NULL;
return 0;
}
@@ -1694,7 +1644,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = {
static struct i2c_driver tlv320dac33_i2c_driver = {
.driver = {
- .name = "tlv320dac33",
+ .name = "tlv320dac33-codec",
.owner = THIS_MODULE,
},
.probe = dac33_i2c_probe,
diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h
index eb8ae07f0bd2..7c318b5da437 100644
--- a/sound/soc/codecs/tlv320dac33.h
+++ b/sound/soc/codecs/tlv320dac33.h
@@ -261,7 +261,4 @@
#define TLV320DAC33_MCLK 0
#define TLV320DAC33_SLEEPCLK 1
-extern struct snd_soc_dai dac33_dai;
-extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33;
-
#endif /* __TLV320DAC33_H */
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 99b70e5978a2..d2c243095673 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -78,8 +78,10 @@ static int tpa6130a2_i2c_write(int reg, u8 value)
if (data->power_state) {
val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value);
- if (val < 0)
+ if (val < 0) {
dev_err(&tpa6130a2_client->dev, "Write failed\n");
+ return val;
+ }
}
/* Either powered on or off, we save the context */
@@ -98,29 +100,34 @@ static u8 tpa6130a2_read(int reg)
return data->regs[reg];
}
-static void tpa6130a2_initialize(void)
+static int tpa6130a2_initialize(void)
{
struct tpa6130a2_data *data;
- int i;
+ int i, ret = 0;
BUG_ON(tpa6130a2_client == NULL);
data = i2c_get_clientdata(tpa6130a2_client);
- for (i = 1; i < TPA6130A2_REG_VERSION; i++)
- tpa6130a2_i2c_write(i, data->regs[i]);
+ for (i = 1; i < TPA6130A2_REG_VERSION; i++) {
+ ret = tpa6130a2_i2c_write(i, data->regs[i]);
+ if (ret < 0)
+ break;
+ }
+
+ return ret;
}
static int tpa6130a2_power(int power)
{
struct tpa6130a2_data *data;
u8 val;
- int ret;
+ int ret = 0;
BUG_ON(tpa6130a2_client == NULL);
data = i2c_get_clientdata(tpa6130a2_client);
mutex_lock(&data->mutex);
- if (power) {
+ if (power && !data->power_state) {
/* Power on */
if (data->power_gpio >= 0)
gpio_set_value(data->power_gpio, 1);
@@ -133,13 +140,22 @@ static int tpa6130a2_power(int power)
}
data->power_state = 1;
- tpa6130a2_initialize();
+ ret = tpa6130a2_initialize();
+ if (ret < 0) {
+ dev_err(&tpa6130a2_client->dev,
+ "Failed to initialize chip\n");
+ if (data->power_gpio >= 0)
+ gpio_set_value(data->power_gpio, 0);
+ regulator_disable(data->supply);
+ data->power_state = 0;
+ goto exit;
+ }
/* Clear SWS */
val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
val &= ~TPA6130A2_SWS;
tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
- } else {
+ } else if (!power && data->power_state) {
/* set SWS */
val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
val |= TPA6130A2_SWS;
@@ -375,7 +391,9 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
{
struct tpa6130a2_data *data;
- BUG_ON(tpa6130a2_client == NULL);
+ if (tpa6130a2_client == NULL)
+ return -ENODEV;
+
data = i2c_get_clientdata(tpa6130a2_client);
snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 7b618bbff884..cbebec6ba1ba 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -36,7 +36,16 @@
#include <sound/initval.h>
#include <sound/tlv.h>
-#include "twl4030.h"
+/* Register descriptions are here */
+#include <linux/mfd/twl4030-codec.h>
+
+/* Shadow register used by the audio driver */
+#define TWL4030_REG_SW_SHADOW 0x4A
+#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
+
+/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
+#define TWL4030_HFL_EN 0x01
+#define TWL4030_HFR_EN 0x02
/*
* twl4030 register cache & default register settings
@@ -277,21 +286,19 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec)
}
-static void twl4030_init_chip(struct platform_device *pdev)
+static void twl4030_init_chip(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct twl4030_setup_data *setup = socdev->codec_data;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev);
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
u8 reg, byte;
int i = 0;
/* Check defaults, if instructed before anything else */
- if (setup && setup->check_defaults)
+ if (pdata && pdata->check_defaults)
twl4030_check_defaults(codec);
/* Reset registers, if no setup data or if instructed to do so */
- if (!setup || (setup && setup->reset_registers))
+ if (!pdata || (pdata && pdata->reset_registers))
twl4030_reset_registers(codec);
/* Refresh APLL_CTL register from HW */
@@ -312,20 +319,14 @@ static void twl4030_init_chip(struct platform_device *pdev)
twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32);
/* Machine dependent setup */
- if (!setup)
+ if (!pdata)
return;
- twl4030->digimic_delay = setup->digimic_delay;
-
- /* Configuration for headset ramp delay from setup data */
- if (setup->sysclk != twl4030->sysclk)
- dev_warn(codec->dev,
- "Mismatch in APLL mclk: %u (configured: %u)\n",
- setup->sysclk, twl4030->sysclk);
+ twl4030->digimic_delay = pdata->digimic_delay;
reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
reg &= ~TWL4030_RAMP_DELAY;
- reg |= (setup->ramp_delay_value << 2);
+ reg |= (pdata->ramp_delay_value << 2);
twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg);
/* initiate offset cancellation */
@@ -333,7 +334,7 @@ static void twl4030_init_chip(struct platform_device *pdev)
reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
reg &= ~TWL4030_OFFSET_CNCL_SEL;
- reg |= setup->offset_cncl_path;
+ reg |= pdata->offset_cncl_path;
twl4030_write(codec, TWL4030_REG_ANAMICL,
reg | TWL4030_CNCL_OFFSET_START);
@@ -718,9 +719,7 @@ static int aif_event(struct snd_soc_dapm_widget *w,
static void headset_ramp(struct snd_soc_codec *codec, int ramp)
{
- struct snd_soc_device *socdev = codec->socdev;
- struct twl4030_setup_data *setup = socdev->codec_data;
-
+ struct twl4030_codec_audio_data *pdata = codec->dev->platform_data;
unsigned char hs_gain, hs_pop;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
/* Base values for ramp delay calculation: 2^19 - 2^26 */
@@ -732,9 +731,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
/* Enable external mute control, this dramatically reduces
* the pop-noise */
- if (setup && setup->hs_extmute) {
- if (setup->set_hs_extmute) {
- setup->set_hs_extmute(1);
+ if (pdata && pdata->hs_extmute) {
+ if (pdata->set_hs_extmute) {
+ pdata->set_hs_extmute(1);
} else {
hs_pop |= TWL4030_EXTMUTE;
twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
@@ -772,9 +771,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
}
/* Disable external mute */
- if (setup && setup->hs_extmute) {
- if (setup->set_hs_extmute) {
- setup->set_hs_extmute(0);
+ if (pdata && pdata->hs_extmute) {
+ if (pdata->set_hs_extmute) {
+ pdata->set_hs_extmute(0);
} else {
hs_pop &= ~TWL4030_EXTMUTE;
twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
@@ -1707,8 +1706,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
if (twl4030->master_substream) {
@@ -1738,8 +1736,7 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
if (twl4030->master_substream == substream)
@@ -1764,8 +1761,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
u8 mode, old_mode, format, old_format;
@@ -1999,8 +1995,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
u8 mode;
@@ -2033,8 +2028,7 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
/* Enable voice digital filters */
twl4030_voice_enable(codec, substream->stream, 0);
@@ -2044,8 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
u8 old_mode, mode;
@@ -2175,7 +2168,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
-static struct snd_soc_dai_ops twl4030_dai_ops = {
+static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
.startup = twl4030_startup,
.shutdown = twl4030_shutdown,
.hw_params = twl4030_hw_params,
@@ -2193,9 +2186,9 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
.set_tristate = twl4030_voice_set_tristate,
};
-struct snd_soc_dai twl4030_dai[] = {
+static struct snd_soc_dai_driver twl4030_dai[] = {
{
- .name = "twl4030",
+ .name = "twl4030-hifi",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 2,
@@ -2208,10 +2201,10 @@ struct snd_soc_dai twl4030_dai[] = {
.channels_max = 4,
.rates = TWL4030_RATES,
.formats = TWL4030_FORMATS,},
- .ops = &twl4030_dai_ops,
+ .ops = &twl4030_dai_hifi_ops,
},
{
- .name = "twl4030 Voice",
+ .name = "twl4030-voice",
.playback = {
.stream_name = "Voice Playback",
.channels_min = 1,
@@ -2227,164 +2220,91 @@ struct snd_soc_dai twl4030_dai[] = {
.ops = &twl4030_dai_voice_ops,
},
};
-EXPORT_SYMBOL_GPL(twl4030_dai);
-static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state)
+static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
return 0;
}
-static int twl4030_soc_resume(struct platform_device *pdev)
+static int twl4030_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
-static struct snd_soc_codec *twl4030_codec;
-
-static int twl4030_soc_probe(struct platform_device *pdev)
+static int twl4030_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret;
-
- BUG_ON(!twl4030_codec);
-
- codec = twl4030_codec;
- socdev->card->codec = codec;
-
- twl4030_init_chip(pdev);
+ struct twl4030_priv *twl4030;
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to create pcms\n");
- return ret;
+ twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
+ if (twl4030 == NULL) {
+ printk("Can not allocate memroy\n");
+ return -ENOMEM;
}
+ snd_soc_codec_set_drvdata(codec, twl4030);
+ /* Set the defaults, and power up the codec */
+ twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
+ codec->idle_bias_off = 1;
+
+ twl4030_init_chip(codec);
snd_soc_add_controls(codec, twl4030_snd_controls,
ARRAY_SIZE(twl4030_snd_controls));
twl4030_add_widgets(codec);
-
return 0;
}
-static int twl4030_soc_remove(struct platform_device *pdev)
+static int twl4030_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
/* Reset registers to their chip default before leaving */
twl4030_reset_registers(codec);
twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
+ .probe = twl4030_soc_probe,
+ .remove = twl4030_soc_remove,
+ .suspend = twl4030_soc_suspend,
+ .resume = twl4030_soc_resume,
+ .read = twl4030_read_reg_cache,
+ .write = twl4030_write,
+ .set_bias_level = twl4030_set_bias_level,
+ .reg_cache_size = sizeof(twl4030_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = twl4030_reg,
+};
+
static int __devinit twl4030_codec_probe(struct platform_device *pdev)
{
struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data;
- struct snd_soc_codec *codec;
- struct twl4030_priv *twl4030;
- int ret;
if (!pdata) {
dev_err(&pdev->dev, "platform_data is missing\n");
return -EINVAL;
}
- twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
- if (twl4030 == NULL) {
- dev_err(&pdev->dev, "Can not allocate memroy\n");
- return -ENOMEM;
- }
-
- codec = &twl4030->codec;
- snd_soc_codec_set_drvdata(codec, twl4030);
- codec->dev = &pdev->dev;
- twl4030_dai[0].dev = &pdev->dev;
- twl4030_dai[1].dev = &pdev->dev;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "twl4030";
- codec->owner = THIS_MODULE;
- codec->read = twl4030_read_reg_cache;
- codec->write = twl4030_write;
- codec->set_bias_level = twl4030_set_bias_level;
- codec->idle_bias_off = 1;
- codec->dai = twl4030_dai;
- codec->num_dai = ARRAY_SIZE(twl4030_dai);
- codec->reg_cache_size = sizeof(twl4030_reg);
- codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
- GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- ret = -ENOMEM;
- goto error_cache;
- }
-
- platform_set_drvdata(pdev, twl4030);
- twl4030_codec = codec;
-
- /* Set the defaults, and power up the codec */
- twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
- codec->bias_level = SND_SOC_BIAS_OFF;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto error_codec;
- }
-
- ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
- snd_soc_unregister_codec(codec);
- goto error_codec;
- }
-
- return 0;
-
-error_codec:
- twl4030_codec_enable(codec, 0);
- kfree(codec->reg_cache);
-error_cache:
- kfree(twl4030);
- return ret;
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030,
+ twl4030_dai, ARRAY_SIZE(twl4030_dai));
}
static int __devexit twl4030_codec_remove(struct platform_device *pdev)
{
- struct twl4030_priv *twl4030 = platform_get_drvdata(pdev);
+ struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev);
- snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
- snd_soc_unregister_codec(&twl4030->codec);
- kfree(twl4030->codec.reg_cache);
+ snd_soc_unregister_codec(&pdev->dev);
kfree(twl4030);
-
- twl4030_codec = NULL;
return 0;
}
-MODULE_ALIAS("platform:twl4030_codec_audio");
+MODULE_ALIAS("platform:twl4030-codec");
static struct platform_driver twl4030_codec_driver = {
.probe = twl4030_codec_probe,
.remove = __devexit_p(twl4030_codec_remove),
.driver = {
- .name = "twl4030_codec_audio",
+ .name = "twl4030-codec",
.owner = THIS_MODULE,
},
};
@@ -2401,14 +2321,6 @@ static void __exit twl4030_exit(void)
}
module_exit(twl4030_exit);
-struct snd_soc_codec_device soc_codec_dev_twl4030 = {
- .probe = twl4030_soc_probe,
- .remove = twl4030_soc_remove,
- .suspend = twl4030_soc_suspend,
- .resume = twl4030_soc_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
-
MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
MODULE_AUTHOR("Steve Sakoman");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
deleted file mode 100644
index 6c57430f6e24..000000000000
--- a/sound/soc/codecs/twl4030.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * ALSA SoC TWL4030 codec driver
- *
- * Author: Steve Sakoman <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __TWL4030_AUDIO_H__
-#define __TWL4030_AUDIO_H__
-
-/* Register descriptions are here */
-#include <linux/mfd/twl4030-codec.h>
-
-/* Shadow register used by the audio driver */
-#define TWL4030_REG_SW_SHADOW 0x4A
-#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
-
-/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
-#define TWL4030_HFL_EN 0x01
-#define TWL4030_HFR_EN 0x02
-
-#define TWL4030_DAI_HIFI 0
-#define TWL4030_DAI_VOICE 1
-
-extern struct snd_soc_dai twl4030_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_twl4030;
-
-struct twl4030_setup_data {
- unsigned int ramp_delay_value;
- unsigned int digimic_delay; /* in ms */
- unsigned int sysclk;
- unsigned int offset_cncl_path;
- unsigned int check_defaults:1;
- unsigned int reset_registers:1;
- unsigned int hs_extmute:1;
- void (*set_hs_extmute)(int mute);
-};
-
-#endif /* End of __TWL4030_AUDIO_H__ */
-
-
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 64a807f1a8a1..10f6e5214511 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -45,7 +45,6 @@
/* codec private data */
struct twl6040_data {
- struct snd_soc_codec codec;
int audpwron;
int naudint;
int codec_powered;
@@ -770,8 +769,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
if (!priv->sysclk) {
@@ -803,8 +801,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
u8 lppllctl;
int rate;
@@ -839,8 +836,7 @@ static int twl6040_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
switch (cmd) {
@@ -978,8 +974,8 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
.set_sysclk = twl6040_set_dai_sysclk,
};
-struct snd_soc_dai twl6040_dai = {
- .name = "twl6040",
+static struct snd_soc_dai_driver twl6040_dai = {
+ .name = "twl6040-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -996,24 +992,17 @@ struct snd_soc_dai twl6040_dai = {
},
.ops = &twl6040_dai_ops,
};
-EXPORT_SYMBOL_GPL(twl6040_dai);
#ifdef CONFIG_PM
-static int twl6040_suspend(struct platform_device *pdev, pm_message_t state)
+static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int twl6040_resume(struct platform_device *pdev)
+static int twl6040_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -1023,68 +1012,9 @@ static int twl6040_resume(struct platform_device *pdev)
#define twl6040_resume NULL
#endif
-static struct snd_soc_codec *twl6040_codec;
-
-static int twl6040_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- BUG_ON(!twl6040_codec);
-
- codec = twl6040_codec;
- socdev->card->codec = codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to create pcms\n");
- return ret;
- }
-
- snd_soc_add_controls(codec, twl6040_snd_controls,
- ARRAY_SIZE(twl6040_snd_controls));
- twl6040_add_widgets(codec);
-
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to register card\n");
- goto card_err;
- }
-
- return ret;
-
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
- return ret;
-}
-
-static int twl6040_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_twl6040 = {
- .probe = twl6040_probe,
- .remove = twl6040_remove,
- .suspend = twl6040_suspend,
- .resume = twl6040_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040);
-
-static int __devinit twl6040_codec_probe(struct platform_device *pdev)
+static int twl6040_probe(struct snd_soc_codec *codec)
{
- struct twl4030_codec_data *twl_codec = pdev->dev.platform_data;
- struct snd_soc_codec *codec;
+ struct twl4030_codec_data *twl_codec = codec->dev->platform_data;
struct twl6040_data *priv;
int audpwron, naudint;
int ret = 0;
@@ -1092,6 +1022,7 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
+ snd_soc_codec_set_drvdata(codec, priv);
if (twl_codec) {
audpwron = twl_codec->audpwron_gpio;
@@ -1104,29 +1035,6 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
priv->audpwron = audpwron;
priv->naudint = naudint;
- codec = &priv->codec;
- codec->dev = &pdev->dev;
- twl6040_dai.dev = &pdev->dev;
-
- codec->name = "twl6040";
- codec->owner = THIS_MODULE;
- codec->read = twl6040_read_reg_cache;
- codec->write = twl6040_write;
- codec->set_bias_level = twl6040_set_bias_level;
- snd_soc_codec_set_drvdata(codec, priv);
- codec->dai = &twl6040_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(twl6040_reg);
- codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg),
- GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- ret = -ENOMEM;
- goto cache_err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
init_completion(&priv->ready);
if (gpio_is_valid(audpwron)) {
@@ -1169,23 +1077,12 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
if (ret)
goto irq_err;
- ret = snd_soc_register_codec(codec);
- if (ret)
- goto reg_err;
-
- twl6040_codec = codec;
-
- ret = snd_soc_register_dai(&twl6040_dai);
- if (ret)
- goto dai_err;
+ snd_soc_add_controls(codec, twl6040_snd_controls,
+ ARRAY_SIZE(twl6040_snd_controls));
+ twl6040_add_widgets(codec);
return 0;
-dai_err:
- snd_soc_unregister_codec(codec);
- twl6040_codec = NULL;
-reg_err:
- twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
irq_err:
if (naudint)
free_irq(naudint, codec);
@@ -1193,36 +1090,57 @@ gpio2_err:
if (gpio_is_valid(audpwron))
gpio_free(audpwron);
gpio1_err:
- kfree(codec->reg_cache);
-cache_err:
kfree(priv);
return ret;
}
-static int __devexit twl6040_codec_remove(struct platform_device *pdev)
+static int twl6040_remove(struct snd_soc_codec *codec)
{
- struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec);
+ struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int audpwron = priv->audpwron;
int naudint = priv->naudint;
+ twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
if (gpio_is_valid(audpwron))
gpio_free(audpwron);
if (naudint)
- free_irq(naudint, twl6040_codec);
+ free_irq(naudint, codec);
- snd_soc_unregister_dai(&twl6040_dai);
- snd_soc_unregister_codec(twl6040_codec);
+ kfree(priv);
- kfree(twl6040_codec);
- twl6040_codec = NULL;
+ return 0;
+}
+static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
+ .probe = twl6040_probe,
+ .remove = twl6040_remove,
+ .suspend = twl6040_suspend,
+ .resume = twl6040_resume,
+ .read = twl6040_read_reg_cache,
+ .write = twl6040_write,
+ .set_bias_level = twl6040_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(twl6040_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = twl6040_reg,
+};
+
+static int __devinit twl6040_codec_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_twl6040, &twl6040_dai, 1);
+}
+
+static int __devexit twl6040_codec_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
static struct platform_driver twl6040_codec_driver = {
.driver = {
- .name = "twl6040_codec",
+ .name = "twl6040-codec",
.owner = THIS_MODULE,
},
.probe = twl6040_codec_probe,
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index c472070a1da2..f7c77fa58a3c 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -135,7 +135,4 @@
#define TWL6040_HPPLL_ID 1
#define TWL6040_LPPLL_ID 2
-extern struct snd_soc_dai twl6040_dai;
-extern struct snd_soc_codec_device soc_codec_dev_twl6040;
-
#endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index f3b4c1d6a82d..464f0cfa4c7a 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -161,8 +161,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec =rtd->codec;
struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
struct snd_pcm_runtime *master_runtime;
@@ -194,8 +193,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
if (uda134x->master_substream == substream)
@@ -209,8 +207,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
u8 hw_params;
@@ -364,7 +361,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
pd->power(1);
/* Sync reg_cache with the hardware */
for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
- codec->write(codec, i, *cache++);
+ codec->driver->write(codec, i, *cache++);
}
break;
case SND_SOC_BIAS_STANDBY:
@@ -465,8 +462,8 @@ static struct snd_soc_dai_ops uda134x_dai_ops = {
.set_fmt = uda134x_set_dai_fmt,
};
-struct snd_soc_dai uda134x_dai = {
- .name = "UDA134X",
+static struct snd_soc_dai_driver uda134x_dai = {
+ .name = "uda134x-hifi",
/* playback capabilities */
.playback = {
.stream_name = "Playback",
@@ -486,27 +483,21 @@ struct snd_soc_dai uda134x_dai = {
/* pcm operations */
.ops = &uda134x_dai_ops,
};
-EXPORT_SYMBOL(uda134x_dai);
-
-static int uda134x_soc_probe(struct platform_device *pdev)
+static int uda134x_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
struct uda134x_priv *uda134x;
- void *codec_setup_data = socdev->codec_data;
- int ret = -ENOMEM;
- struct uda134x_platform_data *pd;
+ struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev);
+ int ret;
printk(KERN_INFO "UDA134X SoC Audio Codec\n");
- if (!codec_setup_data) {
+ if (!pd) {
printk(KERN_ERR "UDA134X SoC codec: "
"missing L3 bitbang function\n");
return -ENODEV;
}
- pd = codec_setup_data;
switch (pd->model) {
case UDA134X_UDA1340:
case UDA134X_UDA1341:
@@ -520,58 +511,22 @@ static int uda134x_soc_probe(struct platform_device *pdev)
return -EINVAL;
}
- socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (socdev->card->codec == NULL)
- return ret;
-
- codec = socdev->card->codec;
-
uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
if (uda134x == NULL)
- goto priv_err;
+ return -ENOMEM;
snd_soc_codec_set_drvdata(codec, uda134x);
- codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
- GFP_KERNEL);
- if (codec->reg_cache == NULL)
- goto reg_err;
-
- mutex_init(&codec->mutex);
-
- codec->reg_cache_size = sizeof(uda134x_reg);
- codec->reg_cache_step = 1;
-
- codec->name = "UDA134X";
- codec->owner = THIS_MODULE;
- codec->dai = &uda134x_dai;
- codec->num_dai = 1;
- codec->read = uda134x_read_reg_cache;
- codec->write = uda134x_write;
-
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->control_data = codec_setup_data;
+ codec->control_data = pd;
if (pd->power)
pd->power(1);
uda134x_reset(codec);
- if (pd->is_powered_on_standby) {
- codec->set_bias_level = NULL;
+ if (pd->is_powered_on_standby)
uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
- } else {
- codec->set_bias_level = uda134x_set_bias_level;
+ else
uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- }
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "UDA134X: failed to register pcms\n");
- goto pcm_err;
- }
switch (pd->model) {
case UDA134X_UDA1340:
@@ -590,61 +545,42 @@ static int uda134x_soc_probe(struct platform_device *pdev)
default:
printk(KERN_ERR "%s unknown codec type: %d",
__func__, pd->model);
- return -EINVAL;
+ kfree(uda134x);
+ return -EINVAL;
}
if (ret < 0) {
printk(KERN_ERR "UDA134X: failed to register controls\n");
- goto pcm_err;
+ kfree(uda134x);
+ return ret;
}
return 0;
-
-pcm_err:
- kfree(codec->reg_cache);
-reg_err:
- kfree(snd_soc_codec_get_drvdata(codec));
-priv_err:
- kfree(codec);
- return ret;
}
/* power down chip */
-static int uda134x_soc_remove(struct platform_device *pdev)
+static int uda134x_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec->reg_cache);
- kfree(codec);
-
+ kfree(uda134x);
return 0;
}
#if defined(CONFIG_PM)
-static int uda134x_soc_suspend(struct platform_device *pdev,
+static int uda134x_soc_suspend(struct snd_soc_codec *codec,
pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int uda134x_soc_resume(struct platform_device *pdev)
+static int uda134x_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
return 0;
@@ -654,25 +590,54 @@ static int uda134x_soc_resume(struct platform_device *pdev)
#define uda134x_soc_resume NULL
#endif /* CONFIG_PM */
-struct snd_soc_codec_device soc_codec_dev_uda134x = {
+static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
.probe = uda134x_soc_probe,
.remove = uda134x_soc_remove,
.suspend = uda134x_soc_suspend,
.resume = uda134x_soc_resume,
+ .reg_cache_size = sizeof(uda134x_reg),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = uda134x_reg,
+ .reg_cache_step = 1,
+ .read = uda134x_read_reg_cache,
+ .write = uda134x_write,
+#ifdef POWER_OFF_ON_STANDBY
+ .set_bias_level = uda134x_set_bias_level,
+#endif
+};
+
+static int __devinit uda134x_codec_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_uda134x, &uda134x_dai, 1);
+}
+
+static int __devexit uda134x_codec_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver uda134x_codec_driver = {
+ .driver = {
+ .name = "uda134x-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = uda134x_codec_probe,
+ .remove = __devexit_p(uda134x_codec_remove),
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
-static int __init uda134x_init(void)
+static int __init uda134x_codec_init(void)
{
- return snd_soc_register_dai(&uda134x_dai);
+ return platform_driver_register(&uda134x_codec_driver);
}
-module_init(uda134x_init);
+module_init(uda134x_codec_init);
-static void __exit uda134x_exit(void)
+static void __exit uda134x_codec_exit(void)
{
- snd_soc_unregister_dai(&uda134x_dai);
+ platform_driver_unregister(&uda134x_codec_driver);
}
-module_exit(uda134x_exit);
+module_exit(uda134x_codec_exit);
MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h
index 205f03b3eaf8..9faae06972b3 100644
--- a/sound/soc/codecs/uda134x.h
+++ b/sound/soc/codecs/uda134x.h
@@ -31,7 +31,4 @@
#define STATUS0_DAIFMT_MASK (~(7<<1))
#define STATUS0_SYSCLK_MASK (~(3<<4))
-extern struct snd_soc_dai uda134x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_uda134x;
-
#endif
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 2f925a27dcde..0c6c725736c6 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -33,14 +33,13 @@
#include "uda1380.h"
-static struct snd_soc_codec *uda1380_codec;
-
/* codec private data */
struct uda1380_priv {
- struct snd_soc_codec codec;
+ struct snd_soc_codec *codec;
u16 reg_cache[UDA1380_CACHEREGNUM];
unsigned int dac_clk;
struct work_struct work;
+ void *control_data;
};
/*
@@ -131,10 +130,51 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
return -EIO;
}
-#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0)
+static void uda1380_sync_cache(struct snd_soc_codec *codec)
+{
+ int reg;
+ u8 data[3];
+ u16 *cache = codec->reg_cache;
+
+ /* Sync reg_cache with the hardware */
+ for (reg = 0; reg < UDA1380_MVOL; reg++) {
+ data[0] = reg;
+ data[1] = (cache[reg] & 0xff00) >> 8;
+ data[2] = cache[reg] & 0x00ff;
+ if (codec->hw_write(codec->control_data, data, 3) != 3)
+ dev_err(codec->dev, "%s: write to reg 0x%x failed\n",
+ __func__, reg);
+ }
+}
+
+static int uda1380_reset(struct snd_soc_codec *codec)
+{
+ struct uda1380_platform_data *pdata = codec->dev->platform_data;
+
+ if (gpio_is_valid(pdata->gpio_reset)) {
+ gpio_set_value(pdata->gpio_reset, 1);
+ mdelay(1);
+ gpio_set_value(pdata->gpio_reset, 0);
+ } else {
+ u8 data[3];
+
+ data[0] = UDA1380_RESET;
+ data[1] = 0;
+ data[2] = 0;
+
+ if (codec->hw_write(codec->control_data, data, 3) != 3) {
+ dev_err(codec->dev, "%s: failed\n", __func__);
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
static void uda1380_flush_work(struct work_struct *work)
{
+ struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work);
+ struct snd_soc_codec *uda1380_codec = uda1380->codec;
int bit, reg;
for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
@@ -145,6 +185,7 @@ static void uda1380_flush_work(struct work_struct *work)
uda1380_read_reg_cache(uda1380_codec, reg));
clear_bit(bit, &uda1380_cache_dirty);
}
+
}
/* declarations of ALSA reg_elem_REAL controls */
@@ -474,8 +515,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
@@ -501,8 +541,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
/* set WSPLL power and divider if running from this clock */
@@ -540,8 +579,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
/* shut down WSPLL power if running from this clock */
@@ -562,18 +600,41 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
int pm = uda1380_read_reg_cache(codec, UDA1380_PM);
+ int reg;
+ struct uda1380_platform_data *pdata = codec->dev->platform_data;
+
+ if (codec->bias_level == level)
+ return 0;
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
+ /* ADC, DAC on */
uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm);
break;
case SND_SOC_BIAS_STANDBY:
- uda1380_write(codec, UDA1380_PM, R02_PON_BIAS);
- break;
- case SND_SOC_BIAS_OFF:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ if (gpio_is_valid(pdata->gpio_power)) {
+ gpio_set_value(pdata->gpio_power, 1);
+ mdelay(1);
+ uda1380_reset(codec);
+ }
+
+ uda1380_sync_cache(codec);
+ }
uda1380_write(codec, UDA1380_PM, 0x0);
break;
+ case SND_SOC_BIAS_OFF:
+ if (!gpio_is_valid(pdata->gpio_power))
+ break;
+
+ gpio_set_value(pdata->gpio_power, 0);
+
+ /* Mark mixer regs cache dirty to sync them with
+ * codec regs on power on.
+ */
+ for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++)
+ set_bit(reg - 0x10, &uda1380_cache_dirty);
}
codec->bias_level = level;
return 0;
@@ -604,9 +665,9 @@ static struct snd_soc_dai_ops uda1380_dai_ops_capture = {
.set_fmt = uda1380_set_dai_fmt_capture,
};
-struct snd_soc_dai uda1380_dai[] = {
+static struct snd_soc_dai_driver uda1380_dai[] = {
{
- .name = "UDA1380",
+ .name = "uda1380-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -622,7 +683,7 @@ struct snd_soc_dai uda1380_dai[] = {
.ops = &uda1380_dai_ops,
},
{ /* playback only - dual interface */
- .name = "UDA1380",
+ .name = "uda1380-hifi-playback",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -633,7 +694,7 @@ struct snd_soc_dai uda1380_dai[] = {
.ops = &uda1380_dai_ops_playback,
},
{ /* capture only - dual interface*/
- .name = "UDA1380",
+ .name = "uda1380-hifi-capture",
.capture = {
.stream_name = "Capture",
.channels_min = 1,
@@ -644,67 +705,69 @@ struct snd_soc_dai uda1380_dai[] = {
.ops = &uda1380_dai_ops_capture,
},
};
-EXPORT_SYMBOL_GPL(uda1380_dai);
-static int uda1380_suspend(struct platform_device *pdev, pm_message_t state)
+static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int uda1380_resume(struct platform_device *pdev)
+static int uda1380_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(uda1380_reg); i++) {
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
-static int uda1380_probe(struct platform_device *pdev)
+static int uda1380_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct uda1380_platform_data *pdata;
- int ret = 0;
+ struct uda1380_platform_data *pdata =codec->dev->platform_data;
+ struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
+ int ret;
- if (uda1380_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
+ uda1380->codec = codec;
+
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ codec->control_data = uda1380->control_data;
+
+ if (!pdata)
+ return -EINVAL;
- socdev->card->codec = uda1380_codec;
- codec = uda1380_codec;
- pdata = codec->dev->platform_data;
+ if (gpio_is_valid(pdata->gpio_reset)) {
+ ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
+ if (ret)
+ goto err_out;
+ ret = gpio_direction_output(pdata->gpio_reset, 0);
+ if (ret)
+ goto err_gpio_reset_conf;
+ }
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
+ if (gpio_is_valid(pdata->gpio_power)) {
+ ret = gpio_request(pdata->gpio_power, "uda1380 power");
+ if (ret)
+ goto err_gpio;
+ ret = gpio_direction_output(pdata->gpio_power, 0);
+ if (ret)
+ goto err_gpio_power_conf;
+ } else {
+ ret = uda1380_reset(codec);
+ if (ret) {
+ dev_err(codec->dev, "Failed to issue reset\n");
+ goto err_reset;
+ }
}
+ INIT_WORK(&uda1380->work, uda1380_flush_work);
+
/* power on device */
uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* set clock input */
switch (pdata->dac_clk) {
case UDA1380_DAC_CLK_SYSCLK:
- uda1380_write(codec, UDA1380_CLK, 0);
+ uda1380_write_reg_cache(codec, UDA1380_CLK, 0);
break;
case UDA1380_DAC_CLK_WSPLL:
- uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK);
+ uda1380_write_reg_cache(codec, UDA1380_CLK,
+ R00_DAC_CLK);
break;
}
@@ -712,167 +775,73 @@ static int uda1380_probe(struct platform_device *pdev)
ARRAY_SIZE(uda1380_snd_controls));
uda1380_add_widgets(codec);
- return ret;
-
-pcm_err:
- return ret;
-}
-
-/* power down chip */
-static int uda1380_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec->control_data)
- uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_uda1380 = {
- .probe = uda1380_probe,
- .remove = uda1380_remove,
- .suspend = uda1380_suspend,
- .resume = uda1380_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
-
-static int uda1380_register(struct uda1380_priv *uda1380)
-{
- int ret, i;
- struct snd_soc_codec *codec = &uda1380->codec;
- struct uda1380_platform_data *pdata = codec->dev->platform_data;
-
- if (uda1380_codec) {
- dev_err(codec->dev, "Another UDA1380 is registered\n");
- return -EINVAL;
- }
-
- if (!pdata || !pdata->gpio_power || !pdata->gpio_reset)
- return -EINVAL;
-
- ret = gpio_request(pdata->gpio_power, "uda1380 power");
- if (ret)
- goto err_out;
- ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
- if (ret)
- goto err_gpio;
-
- gpio_direction_output(pdata->gpio_power, 1);
-
- /* we may need to have the clock running here - pH5 */
- gpio_direction_output(pdata->gpio_reset, 1);
- udelay(5);
- gpio_set_value(pdata->gpio_reset, 0);
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, uda1380);
- codec->name = "UDA1380";
- codec->owner = THIS_MODULE;
- codec->read = uda1380_read_reg_cache;
- codec->write = uda1380_write;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = uda1380_set_bias_level;
- codec->dai = uda1380_dai;
- codec->num_dai = ARRAY_SIZE(uda1380_dai);
- codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
- codec->reg_cache = &uda1380->reg_cache;
- codec->reg_cache_step = 1;
-
- memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg));
-
- ret = uda1380_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- goto err_reset;
- }
-
- INIT_WORK(&uda1380->work, uda1380_flush_work);
- for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++)
- uda1380_dai[i].dev = codec->dev;
-
- uda1380_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err_reset;
- }
-
- ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
- goto err_dai;
- }
-
- return 0;
-
-err_dai:
- snd_soc_unregister_codec(codec);
err_reset:
- gpio_set_value(pdata->gpio_power, 0);
- gpio_free(pdata->gpio_reset);
+err_gpio_power_conf:
+ if (gpio_is_valid(pdata->gpio_power))
+ gpio_free(pdata->gpio_power);
+
+err_gpio_reset_conf:
err_gpio:
- gpio_free(pdata->gpio_power);
+ if (gpio_is_valid(pdata->gpio_reset))
+ gpio_free(pdata->gpio_reset);
err_out:
return ret;
}
-static void uda1380_unregister(struct uda1380_priv *uda1380)
+/* power down chip */
+static int uda1380_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = &uda1380->codec;
- struct uda1380_platform_data *pdata = codec->dev->platform_data;
+ struct uda1380_platform_data *pdata =codec->dev->platform_data;
- snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
- snd_soc_unregister_codec(&uda1380->codec);
+ uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
- gpio_set_value(pdata->gpio_power, 0);
gpio_free(pdata->gpio_reset);
gpio_free(pdata->gpio_power);
- kfree(uda1380);
- uda1380_codec = NULL;
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
+ .probe = uda1380_probe,
+ .remove = uda1380_remove,
+ .suspend = uda1380_suspend,
+ .resume = uda1380_resume,
+ .read = uda1380_read_reg_cache,
+ .write = uda1380_write,
+ .set_bias_level = uda1380_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(uda1380_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = uda1380_reg,
+ .reg_cache_step = 1,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct uda1380_priv *uda1380;
- struct snd_soc_codec *codec;
int ret;
uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);
if (uda1380 == NULL)
return -ENOMEM;
- codec = &uda1380->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
i2c_set_clientdata(i2c, uda1380);
- codec->control_data = i2c;
+ uda1380->control_data = i2c;
- codec->dev = &i2c->dev;
-
- ret = uda1380_register(uda1380);
- if (ret != 0)
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai));
+ if (ret < 0)
kfree(uda1380);
-
return ret;
}
static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
{
- struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c);
- uda1380_unregister(uda1380);
+ snd_soc_unregister_codec(&i2c->dev);
+ kfree(i2c_get_clientdata(i2c));
return 0;
}
@@ -884,7 +853,7 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
static struct i2c_driver uda1380_i2c_driver = {
.driver = {
- .name = "UDA1380 I2C Codec",
+ .name = "uda1380-codec",
.owner = THIS_MODULE,
},
.probe = uda1380_i2c_probe,
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h
index 9cefa8a54770..942e3927c72b 100644
--- a/sound/soc/codecs/uda1380.h
+++ b/sound/soc/codecs/uda1380.h
@@ -76,7 +76,4 @@
#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */
#define UDA1380_DAI_CAPTURE 2 /* capture DAI */
-extern struct snd_soc_dai uda1380_dai[3];
-extern struct snd_soc_codec_device soc_codec_dev_uda1380;
-
#endif /* _UDA1380_H */
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
new file mode 100644
index 000000000000..0c47c788ccdf
--- /dev/null
+++ b/sound/soc/codecs/wl1273.c
@@ -0,0 +1,528 @@
+/*
+ * ALSA SoC WL1273 codec driver
+ *
+ * Author: Matti Aaltonen, <matti.j.aaltonen@nokia.com>
+ *
+ * Copyright: (C) 2010 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/mfd/wl1273-core.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "wl1273.h"
+
+enum wl1273_mode { WL1273_MODE_BT, WL1273_MODE_FM_RX, WL1273_MODE_FM_TX };
+
+/* codec private data */
+struct wl1273_priv {
+ enum wl1273_mode mode;
+ struct wl1273_core *core;
+ unsigned int channels;
+};
+
+static int snd_wl1273_fm_set_i2s_mode(struct wl1273_core *core,
+ int rate, int width)
+{
+ struct device *dev = &core->i2c_dev->dev;
+ int r = 0;
+ u16 mode;
+
+ dev_dbg(dev, "rate: %d\n", rate);
+ dev_dbg(dev, "width: %d\n", width);
+
+ mutex_lock(&core->lock);
+
+ mode = core->i2s_mode & ~WL1273_IS2_WIDTH & ~WL1273_IS2_RATE;
+
+ switch (rate) {
+ case 48000:
+ mode |= WL1273_IS2_RATE_48K;
+ break;
+ case 44100:
+ mode |= WL1273_IS2_RATE_44_1K;
+ break;
+ case 32000:
+ mode |= WL1273_IS2_RATE_32K;
+ break;
+ case 22050:
+ mode |= WL1273_IS2_RATE_22_05K;
+ break;
+ case 16000:
+ mode |= WL1273_IS2_RATE_16K;
+ break;
+ case 12000:
+ mode |= WL1273_IS2_RATE_12K;
+ break;
+ case 11025:
+ mode |= WL1273_IS2_RATE_11_025;
+ break;
+ case 8000:
+ mode |= WL1273_IS2_RATE_8K;
+ break;
+ default:
+ dev_err(dev, "Sampling rate: %d not supported\n", rate);
+ r = -EINVAL;
+ goto out;
+ }
+
+ switch (width) {
+ case 16:
+ mode |= WL1273_IS2_WIDTH_32;
+ break;
+ case 20:
+ mode |= WL1273_IS2_WIDTH_40;
+ break;
+ case 24:
+ mode |= WL1273_IS2_WIDTH_48;
+ break;
+ case 25:
+ mode |= WL1273_IS2_WIDTH_50;
+ break;
+ case 30:
+ mode |= WL1273_IS2_WIDTH_60;
+ break;
+ case 32:
+ mode |= WL1273_IS2_WIDTH_64;
+ break;
+ case 40:
+ mode |= WL1273_IS2_WIDTH_80;
+ break;
+ case 48:
+ mode |= WL1273_IS2_WIDTH_96;
+ break;
+ case 64:
+ mode |= WL1273_IS2_WIDTH_128;
+ break;
+ default:
+ dev_err(dev, "Data width: %d not supported\n", width);
+ r = -EINVAL;
+ goto out;
+ }
+
+ dev_dbg(dev, "WL1273_I2S_DEF_MODE: 0x%04x\n", WL1273_I2S_DEF_MODE);
+ dev_dbg(dev, "core->i2s_mode: 0x%04x\n", core->i2s_mode);
+ dev_dbg(dev, "mode: 0x%04x\n", mode);
+
+ if (core->i2s_mode != mode) {
+ r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, mode);
+ if (r)
+ goto out;
+
+ core->i2s_mode = mode;
+ r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
+ WL1273_AUDIO_ENABLE_I2S);
+ if (r)
+ goto out;
+ }
+out:
+ mutex_unlock(&core->lock);
+
+ return r;
+}
+
+static int snd_wl1273_fm_set_channel_number(struct wl1273_core *core,
+ int channel_number)
+{
+ struct i2c_client *client = core->i2c_dev;
+ struct device *dev = &client->dev;
+ int r = 0;
+
+ dev_dbg(dev, "%s\n", __func__);
+
+ mutex_lock(&core->lock);
+
+ if (core->channel_number == channel_number)
+ goto out;
+
+ if (channel_number == 1 && core->mode == WL1273_MODE_RX)
+ r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
+ WL1273_RX_MONO);
+ else if (channel_number == 1 && core->mode == WL1273_MODE_TX)
+ r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
+ WL1273_TX_MONO);
+ else if (channel_number == 2 && core->mode == WL1273_MODE_RX)
+ r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
+ WL1273_RX_STEREO);
+ else if (channel_number == 2 && core->mode == WL1273_MODE_TX)
+ r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
+ WL1273_TX_STEREO);
+ else
+ r = -EINVAL;
+out:
+ mutex_unlock(&core->lock);
+
+ return r;
+}
+
+static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = wl1273->mode;
+
+ return 0;
+}
+
+static const char *wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" };
+
+static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+ if (wl1273->mode == ucontrol->value.integer.value[0])
+ return 0;
+
+ /* Do not allow changes while stream is running */
+ if (codec->active)
+ return -EPERM;
+
+ if (ucontrol->value.integer.value[0] < 0 ||
+ ucontrol->value.integer.value[0] >= ARRAY_SIZE(wl1273_audio_route))
+ return -EINVAL;
+
+ wl1273->mode = ucontrol->value.integer.value[0];
+
+ return 1;
+}
+
+static const struct soc_enum wl1273_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route);
+
+static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s: enter.\n", __func__);
+
+ ucontrol->value.integer.value[0] = wl1273->core->audio_mode;
+
+ return 0;
+}
+
+static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+ int val, r = 0;
+
+ dev_dbg(codec->dev, "%s: enter.\n", __func__);
+
+ val = ucontrol->value.integer.value[0];
+ if (wl1273->core->audio_mode == val)
+ return 0;
+
+ r = wl1273_fm_set_audio(wl1273->core, val);
+ if (r < 0)
+ return r;
+
+ return 1;
+}
+
+static const char *wl1273_audio_strings[] = { "Digital", "Analog" };
+
+static const struct soc_enum wl1273_audio_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings),
+ wl1273_audio_strings);
+
+static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s: enter.\n", __func__);
+
+ ucontrol->value.integer.value[0] = wl1273->core->volume;
+
+ return 0;
+}
+
+static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+ int r;
+
+ dev_dbg(codec->dev, "%s: enter.\n", __func__);
+
+ r = wl1273_fm_set_volume(wl1273->core,
+ ucontrol->value.integer.value[0]);
+ if (r)
+ return r;
+
+ return 1;
+}
+
+static const struct snd_kcontrol_new wl1273_controls[] = {
+ SOC_ENUM_EXT("Codec Mode", wl1273_enum,
+ snd_wl1273_get_audio_route, snd_wl1273_set_audio_route),
+ SOC_ENUM_EXT("Audio Switch", wl1273_audio_enum,
+ snd_wl1273_fm_audio_get, snd_wl1273_fm_audio_put),
+ SOC_SINGLE_EXT("Volume", 0, 0, WL1273_MAX_VOLUME, 0,
+ snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put),
+};
+
+static int wl1273_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+ switch (wl1273->mode) {
+ case WL1273_MODE_BT:
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ 8000, 8000);
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 1, 1);
+ break;
+ case WL1273_MODE_FM_RX:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ pr_err("Cannot play in RX mode.\n");
+ return -EINVAL;
+ }
+ break;
+ case WL1273_MODE_FM_TX:
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ pr_err("Cannot capture in TX mode.\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+static int wl1273_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(rtd->codec);
+ struct wl1273_core *core = wl1273->core;
+ unsigned int rate, width, r;
+
+ if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) {
+ pr_err("Only SNDRV_PCM_FORMAT_S16_LE supported.\n");
+ return -EINVAL;
+ }
+
+ rate = params_rate(params);
+ width = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
+
+ if (wl1273->mode == WL1273_MODE_BT) {
+ if (rate != 8000) {
+ pr_err("Rate %d not supported.\n", params_rate(params));
+ return -EINVAL;
+ }
+
+ if (params_channels(params) != 1) {
+ pr_err("Only mono supported.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
+ if (wl1273->mode == WL1273_MODE_FM_TX &&
+ substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ pr_err("Only playback supported with TX.\n");
+ return -EINVAL;
+ }
+
+ if (wl1273->mode == WL1273_MODE_FM_RX &&
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ pr_err("Only capture supported with RX.\n");
+ return -EINVAL;
+ }
+
+ if (wl1273->mode != WL1273_MODE_FM_RX &&
+ wl1273->mode != WL1273_MODE_FM_TX) {
+ pr_err("Unexpected mode: %d.\n", wl1273->mode);
+ return -EINVAL;
+ }
+
+ r = snd_wl1273_fm_set_i2s_mode(core, rate, width);
+ if (r)
+ return r;
+
+ wl1273->channels = params_channels(params);
+ r = snd_wl1273_fm_set_channel_number(core, wl1273->channels);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops wl1273_dai_ops = {
+ .startup = wl1273_startup,
+ .hw_params = wl1273_hw_params,
+};
+
+static struct snd_soc_dai_driver wl1273_dai = {
+ .name = "wl1273-fm",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE},
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE},
+ .ops = &wl1273_dai_ops,
+};
+
+/* Audio interface format for the soc_card driver */
+int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt)
+{
+ struct wl1273_priv *wl1273;
+
+ if (codec == NULL || fmt == NULL)
+ return -EINVAL;
+
+ wl1273 = snd_soc_codec_get_drvdata(codec);
+
+ switch (wl1273->mode) {
+ case WL1273_MODE_FM_RX:
+ case WL1273_MODE_FM_TX:
+ *fmt = SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+
+ break;
+ case WL1273_MODE_BT:
+ *fmt = SND_SOC_DAIFMT_DSP_A |
+ SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wl1273_get_format);
+
+static int wl1273_probe(struct snd_soc_codec *codec)
+{
+ struct wl1273_core **core = codec->dev->platform_data;
+ struct wl1273_priv *wl1273;
+ int r;
+
+ dev_dbg(codec->dev, "%s.\n", __func__);
+
+ if (!core) {
+ dev_err(codec->dev, "Platform data is missing.\n");
+ return -EINVAL;
+ }
+
+ wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
+ if (wl1273 == NULL) {
+ dev_err(codec->dev, "Cannot allocate memory.\n");
+ return -ENOMEM;
+ }
+
+ wl1273->mode = WL1273_MODE_BT;
+ wl1273->core = *core;
+
+ snd_soc_codec_set_drvdata(codec, wl1273);
+ mutex_init(&codec->mutex);
+
+ r = snd_soc_add_controls(codec, wl1273_controls,
+ ARRAY_SIZE(wl1273_controls));
+ if (r)
+ kfree(wl1273);
+
+ return r;
+}
+
+static int wl1273_remove(struct snd_soc_codec *codec)
+{
+ struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "%s\n", __func__);
+ kfree(wl1273);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
+ .probe = wl1273_probe,
+ .remove = wl1273_remove,
+};
+
+static int __devinit wl1273_platform_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273,
+ &wl1273_dai, 1);
+}
+
+static int __devexit wl1273_platform_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+MODULE_ALIAS("platform:wl1273-codec");
+
+static struct platform_driver wl1273_platform_driver = {
+ .driver = {
+ .name = "wl1273-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wl1273_platform_probe,
+ .remove = __devexit_p(wl1273_platform_remove),
+};
+
+static int __init wl1273_init(void)
+{
+ return platform_driver_register(&wl1273_platform_driver);
+}
+module_init(wl1273_init);
+
+static void __exit wl1273_exit(void)
+{
+ platform_driver_unregister(&wl1273_platform_driver);
+}
+module_exit(wl1273_exit);
+
+MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
+MODULE_DESCRIPTION("ASoC WL1273 codec driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wl1273.h b/sound/soc/codecs/wl1273.h
new file mode 100644
index 000000000000..14ed027fdcfc
--- /dev/null
+++ b/sound/soc/codecs/wl1273.h
@@ -0,0 +1,101 @@
+/*
+ * sound/soc/codec/wl1273.h
+ *
+ * ALSA SoC WL1273 codec driver
+ *
+ * Copyright (C) Nokia Corporation
+ * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1273_CODEC_H__
+#define __WL1273_CODEC_H__
+
+/* I2S protocol, left channel first, data width 16 bits */
+#define WL1273_PCM_DEF_MODE 0x00
+
+/* Rx */
+#define WL1273_AUDIO_ENABLE_I2S (1 << 0)
+#define WL1273_AUDIO_ENABLE_ANALOG (1 << 1)
+
+/* Tx */
+#define WL1273_AUDIO_IO_SET_ANALOG 0
+#define WL1273_AUDIO_IO_SET_I2S 1
+
+#define WL1273_POWER_SET_OFF 0
+#define WL1273_POWER_SET_FM (1 << 0)
+#define WL1273_POWER_SET_RDS (1 << 1)
+#define WL1273_POWER_SET_RETENTION (1 << 4)
+
+#define WL1273_PUPD_SET_OFF 0x00
+#define WL1273_PUPD_SET_ON 0x01
+#define WL1273_PUPD_SET_RETENTION 0x10
+
+/* I2S mode */
+#define WL1273_IS2_WIDTH_32 0x0
+#define WL1273_IS2_WIDTH_40 0x1
+#define WL1273_IS2_WIDTH_22_23 0x2
+#define WL1273_IS2_WIDTH_23_22 0x3
+#define WL1273_IS2_WIDTH_48 0x4
+#define WL1273_IS2_WIDTH_50 0x5
+#define WL1273_IS2_WIDTH_60 0x6
+#define WL1273_IS2_WIDTH_64 0x7
+#define WL1273_IS2_WIDTH_80 0x8
+#define WL1273_IS2_WIDTH_96 0x9
+#define WL1273_IS2_WIDTH_128 0xa
+#define WL1273_IS2_WIDTH 0xf
+
+#define WL1273_IS2_FORMAT_STD (0x0 << 4)
+#define WL1273_IS2_FORMAT_LEFT (0x1 << 4)
+#define WL1273_IS2_FORMAT_RIGHT (0x2 << 4)
+#define WL1273_IS2_FORMAT_USER (0x3 << 4)
+
+#define WL1273_IS2_MASTER (0x0 << 6)
+#define WL1273_IS2_SLAVEW (0x1 << 6)
+
+#define WL1273_IS2_TRI_AFTER_SENDING (0x0 << 7)
+#define WL1273_IS2_TRI_ALWAYS_ACTIVE (0x1 << 7)
+
+#define WL1273_IS2_SDOWS_RR (0x0 << 8)
+#define WL1273_IS2_SDOWS_RF (0x1 << 8)
+#define WL1273_IS2_SDOWS_FR (0x2 << 8)
+#define WL1273_IS2_SDOWS_FF (0x3 << 8)
+
+#define WL1273_IS2_TRI_OPT (0x0 << 10)
+#define WL1273_IS2_TRI_ALWAYS (0x1 << 10)
+
+#define WL1273_IS2_RATE_48K (0x0 << 12)
+#define WL1273_IS2_RATE_44_1K (0x1 << 12)
+#define WL1273_IS2_RATE_32K (0x2 << 12)
+#define WL1273_IS2_RATE_22_05K (0x4 << 12)
+#define WL1273_IS2_RATE_16K (0x5 << 12)
+#define WL1273_IS2_RATE_12K (0x8 << 12)
+#define WL1273_IS2_RATE_11_025 (0x9 << 12)
+#define WL1273_IS2_RATE_8K (0xa << 12)
+#define WL1273_IS2_RATE (0xf << 12)
+
+#define WL1273_I2S_DEF_MODE (WL1273_IS2_WIDTH_32 | \
+ WL1273_IS2_FORMAT_STD | \
+ WL1273_IS2_MASTER | \
+ WL1273_IS2_TRI_AFTER_SENDING | \
+ WL1273_IS2_SDOWS_RR | \
+ WL1273_IS2_TRI_OPT | \
+ WL1273_IS2_RATE_48K)
+
+int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt);
+
+#endif /* End of __WL1273_CODEC_H__ */
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h
index c18e261c3c7f..0b6f056f73cc 100644
--- a/sound/soc/codecs/wm2000.h
+++ b/sound/soc/codecs/wm2000.h
@@ -16,9 +16,6 @@ struct wm2000_setup_data {
extern int wm2000_add_controls(struct snd_soc_codec *codec);
-extern struct snd_soc_dai wm2000_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm2000;
-
#define WM2000_REG_SYS_START 0x8000
#define WM2000_REG_SPEECH_CLARITY 0x8fef
#define WM2000_REG_SYS_WATCHDOG 0x8ff6
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 0221ca79b3ae..7611add7f8c3 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -831,7 +831,7 @@ static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
}
/* MCLK direction */
- if (dir == WM8350_MCLK_DIR_OUT)
+ if (dir == SND_SOC_CLOCK_OUT)
wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2,
WM8350_MCLK_DIR);
else
@@ -1321,20 +1321,14 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm8350_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8350_resume(struct platform_device *pdev)
+static int wm8350_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -1489,24 +1483,74 @@ int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect);
-static struct snd_soc_codec *wm8350_codec;
+#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000)
+
+#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
-static int wm8350_probe(struct platform_device *pdev)
+static struct snd_soc_dai_ops wm8350_dai_ops = {
+ .hw_params = wm8350_pcm_hw_params,
+ .digital_mute = wm8350_mute,
+ .trigger = wm8350_pcm_trigger,
+ .set_fmt = wm8350_set_dai_fmt,
+ .set_sysclk = wm8350_set_dai_sysclk,
+ .set_pll = wm8350_set_fll,
+ .set_clkdiv = wm8350_set_clkdiv,
+};
+
+static struct snd_soc_dai_driver wm8350_dai = {
+ .name = "wm8350-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8350_RATES,
+ .formats = WM8350_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8350_RATES,
+ .formats = WM8350_FORMATS,
+ },
+ .ops = &wm8350_dai_ops,
+};
+
+static int wm8350_codec_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct wm8350 *wm8350;
+ struct wm8350 *wm8350 = dev_get_platdata(codec->dev);
struct wm8350_data *priv;
- int ret;
struct wm8350_output *out1;
struct wm8350_output *out2;
+ int ret, i;
- BUG_ON(!wm8350_codec);
+ if (wm8350->codec.platform_data == NULL) {
+ dev_err(codec->dev, "No audio platform data supplied\n");
+ return -EINVAL;
+ }
+
+ priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+ snd_soc_codec_set_drvdata(codec, priv);
+
+ for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+ priv->supplies[i].supply = supply_names[i];
+
+ ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
+ priv->supplies);
+ if (ret != 0)
+ goto err_priv;
+
+ wm8350->codec.codec = codec;
+ codec->control_data = wm8350;
- socdev->card->codec = wm8350_codec;
- codec = socdev->card->codec;
- wm8350 = codec->control_data;
- priv = snd_soc_codec_get_drvdata(codec);
+ /* Put the codec into reset if it wasn't already */
+ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+
+ INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
/* Enable the codec */
wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
@@ -1542,6 +1586,13 @@ static int wm8350_probe(struct platform_device *pdev)
wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME,
WM8350_OUT2_VU | WM8350_OUT2R_MUTE);
+ /* Make sure AIF tristating is disabled by default */
+ wm8350_clear_bits(wm8350, WM8350_AI_FORMATING, WM8350_AIF_TRI);
+
+ /* Make sure we've got a sane companding setup too */
+ wm8350_clear_bits(wm8350, WM8350_ADC_DAC_COMP,
+ WM8350_DAC_COMP | WM8350_LOOPBACK);
+
/* Make sure jack detect is disabled to start off with */
wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
WM8350_JDL_ENA | WM8350_JDR_ENA);
@@ -1557,11 +1608,6 @@ static int wm8350_probe(struct platform_device *pdev)
wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
wm8350_mic_handler, 0, "Microphone detect", priv);
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to create pcms\n");
- return ret;
- }
snd_soc_add_controls(codec, wm8350_snd_controls,
ARRAY_SIZE(wm8350_snd_controls));
@@ -1570,14 +1616,16 @@ static int wm8350_probe(struct platform_device *pdev)
wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
+
+err_priv:
+ kfree(priv);
+ return ret;
}
-static int wm8350_remove(struct platform_device *pdev)
+static int wm8350_codec_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
- struct wm8350 *wm8350 = codec->control_data;
struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
+ struct wm8350 *wm8350 = dev_get_platdata(codec->dev);
int ret;
wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
@@ -1607,134 +1655,30 @@ static int wm8350_remove(struct platform_device *pdev)
wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+ regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
+ kfree(priv);
return 0;
}
-#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000)
-
-#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S20_3LE |\
- SNDRV_PCM_FMTBIT_S24_LE)
-
-static struct snd_soc_dai_ops wm8350_dai_ops = {
- .hw_params = wm8350_pcm_hw_params,
- .digital_mute = wm8350_mute,
- .trigger = wm8350_pcm_trigger,
- .set_fmt = wm8350_set_dai_fmt,
- .set_sysclk = wm8350_set_dai_sysclk,
- .set_pll = wm8350_set_fll,
- .set_clkdiv = wm8350_set_clkdiv,
-};
-
-struct snd_soc_dai wm8350_dai = {
- .name = "WM8350",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = WM8350_RATES,
- .formats = WM8350_FORMATS,
- },
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = WM8350_RATES,
- .formats = WM8350_FORMATS,
- },
- .ops = &wm8350_dai_ops,
-};
-EXPORT_SYMBOL_GPL(wm8350_dai);
-
-struct snd_soc_codec_device soc_codec_dev_wm8350 = {
- .probe = wm8350_probe,
- .remove = wm8350_remove,
+static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
+ .probe = wm8350_codec_probe,
+ .remove = wm8350_codec_remove,
.suspend = wm8350_suspend,
.resume = wm8350_resume,
+ .read = wm8350_codec_read,
+ .write = wm8350_codec_write,
+ .set_bias_level = wm8350_set_bias_level,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350);
-static __devinit int wm8350_codec_probe(struct platform_device *pdev)
+static int __devinit wm8350_probe(struct platform_device *pdev)
{
- struct wm8350 *wm8350 = platform_get_drvdata(pdev);
- struct wm8350_data *priv;
- struct snd_soc_codec *codec;
- int ret, i;
-
- if (wm8350->codec.platform_data == NULL) {
- dev_err(&pdev->dev, "No audio platform data supplied\n");
- return -EINVAL;
- }
-
- priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
- if (priv == NULL)
- return -ENOMEM;
-
- for (i = 0; i < ARRAY_SIZE(supply_names); i++)
- priv->supplies[i].supply = supply_names[i];
-
- ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
- priv->supplies);
- if (ret != 0)
- goto err_priv;
-
- codec = &priv->codec;
- wm8350->codec.codec = codec;
-
- wm8350_dai.dev = &pdev->dev;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
- codec->dev = &pdev->dev;
- codec->name = "WM8350";
- codec->owner = THIS_MODULE;
- codec->read = wm8350_codec_read;
- codec->write = wm8350_codec_write;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8350_set_bias_level;
- codec->dai = &wm8350_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8350_MAX_REGISTER;
- snd_soc_codec_set_drvdata(codec, priv);
- codec->control_data = wm8350;
-
- /* Put the codec into reset if it wasn't already */
- wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
-
- INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
- ret = snd_soc_register_codec(codec);
- if (ret != 0)
- goto err_supply;
-
- wm8350_codec = codec;
-
- ret = snd_soc_register_dai(&wm8350_dai);
- if (ret != 0)
- goto err_codec;
- return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err_supply:
- regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
-err_priv:
- kfree(priv);
- wm8350_codec = NULL;
- return ret;
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350,
+ &wm8350_dai, 1);
}
-static int __devexit wm8350_codec_remove(struct platform_device *pdev)
+static int __devexit wm8350_remove(struct platform_device *pdev)
{
- struct wm8350 *wm8350 = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = wm8350->codec.codec;
- struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
-
- snd_soc_unregister_dai(&wm8350_dai);
- snd_soc_unregister_codec(codec);
- regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
- kfree(priv);
- wm8350_codec = NULL;
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
@@ -1743,8 +1687,8 @@ static struct platform_driver wm8350_codec_driver = {
.name = "wm8350-codec",
.owner = THIS_MODULE,
},
- .probe = wm8350_codec_probe,
- .remove = __devexit_p(wm8350_codec_remove),
+ .probe = wm8350_probe,
+ .remove = __devexit_p(wm8350_remove),
};
static __init int wm8350_init(void)
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index 9ed0467c71db..74108eb82938 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -15,9 +15,6 @@
#include <sound/soc.h>
#include <linux/mfd/wm8350/audio.h>
-extern struct snd_soc_dai wm8350_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8350;
-
enum wm8350_jack {
WM8350_JDL = 1,
WM8350_JDR = 2,
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 8f294066b0ed..850299786e02 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -65,7 +65,7 @@ static struct regulator_bulk_data power[] = {
/* codec private data */
struct wm8400_priv {
- struct snd_soc_codec codec;
+ struct snd_soc_codec *codec;
struct wm8400 *wm8400;
u16 fake_register;
unsigned int sysclk;
@@ -1163,8 +1163,7 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1);
audio1 &= ~WM8400_AIF_WL_MASK;
@@ -1332,10 +1331,9 @@ static struct snd_soc_dai_ops wm8400_dai_ops = {
* 1. ADC/DAC on Primary Interface
* 2. ADC on Primary Interface/DAC on secondary
*/
-struct snd_soc_dai wm8400_dai = {
+static struct snd_soc_dai_driver wm8400_dai = {
/* ADC/DAC on primary */
- .name = "WM8400 ADC/DAC Primary",
- .id = 1,
+ .name = "wm8400-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -1352,147 +1350,53 @@ struct snd_soc_dai wm8400_dai = {
},
.ops = &wm8400_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8400_dai);
-static int wm8400_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8400_resume(struct platform_device *pdev)
+static int wm8400_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
-static struct snd_soc_codec *wm8400_codec;
-
-static int wm8400_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret;
-
- if (!wm8400_codec) {
- dev_err(&pdev->dev, "wm8400 not yet discovered\n");
- return -ENODEV;
- }
- codec = wm8400_codec;
-
- socdev->card->codec = codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to create pcms\n");
- goto pcm_err;
- }
-
- wm8400_add_controls(codec);
- wm8400_add_widgets(codec);
-
-pcm_err:
- return ret;
-}
-
-/* power down chip */
-static int wm8400_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8400 = {
- .probe = wm8400_probe,
- .remove = wm8400_remove,
- .suspend = wm8400_suspend,
- .resume = wm8400_resume,
-};
-
static void wm8400_probe_deferred(struct work_struct *work)
{
struct wm8400_priv *priv = container_of(work, struct wm8400_priv,
work);
- struct snd_soc_codec *codec = &priv->codec;
- int ret;
+ struct snd_soc_codec *codec = priv->codec;
/* charge output caps */
wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- /* We're done, tell the subsystem. */
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(priv->wm8400->dev,
- "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&wm8400_dai);
- if (ret != 0) {
- dev_err(priv->wm8400->dev,
- "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
- return;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
-static int wm8400_codec_probe(struct platform_device *dev)
+static int wm8400_codec_probe(struct snd_soc_codec *codec)
{
+ struct wm8400 *wm8400 = dev_get_platdata(codec->dev);
struct wm8400_priv *priv;
int ret;
u16 reg;
- struct snd_soc_codec *codec;
priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
- codec = &priv->codec;
snd_soc_codec_set_drvdata(codec, priv);
- codec->control_data = dev_get_drvdata(&dev->dev);
- priv->wm8400 = dev_get_drvdata(&dev->dev);
+ codec->control_data = priv->wm8400 = wm8400;
+ priv->codec = codec;
- ret = regulator_bulk_get(priv->wm8400->dev,
+ ret = regulator_bulk_get(wm8400->dev,
ARRAY_SIZE(power), &power[0]);
if (ret != 0) {
- dev_err(&dev->dev, "Failed to get regulators: %d\n", ret);
+ dev_err(codec->dev, "Failed to get regulators: %d\n", ret);
goto err;
}
- codec->dev = &dev->dev;
- wm8400_dai.dev = &dev->dev;
-
- codec->name = "WM8400";
- codec->owner = THIS_MODULE;
- codec->read = wm8400_read;
- codec->write = wm8400_write;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8400_set_bias_level;
- codec->dai = &wm8400_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8400_REGISTER_COUNT;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
INIT_WORK(&priv->work, wm8400_probe_deferred);
wm8400_codec_reset(codec);
@@ -1511,65 +1415,78 @@ static int wm8400_codec_probe(struct platform_device *dev)
wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- wm8400_codec = codec;
-
if (!schedule_work(&priv->work)) {
ret = -EINVAL;
goto err_regulator;
}
-
+ wm8400_add_controls(codec);
+ wm8400_add_widgets(codec);
return 0;
err_regulator:
- wm8400_codec = NULL;
regulator_bulk_free(ARRAY_SIZE(power), power);
err:
kfree(priv);
return ret;
}
-static int __exit wm8400_codec_remove(struct platform_device *dev)
+static int wm8400_codec_remove(struct snd_soc_codec *codec)
{
- struct wm8400_priv *priv = snd_soc_codec_get_drvdata(wm8400_codec);
+ struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec);
u16 reg;
- snd_soc_unregister_dai(&wm8400_dai);
- snd_soc_unregister_codec(wm8400_codec);
-
- reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1);
- wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1,
+ reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
+ wm8400_write(codec, WM8400_POWER_MANAGEMENT_1,
reg & (~WM8400_CODEC_ENA));
regulator_bulk_free(ARRAY_SIZE(power), power);
kfree(priv);
- wm8400_codec = NULL;
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
+ .probe = wm8400_codec_probe,
+ .remove = wm8400_codec_remove,
+ .suspend = wm8400_suspend,
+ .resume = wm8400_resume,
+ .read = wm8400_read,
+ .write = wm8400_write,
+ .set_bias_level = wm8400_set_bias_level,
+};
+
+static int __devinit wm8400_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400,
+ &wm8400_dai, 1);
+}
+static int __devexit wm8400_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
static struct platform_driver wm8400_codec_driver = {
.driver = {
- .name = "wm8400-codec",
- .owner = THIS_MODULE,
- },
- .probe = wm8400_codec_probe,
- .remove = __exit_p(wm8400_codec_remove),
+ .name = "wm8400-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8400_probe,
+ .remove = __devexit_p(wm8400_remove),
};
-static int __init wm8400_codec_init(void)
+static __init int wm8400_init(void)
{
return platform_driver_register(&wm8400_codec_driver);
}
-module_init(wm8400_codec_init);
+module_init(wm8400_init);
-static void __exit wm8400_codec_exit(void)
+static __exit void wm8400_exit(void)
{
platform_driver_unregister(&wm8400_codec_driver);
}
-module_exit(wm8400_codec_exit);
-
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400);
+module_exit(wm8400_exit);
MODULE_DESCRIPTION("ASoC WM8400 driver");
MODULE_AUTHOR("Mark Brown");
diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h
index 79c5934d4776..521adb193870 100644
--- a/sound/soc/codecs/wm8400.h
+++ b/sound/soc/codecs/wm8400.h
@@ -56,7 +56,4 @@
#define WM8400_BCLK_DIV_44 (0xE << 1)
#define WM8400_BCLK_DIV_48 (0xF << 1)
-extern struct snd_soc_dai wm8400_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8400;
-
#endif
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 0f7bcb61071a..8f107095760e 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -29,10 +29,6 @@
#include "wm8510.h"
-#define WM8510_VERSION "0.6"
-
-struct snd_soc_codec_device soc_codec_dev_wm8510;
-
/*
* wm8510 register cache
* We can't read the WM8510 register space when we are
@@ -61,6 +57,11 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
+/* codec private data */
+struct wm8510_priv {
+ enum snd_soc_control_type control_type;
+};
+
static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
static const char *wm8510_alc[] = { "ALC", "Limiter" };
@@ -403,8 +404,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
@@ -514,8 +514,8 @@ static struct snd_soc_dai_ops wm8510_dai_ops = {
.set_pll = wm8510_set_dai_pll,
};
-struct snd_soc_dai wm8510_dai = {
- .name = "WM8510 HiFi",
+static struct snd_soc_dai_driver wm8510_dai = {
+ .name = "wm8510-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -531,21 +531,15 @@ struct snd_soc_dai wm8510_dai = {
.ops = &wm8510_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8510_dai);
-static int wm8510_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8510_resume(struct platform_device *pdev)
+static int wm8510_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -561,256 +555,158 @@ static int wm8510_resume(struct platform_device *pdev)
return 0;
}
-/*
- * initialise the WM8510 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8510_init(struct snd_soc_device *socdev,
- enum snd_soc_control_type control)
+static int wm8510_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = socdev->card->codec;
- int ret = 0;
-
- codec->name = "WM8510";
- codec->owner = THIS_MODULE;
- codec->set_bias_level = wm8510_set_bias_level;
- codec->dai = &wm8510_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm8510_reg);
- codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL);
-
- if (codec->reg_cache == NULL)
- return -ENOMEM;
+ struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
+ int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type);
if (ret < 0) {
- printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n",
- ret);
- goto err;
+ printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret);
+ return ret;
}
wm8510_reset(codec);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "wm8510: failed to create pcms\n");
- goto err;
- }
-
/* power on device */
- codec->bias_level = SND_SOC_BIAS_OFF;
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
snd_soc_add_controls(codec, wm8510_snd_controls,
ARRAY_SIZE(wm8510_snd_controls));
wm8510_add_widgets(codec);
return ret;
-
-err:
- kfree(codec->reg_cache);
- return ret;
}
-static struct snd_soc_device *wm8510_socdev;
+/* power down chip */
+static int wm8510_remove(struct snd_soc_codec *codec)
+{
+ struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ kfree(wm8510);
+ return 0;
+}
-/*
- * WM8510 2 wire address is 0x1a
- */
+static struct snd_soc_codec_driver soc_codec_dev_wm8510 = {
+ .probe = wm8510_probe,
+ .remove = wm8510_remove,
+ .suspend = wm8510_suspend,
+ .resume = wm8510_resume,
+ .set_bias_level = wm8510_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8510_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default =wm8510_reg,
+};
-static int wm8510_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8510_spi_probe(struct spi_device *spi)
{
- struct snd_soc_device *socdev = wm8510_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct wm8510_priv *wm8510;
int ret;
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
+ wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL);
+ if (wm8510 == NULL)
+ return -ENOMEM;
- ret = wm8510_init(socdev, SND_SOC_I2C);
- if (ret < 0)
- pr_err("failed to initialise WM8510\n");
+ wm8510->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8510);
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8510, &wm8510_dai, 1);
+ if (ret < 0)
+ kfree(wm8510);
return ret;
}
-static int wm8510_i2c_remove(struct i2c_client *client)
+static int __devexit wm8510_spi_remove(struct spi_device *spi)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
+ snd_soc_unregister_codec(&spi->dev);
return 0;
}
-static const struct i2c_device_id wm8510_i2c_id[] = {
- { "wm8510", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
-
-static struct i2c_driver wm8510_i2c_driver = {
+static struct spi_driver wm8510_spi_driver = {
.driver = {
- .name = "WM8510 I2C Codec",
- .owner = THIS_MODULE,
+ .name = "wm8510",
+ .owner = THIS_MODULE,
},
- .probe = wm8510_i2c_probe,
- .remove = wm8510_i2c_remove,
- .id_table = wm8510_i2c_id,
+ .probe = wm8510_spi_probe,
+ .remove = __devexit_p(wm8510_spi_remove),
};
+#endif /* CONFIG_SPI_MASTER */
-static int wm8510_add_i2c_device(struct platform_device *pdev,
- const struct wm8510_setup_data *setup)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
+ struct wm8510_priv *wm8510;
int ret;
- ret = i2c_add_driver(&wm8510_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = setup->i2c_address;
- strlcpy(info.type, "wm8510", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n",
- setup->i2c_bus);
- goto err_driver;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
-
- return 0;
-
-err_driver:
- i2c_del_driver(&wm8510_i2c_driver);
- return -ENODEV;
-}
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8510_spi_probe(struct spi_device *spi)
-{
- struct snd_soc_device *socdev = wm8510_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
- int ret;
+ wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL);
+ if (wm8510 == NULL)
+ return -ENOMEM;
- codec->control_data = spi;
+ i2c_set_clientdata(i2c, wm8510);
+ wm8510->control_type = SND_SOC_I2C;
- ret = wm8510_init(socdev, SND_SOC_SPI);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8510, &wm8510_dai, 1);
if (ret < 0)
- dev_err(&spi->dev, "failed to initialise WM8510\n");
-
+ kfree(wm8510);
return ret;
}
-static int __devexit wm8510_spi_remove(struct spi_device *spi)
+static __devexit int wm8510_i2c_remove(struct i2c_client *client)
{
+ snd_soc_unregister_codec(&client->dev);
return 0;
}
-static struct spi_driver wm8510_spi_driver = {
+static const struct i2c_device_id wm8510_i2c_id[] = {
+ { "wm8510", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
+
+static struct i2c_driver wm8510_i2c_driver = {
.driver = {
- .name = "wm8510",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
+ .name = "wm8510-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8510_spi_probe,
- .remove = __devexit_p(wm8510_spi_remove),
+ .probe = wm8510_i2c_probe,
+ .remove = __devexit_p(wm8510_i2c_remove),
+ .id_table = wm8510_i2c_id,
};
-#endif /* CONFIG_SPI_MASTER */
+#endif
-static int wm8510_probe(struct platform_device *pdev)
+static int __init wm8510_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8510_setup_data *setup;
- struct snd_soc_codec *codec;
int ret = 0;
-
- pr_info("WM8510 Audio Codec %s", WM8510_VERSION);
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- socdev->card->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- wm8510_socdev = socdev;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- ret = wm8510_add_i2c_device(pdev, setup);
+ ret = i2c_add_driver(&wm8510_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n",
+ ret);
}
#endif
#if defined(CONFIG_SPI_MASTER)
- if (setup->spi) {
- ret = spi_register_driver(&wm8510_spi_driver);
- if (ret != 0)
- printk(KERN_ERR "can't add spi driver");
+ ret = spi_register_driver(&wm8510_spi_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n",
+ ret);
}
#endif
-
- if (ret != 0)
- kfree(codec);
return ret;
}
+module_init(wm8510_modinit);
-/* power down chip */
-static int wm8510_remove(struct platform_device *pdev)
+static void __exit wm8510_exit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec->control_data)
- wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8510_i2c_driver);
#endif
#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver(&wm8510_spi_driver);
#endif
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8510 = {
- .probe = wm8510_probe,
- .remove = wm8510_remove,
- .suspend = wm8510_suspend,
- .resume = wm8510_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
-
-static int __init wm8510_modinit(void)
-{
- return snd_soc_register_dai(&wm8510_dai);
-}
-module_init(wm8510_modinit);
-
-static void __exit wm8510_exit(void)
-{
- snd_soc_unregister_dai(&wm8510_dai);
}
module_exit(wm8510_exit);
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h
index bdefcf5c69ff..b3e26ed9f2d0 100644
--- a/sound/soc/codecs/wm8510.h
+++ b/sound/soc/codecs/wm8510.h
@@ -99,7 +99,4 @@ struct wm8510_setup_data {
unsigned short i2c_address;
};
-extern struct snd_soc_dai wm8510_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8510;
-
#endif
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 0ad039b4adf5..9a433a5396cb 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -30,9 +30,6 @@
#include "wm8523.h"
-static struct snd_soc_codec *wm8523_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8523;
-
#define WM8523_NUM_SUPPLIES 2
static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
"AVDD",
@@ -43,7 +40,7 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
/* codec private data */
struct wm8523_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
u16 reg_cache[WM8523_REGISTER_COUNT];
struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
unsigned int sysclk;
@@ -149,7 +146,6 @@ static int wm8523_startup(struct snd_pcm_substream *substream,
return -EINVAL;
}
- return 0;
snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&wm8523->rate_constraint);
@@ -162,8 +158,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
int i;
u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
@@ -387,8 +382,8 @@ static struct snd_soc_dai_ops wm8523_dai_ops = {
.set_fmt = wm8523_set_dai_fmt,
};
-struct snd_soc_dai wm8523_dai = {
- .name = "WM8523",
+static struct snd_soc_dai_driver wm8523_dai = {
+ .name = "wm8523-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2, /* Mono modes not yet supported */
@@ -398,25 +393,17 @@ struct snd_soc_dai wm8523_dai = {
},
.ops = &wm8523_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8523_dai);
#ifdef CONFIG_PM
-static int wm8523_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8523_resume(struct platform_device *pdev)
+static int wm8523_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
}
#else
@@ -424,93 +411,20 @@ static int wm8523_resume(struct platform_device *pdev)
#define wm8523_resume NULL
#endif
-static int wm8523_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8523_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8523_codec;
- codec = wm8523_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8523_snd_controls,
- ARRAY_SIZE(wm8523_snd_controls));
- wm8523_add_widgets(codec);
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-static int wm8523_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8523 = {
- .probe = wm8523_probe,
- .remove = wm8523_remove,
- .suspend = wm8523_suspend,
- .resume = wm8523_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523);
-
-static int wm8523_register(struct wm8523_priv *wm8523,
- enum snd_soc_control_type control)
+static int wm8523_probe(struct snd_soc_codec *codec)
{
- int ret;
- struct snd_soc_codec *codec = &wm8523->codec;
- int i;
-
- if (wm8523_codec) {
- dev_err(codec->dev, "Another WM8523 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8523);
- codec->name = "WM8523";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8523_set_bias_level;
- codec->dai = &wm8523_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8523_REGISTER_COUNT;
- codec->reg_cache = &wm8523->reg_cache;
- codec->volatile_register = wm8523_volatile_register;
+ struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+ int ret, i;
+ codec->hw_write = (hw_write_t)i2c_master_send;
wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
wm8523->rate_constraint.count =
ARRAY_SIZE(wm8523->rate_constraint_list);
- memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg));
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
@@ -520,7 +434,7 @@ static int wm8523_register(struct wm8523_priv *wm8523,
wm8523->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
@@ -555,8 +469,6 @@ static int wm8523_register(struct wm8523_priv *wm8523,
goto err_enable;
}
- wm8523_dai.dev = codec->dev;
-
/* Change some default settings - latch VU and enable ZC */
wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
@@ -566,69 +478,67 @@ static int wm8523_register(struct wm8523_priv *wm8523,
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
- wm8523_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err_enable;
- }
-
- ret = snd_soc_register_dai(&wm8523_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
+ snd_soc_add_controls(codec, wm8523_snd_controls,
+ ARRAY_SIZE(wm8523_snd_controls));
+ wm8523_add_widgets(codec);
return 0;
-err_codec:
- snd_soc_unregister_codec(codec);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
err_get:
regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
-err:
- kfree(wm8523);
+
return ret;
}
-static void wm8523_unregister(struct wm8523_priv *wm8523)
+static int wm8523_remove(struct snd_soc_codec *codec)
{
- wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF);
+ struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+
+ wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
- snd_soc_unregister_dai(&wm8523_dai);
- snd_soc_unregister_codec(&wm8523->codec);
- kfree(wm8523);
- wm8523_codec = NULL;
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8523 = {
+ .probe = wm8523_probe,
+ .remove = wm8523_remove,
+ .suspend = wm8523_suspend,
+ .resume = wm8523_resume,
+ .set_bias_level = wm8523_set_bias_level,
+ .reg_cache_size = WM8523_REGISTER_COUNT,
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8523_reg,
+ .volatile_register = wm8523_volatile_register,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8523_priv *wm8523;
- struct snd_soc_codec *codec;
+ int ret;
wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL);
if (wm8523 == NULL)
return -ENOMEM;
- codec = &wm8523->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
i2c_set_clientdata(i2c, wm8523);
- codec->control_data = i2c;
+ wm8523->control_type = SND_SOC_I2C;
- codec->dev = &i2c->dev;
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8523, &wm8523_dai, 1);
+ if (ret < 0)
+ kfree(wm8523);
+ return ret;
- return wm8523_register(wm8523, SND_SOC_I2C);
}
static __devexit int wm8523_i2c_remove(struct i2c_client *client)
{
- struct wm8523_priv *wm8523 = i2c_get_clientdata(client);
- wm8523_unregister(wm8523);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -640,7 +550,7 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
static struct i2c_driver wm8523_i2c_driver = {
.driver = {
- .name = "WM8523",
+ .name = "wm8523-codec",
.owner = THIS_MODULE,
},
.probe = wm8523_i2c_probe,
diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h
index 1aa9ce3e1357..4d5b1eb8f2fc 100644
--- a/sound/soc/codecs/wm8523.h
+++ b/sound/soc/codecs/wm8523.h
@@ -154,7 +154,4 @@
#define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */
#define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */
-extern struct snd_soc_dai wm8523_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8523;
-
#endif
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 72deeabef4fe..a2e0ed59b376 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -94,6 +94,8 @@
#define WM8580_MAX_REGISTER 0x35
+#define WM8580_DACOSR 0x40
+
/* PLLB4 (register 7h) */
#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60
#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20
@@ -112,19 +114,7 @@
/* AIF control 1 (registers 9h-bh) */
#define WM8580_AIF_RATE_MASK 0x7
-#define WM8580_AIF_RATE_128 0x0
-#define WM8580_AIF_RATE_192 0x1
-#define WM8580_AIF_RATE_256 0x2
-#define WM8580_AIF_RATE_384 0x3
-#define WM8580_AIF_RATE_512 0x4
-#define WM8580_AIF_RATE_768 0x5
-#define WM8580_AIF_RATE_1152 0x6
-
#define WM8580_AIF_BCLKSEL_MASK 0x18
-#define WM8580_AIF_BCLKSEL_64 0x00
-#define WM8580_AIF_BCLKSEL_128 0x08
-#define WM8580_AIF_BCLKSEL_256 0x10
-#define WM8580_AIF_BCLKSEL_SYSCLK 0x18
#define WM8580_AIF_MS 0x20
@@ -199,11 +189,12 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
/* codec private data */
struct wm8580_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
u16 reg_cache[WM8580_MAX_REGISTER + 1];
struct pll_state a;
struct pll_state b;
+ int sysclk[2];
};
static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
@@ -273,8 +264,8 @@ SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1),
SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1),
SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1),
-SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0),
-SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
+SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 1),
+SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
};
static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
@@ -476,6 +467,10 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
return 0;
}
+static const int wm8580_sysclk_ratios[] = {
+ 128, 192, 256, 384, 512, 768, 1152,
+};
+
/*
* Set PCM DAI bit size and sample rate.
*/
@@ -484,29 +479,68 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
- u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id);
+ struct snd_soc_codec *codec = rtd->codec;
+ struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+ u16 paifa = 0;
+ u16 paifb = 0;
+ int i, ratio, osr;
- paifb &= ~WM8580_AIF_LENGTH_MASK;
/* bit size */
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
+ paifa |= 0x8;
break;
case SNDRV_PCM_FORMAT_S20_3LE:
+ paifa |= 0x10;
paifb |= WM8580_AIF_LENGTH_20;
break;
case SNDRV_PCM_FORMAT_S24_LE:
+ paifa |= 0x10;
paifb |= WM8580_AIF_LENGTH_24;
break;
case SNDRV_PCM_FORMAT_S32_LE:
+ paifa |= 0x10;
paifb |= WM8580_AIF_LENGTH_24;
break;
default:
return -EINVAL;
}
- snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb);
+ /* Look up the SYSCLK ratio; accept only exact matches */
+ ratio = wm8580->sysclk[dai->id] / params_rate(params);
+ for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++)
+ if (ratio == wm8580_sysclk_ratios[i])
+ break;
+ if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) {
+ dev_err(codec->dev, "Invalid clock ratio %d/%d\n",
+ wm8580->sysclk[dai->id], params_rate(params));
+ return -EINVAL;
+ }
+ paifa |= i;
+ dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n",
+ wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (ratio) {
+ case 128:
+ case 192:
+ osr = WM8580_DACOSR;
+ dev_dbg(codec->dev, "Selecting 64x OSR\n");
+ break;
+ default:
+ osr = 0;
+ dev_dbg(codec->dev, "Selecting 128x OSR\n");
+ break;
+ }
+
+ snd_soc_update_bits(codec, WM8580_PAIF3, WM8580_DACOSR, osr);
+ }
+
+ snd_soc_update_bits(codec, WM8580_PAIF1 + dai->driver->id,
+ WM8580_AIF_RATE_MASK | WM8580_AIF_BCLKSEL_MASK,
+ paifa);
+ snd_soc_update_bits(codec, WM8580_PAIF3 + dai->driver->id,
+ WM8580_AIF_LENGTH_MASK, paifb);
return 0;
}
@@ -518,8 +552,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int aifb;
int can_invert_lrclk;
- aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id);
- aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id);
+ aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id);
+ aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id);
aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
@@ -585,8 +619,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
- snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa);
- snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb);
+ snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa);
+ snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb);
return 0;
}
@@ -624,28 +658,6 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
snd_soc_write(codec, WM8580_PLLB4, reg);
break;
- case WM8580_DAC_CLKSEL:
- reg = snd_soc_read(codec, WM8580_CLKSEL);
- reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
-
- switch (div) {
- case WM8580_CLKSRC_MCLK:
- break;
-
- case WM8580_CLKSRC_PLLA:
- reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLA;
- break;
-
- case WM8580_CLKSRC_PLLB:
- reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLB;
- break;
-
- default:
- return -EINVAL;
- }
- snd_soc_write(codec, WM8580_CLKSEL, reg);
- break;
-
case WM8580_CLKOUTSRC:
reg = snd_soc_read(codec, WM8580_PLLB4);
reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
@@ -679,6 +691,55 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
return 0;
}
+static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+ int sel, sel_mask, sel_shift;
+
+ switch (dai->driver->id) {
+ case WM8580_DAI_PAIFRX:
+ sel_mask = 0x3;
+ sel_shift = 0;
+ break;
+
+ case WM8580_DAI_PAIFTX:
+ sel_mask = 0xc;
+ sel_shift = 2;
+ break;
+
+ default:
+ BUG_ON("Unknown DAI driver ID\n");
+ return -EINVAL;
+ }
+
+ switch (clk_id) {
+ case WM8580_CLKSRC_ADCMCLK:
+ if (dai->id != WM8580_DAI_PAIFTX)
+ return -EINVAL;
+ sel = 0 << sel_shift;
+ break;
+ case WM8580_CLKSRC_PLLA:
+ sel = 1 << sel_shift;
+ break;
+ case WM8580_CLKSRC_PLLB:
+ sel = 2 << sel_shift;
+ break;
+ case WM8580_CLKSRC_MCLK:
+ sel = 3 << sel_shift;
+ break;
+ default:
+ dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ /* We really should validate PLL settings but not yet */
+ wm8580->sysclk[dai->id] = freq;
+
+ return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel);
+}
+
static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
{
struct snd_soc_codec *codec = codec_dai->codec;
@@ -732,6 +793,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
+ .set_sysclk = wm8580_set_sysclk,
.hw_params = wm8580_paif_hw_params,
.set_fmt = wm8580_set_paif_dai_fmt,
.set_clkdiv = wm8580_set_dai_clkdiv,
@@ -740,16 +802,17 @@ static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
};
static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
+ .set_sysclk = wm8580_set_sysclk,
.hw_params = wm8580_paif_hw_params,
.set_fmt = wm8580_set_paif_dai_fmt,
.set_clkdiv = wm8580_set_dai_clkdiv,
.set_pll = wm8580_set_dai_pll,
};
-struct snd_soc_dai wm8580_dai[] = {
+static struct snd_soc_dai_driver wm8580_dai[] = {
{
- .name = "WM8580 PAIFRX",
- .id = 0,
+ .name = "wm8580-hifi-playback",
+ .id = WM8580_DAI_PAIFRX,
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -760,8 +823,8 @@ struct snd_soc_dai wm8580_dai[] = {
.ops = &wm8580_dai_ops_playback,
},
{
- .name = "WM8580 PAIFTX",
- .id = 1,
+ .name = "wm8580-hifi-capture",
+ .id = WM8580_DAI_PAIFTX,
.capture = {
.stream_name = "Capture",
.channels_min = 2,
@@ -772,90 +835,16 @@ struct snd_soc_dai wm8580_dai[] = {
.ops = &wm8580_dai_ops_capture,
},
};
-EXPORT_SYMBOL_GPL(wm8580_dai);
-
-static struct snd_soc_codec *wm8580_codec;
-static int wm8580_probe(struct platform_device *pdev)
+static int wm8580_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8580_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8580_codec;
- codec = wm8580_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8580_snd_controls,
- ARRAY_SIZE(wm8580_snd_controls));
- wm8580_add_widgets(codec);
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-/* power down chip */
-static int wm8580_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8580 = {
- .probe = wm8580_probe,
- .remove = wm8580_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
-
-static int wm8580_register(struct wm8580_priv *wm8580,
- enum snd_soc_control_type control)
-{
- int ret, i;
- struct snd_soc_codec *codec = &wm8580->codec;
-
- if (wm8580_codec) {
- dev_err(codec->dev, "Another WM8580 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8580);
- codec->name = "WM8580";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8580_set_bias_level;
- codec->dai = wm8580_dai;
- codec->num_dai = ARRAY_SIZE(wm8580_dai);
- codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache);
- codec->reg_cache = &wm8580->reg_cache;
-
- memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
+ struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0,i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
@@ -865,7 +854,7 @@ static int wm8580_register(struct wm8580_priv *wm8580,
wm8580->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
@@ -882,74 +871,68 @@ static int wm8580_register(struct wm8580_priv *wm8580,
goto err_regulator_enable;
}
- for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
- wm8580_dai[i].dev = codec->dev;
-
wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- wm8580_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err_regulator_enable;
- }
-
- ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
+ snd_soc_add_controls(codec, wm8580_snd_controls,
+ ARRAY_SIZE(wm8580_snd_controls));
+ wm8580_add_widgets(codec);
return 0;
-err_codec:
- snd_soc_unregister_codec(codec);
err_regulator_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
err_regulator_get:
regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
-err:
- kfree(wm8580);
return ret;
}
-static void wm8580_unregister(struct wm8580_priv *wm8580)
+/* power down chip */
+static int wm8580_remove(struct snd_soc_codec *codec)
{
- wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
- snd_soc_unregister_codec(&wm8580->codec);
+ struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+
+ wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
- kfree(wm8580);
- wm8580_codec = NULL;
+
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
+ .probe = wm8580_probe,
+ .remove = wm8580_remove,
+ .set_bias_level = wm8580_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8580_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = &wm8580_reg,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int wm8580_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8580_priv *wm8580;
- struct snd_soc_codec *codec;
+ int ret;
wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
if (wm8580 == NULL)
return -ENOMEM;
- codec = &wm8580->codec;
-
i2c_set_clientdata(i2c, wm8580);
- codec->control_data = i2c;
+ wm8580->control_type = SND_SOC_I2C;
- codec->dev = &i2c->dev;
-
- return wm8580_register(wm8580, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai));
+ if (ret < 0)
+ kfree(wm8580);
+ return ret;
}
static int wm8580_i2c_remove(struct i2c_client *client)
{
- struct wm8580_priv *wm8580 = i2c_get_clientdata(client);
- wm8580_unregister(wm8580);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -961,7 +944,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
static struct i2c_driver wm8580_i2c_driver = {
.driver = {
- .name = "wm8580",
+ .name = "wm8580-codec",
.owner = THIS_MODULE,
},
.probe = wm8580_i2c_probe,
@@ -972,7 +955,7 @@ static struct i2c_driver wm8580_i2c_driver = {
static int __init wm8580_modinit(void)
{
- int ret;
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8580_i2c_driver);
@@ -981,7 +964,7 @@ static int __init wm8580_modinit(void)
}
#endif
- return 0;
+ return ret;
}
module_init(wm8580_modinit);
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h
index 0dfb5ddde6a2..1d34656d0dcb 100644
--- a/sound/soc/codecs/wm8580.h
+++ b/sound/soc/codecs/wm8580.h
@@ -19,20 +19,17 @@
#define WM8580_PLLB 2
#define WM8580_MCLK 1
-#define WM8580_DAC_CLKSEL 2
-#define WM8580_CLKOUTSRC 3
+#define WM8580_CLKOUTSRC 2
-#define WM8580_CLKSRC_MCLK 1
-#define WM8580_CLKSRC_PLLA 2
-#define WM8580_CLKSRC_PLLB 3
-#define WM8580_CLKSRC_OSC 4
-#define WM8580_CLKSRC_NONE 5
+#define WM8580_CLKSRC_MCLK 1
+#define WM8580_CLKSRC_PLLA 2
+#define WM8580_CLKSRC_PLLB 3
+#define WM8580_CLKSRC_OSC 4
+#define WM8580_CLKSRC_NONE 5
+#define WM8580_CLKSRC_ADCMCLK 6
#define WM8580_DAI_PAIFRX 0
#define WM8580_DAI_PAIFTX 1
-extern struct snd_soc_dai wm8580_dai[];
-extern struct snd_soc_codec_device soc_codec_dev_wm8580;
-
#endif
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index e2dba07f0260..54fbd76c8bca 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -31,11 +31,9 @@
#include "wm8711.h"
-static struct snd_soc_codec *wm8711_codec;
-
/* codec private data */
struct wm8711_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type bus_type;
u16 reg_cache[WM8711_CACHEREGNUM];
unsigned int sysclk;
};
@@ -163,7 +161,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
+ struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
int i = get_coeff(wm8711->sysclk, params_rate(params));
u16 srate = (coeff_div[i].sr << 2) |
@@ -227,7 +225,7 @@ static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
+ struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
switch (freq) {
case 11289600:
@@ -338,8 +336,8 @@ static struct snd_soc_dai_ops wm8711_ops = {
.set_fmt = wm8711_set_dai_fmt,
};
-struct snd_soc_dai wm8711_dai = {
- .name = "WM8711",
+static struct snd_soc_dai_driver wm8711_dai = {
+ .name = "wm8711-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -349,22 +347,16 @@ struct snd_soc_dai wm8711_dai = {
},
.ops = &wm8711_ops,
};
-EXPORT_SYMBOL_GPL(wm8711_dai);
-static int wm8711_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
snd_soc_write(codec, WM8711_ACTIVE, 0x0);
wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8711_resume(struct platform_device *pdev)
+static int wm8711_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -380,99 +372,23 @@ static int wm8711_resume(struct platform_device *pdev)
return 0;
}
-static int wm8711_probe(struct platform_device *pdev)
+static int wm8711_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8711_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8711_codec;
- codec = wm8711_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8711_snd_controls,
- ARRAY_SIZE(wm8711_snd_controls));
- wm8711_add_widgets(codec);
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-/* power down chip */
-static int wm8711_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8711 = {
- .probe = wm8711_probe,
- .remove = wm8711_remove,
- .suspend = wm8711_suspend,
- .resume = wm8711_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711);
-
-static int wm8711_register(struct wm8711_priv *wm8711,
- enum snd_soc_control_type control)
-{
- int ret;
- struct snd_soc_codec *codec = &wm8711->codec;
- u16 reg;
-
- if (wm8711_codec) {
- dev_err(codec->dev, "Another WM8711 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8711);
- codec->name = "WM8711";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8711_set_bias_level;
- codec->dai = &wm8711_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8711_CACHEREGNUM;
- codec->reg_cache = &wm8711->reg_cache;
-
- memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg));
+ struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
+ int ret, reg;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
ret = wm8711_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
- goto err;
+ return ret;
}
- wm8711_dai.dev = codec->dev;
-
wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Latch the update bits */
@@ -481,70 +397,62 @@ static int wm8711_register(struct wm8711_priv *wm8711,
reg = snd_soc_read(codec, WM8711_ROUT1V);
snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
- wm8711_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&wm8711_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
- return 0;
+ snd_soc_add_controls(codec, wm8711_snd_controls,
+ ARRAY_SIZE(wm8711_snd_controls));
+ wm8711_add_widgets(codec);
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8711);
return ret;
+
}
-static void wm8711_unregister(struct wm8711_priv *wm8711)
+/* power down chip */
+static int wm8711_remove(struct snd_soc_codec *codec)
{
- wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm8711_dai);
- snd_soc_unregister_codec(&wm8711->codec);
- kfree(wm8711);
- wm8711_codec = NULL;
+ wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8711 = {
+ .probe = wm8711_probe,
+ .remove = wm8711_remove,
+ .suspend = wm8711_suspend,
+ .resume = wm8711_resume,
+ .set_bias_level = wm8711_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8711_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8711_reg,
+};
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8711_spi_probe(struct spi_device *spi)
{
- struct snd_soc_codec *codec;
struct wm8711_priv *wm8711;
+ int ret;
wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
if (wm8711 == NULL)
return -ENOMEM;
- codec = &wm8711->codec;
- codec->control_data = spi;
- codec->dev = &spi->dev;
+ spi_set_drvdata(spi, wm8711);
+ wm8711->bus_type = SND_SOC_SPI;
- dev_set_drvdata(&spi->dev, wm8711);
-
- return wm8711_register(wm8711, SND_SOC_SPI);
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8711, &wm8711_dai, 1);
+ if (ret < 0)
+ kfree(wm8711);
+ return ret;
}
static int __devexit wm8711_spi_remove(struct spi_device *spi)
{
- struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev);
-
- wm8711_unregister(wm8711);
-
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver wm8711_spi_driver = {
.driver = {
- .name = "wm8711",
- .bus = &spi_bus_type,
+ .name = "wm8711-codec",
.owner = THIS_MODULE,
},
.probe = wm8711_spi_probe,
@@ -553,31 +461,30 @@ static struct spi_driver wm8711_spi_driver = {
#endif /* CONFIG_SPI_MASTER */
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8711_i2c_probe(struct i2c_client *i2c,
+static __devinit int wm8711_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct wm8711_priv *wm8711;
- struct snd_soc_codec *codec;
+ int ret;
wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
if (wm8711 == NULL)
return -ENOMEM;
- codec = &wm8711->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
- i2c_set_clientdata(i2c, wm8711);
- codec->control_data = i2c;
+ i2c_set_clientdata(client, wm8711);
+ wm8711->bus_type = SND_SOC_I2C;
- codec->dev = &i2c->dev;
-
- return wm8711_register(wm8711, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&client->dev,
+ &soc_codec_dev_wm8711, &wm8711_dai, 1);
+ if (ret < 0)
+ kfree(wm8711);
+ return ret;
}
static __devexit int wm8711_i2c_remove(struct i2c_client *client)
{
- struct wm8711_priv *wm8711 = i2c_get_clientdata(client);
- wm8711_unregister(wm8711);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -589,7 +496,7 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
static struct i2c_driver wm8711_i2c_driver = {
.driver = {
- .name = "WM8711 I2C Codec",
+ .name = "wm8711-codec",
.owner = THIS_MODULE,
},
.probe = wm8711_i2c_probe,
diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h
index 381e84a43816..a61db985499f 100644
--- a/sound/soc/codecs/wm8711.h
+++ b/sound/soc/codecs/wm8711.h
@@ -36,7 +36,4 @@ struct wm8711_setup_data {
unsigned short i2c_address;
};
-extern struct snd_soc_dai wm8711_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8711;
-
#endif
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
index 9d1df2628136..748808285119 100644
--- a/sound/soc/codecs/wm8727.c
+++ b/sound/soc/codecs/wm8727.c
@@ -23,7 +23,6 @@
#include <sound/initval.h>
#include <sound/soc.h>
-#include "wm8727.h"
/*
* Note this is a simple chip with no configuration interface, sample rate is
* determined automatically by examining the Master clock and Bit clock ratios
@@ -33,8 +32,8 @@
SNDRV_PCM_RATE_192000)
-struct snd_soc_dai wm8727_dai = {
- .name = "WM8727",
+static struct snd_soc_dai_driver wm8727_dai = {
+ .name = "wm8727-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -43,103 +42,18 @@ struct snd_soc_dai wm8727_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
},
};
-EXPORT_SYMBOL_GPL(wm8727_dai);
-static struct snd_soc_codec *wm8727_codec;
+static struct snd_soc_codec_driver soc_codec_dev_wm8727;
-static int wm8727_soc_probe(struct platform_device *pdev)
+static __devinit int wm8727_probe(struct platform_device *pdev)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- int ret = 0;
-
- BUG_ON(!wm8727_codec);
-
- socdev->card->codec = wm8727_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "wm8727: failed to create pcms\n");
- goto pcm_err;
- }
-
- return ret;
-
-pcm_err:
- kfree(socdev->card->codec);
- socdev->card->codec = NULL;
- return ret;
-}
-
-static int wm8727_soc_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8727 = {
- .probe = wm8727_soc_probe,
- .remove = wm8727_soc_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727);
-
-
-static __devinit int wm8727_platform_probe(struct platform_device *pdev)
-{
- struct snd_soc_codec *codec;
- int ret;
-
- if (wm8727_codec) {
- dev_err(&pdev->dev, "Another WM8727 is registered\n");
- return -EBUSY;
- }
-
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
- wm8727_codec = codec;
-
- platform_set_drvdata(pdev, codec);
-
- mutex_init(&codec->mutex);
- codec->dev = &pdev->dev;
- codec->name = "WM8727";
- codec->owner = THIS_MODULE;
- codec->dai = &wm8727_dai;
- codec->num_dai = 1;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- wm8727_dai.dev = &pdev->dev;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to register CODEC: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&wm8727_dai);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
- return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(codec);
- return ret;
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_wm8727, &wm8727_dai, 1);
}
-static int __devexit wm8727_platform_remove(struct platform_device *pdev)
+static int __devexit wm8727_remove(struct platform_device *pdev)
{
- snd_soc_unregister_dai(&wm8727_dai);
- snd_soc_unregister_codec(platform_get_drvdata(pdev));
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
@@ -149,8 +63,8 @@ static struct platform_driver wm8727_codec_driver = {
.owner = THIS_MODULE,
},
- .probe = wm8727_platform_probe,
- .remove = __devexit_p(wm8727_platform_remove),
+ .probe = wm8727_probe,
+ .remove = __devexit_p(wm8727_remove),
};
static int __init wm8727_init(void)
diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h
deleted file mode 100644
index ee19aa71bcdc..000000000000
--- a/sound/soc/codecs/wm8727.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * wm8727.h
- *
- * Created on: 15-Oct-2009
- * Author: neil.jones@imgtec.com
- *
- * Copyright (C) 2009 Imagination Technologies Ltd.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef WM8727_H_
-#define WM8727_H_
-
-extern struct snd_soc_dai wm8727_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8727;
-
-#endif /* WM8727_H_ */
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 34be2d2b69ef..075f35e4f4cb 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -29,8 +29,6 @@
#include "wm8728.h"
-struct snd_soc_codec_device soc_codec_dev_wm8728;
-
/*
* We can't read the WM8728 register space so we cache them instead.
* Note that the defaults here aren't the physical defaults, we latch
@@ -44,6 +42,11 @@ static const u16 wm8728_reg_defaults[] = {
0x100,
};
+/* codec private data */
+struct wm8728_priv {
+ enum snd_soc_control_type control_type;
+};
+
static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
static const struct snd_kcontrol_new wm8728_snd_controls[] = {
@@ -96,8 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 dac = snd_soc_read(codec, WM8728_DACCTL);
dac &= ~0x18;
@@ -210,8 +212,8 @@ static struct snd_soc_dai_ops wm8728_dai_ops = {
.set_fmt = wm8728_set_dai_fmt,
};
-struct snd_soc_dai wm8728_dai = {
- .name = "WM8728",
+static struct snd_soc_dai_driver wm8728_dai = {
+ .name = "wm8728-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -221,63 +223,31 @@ struct snd_soc_dai wm8728_dai = {
},
.ops = &wm8728_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8728_dai);
-static int wm8728_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8728_resume(struct platform_device *pdev)
+static int wm8728_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
-/*
- * initialise the WM8728 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8728_init(struct snd_soc_device *socdev,
- enum snd_soc_control_type control)
+static int wm8728_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = socdev->card->codec;
- int ret = 0;
-
- codec->name = "WM8728";
- codec->owner = THIS_MODULE;
- codec->set_bias_level = wm8728_set_bias_level;
- codec->dai = &wm8728_dai;
- codec->num_dai = 1;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults);
- codec->reg_cache = kmemdup(wm8728_reg_defaults,
- sizeof(wm8728_reg_defaults),
- GFP_KERNEL);
- if (codec->reg_cache == NULL)
- return -ENOMEM;
+ struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec);
+ int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type);
if (ret < 0) {
printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
ret);
- goto err;
- }
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "wm8728: failed to create pcms\n");
- goto err;
+ return ret;
}
/* power on device */
@@ -288,215 +258,136 @@ static int wm8728_init(struct snd_soc_device *socdev,
wm8728_add_widgets(codec);
return ret;
-
-err:
- kfree(codec->reg_cache);
- return ret;
}
-static struct snd_soc_device *wm8728_socdev;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8728_remove(struct snd_soc_codec *codec)
+{
+ wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
-/*
- * WM8728 2 wire address is determined by GPIO5
- * state during powerup.
- * low = 0x1a
- * high = 0x1b
- */
+static struct snd_soc_codec_driver soc_codec_dev_wm8728 = {
+ .probe = wm8728_probe,
+ .remove = wm8728_remove,
+ .suspend = wm8728_suspend,
+ .resume = wm8728_resume,
+ .set_bias_level = wm8728_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8728_reg_defaults,
+};
-static int wm8728_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8728_spi_probe(struct spi_device *spi)
{
- struct snd_soc_device *socdev = wm8728_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct wm8728_priv *wm8728;
int ret;
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
+ wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL);
+ if (wm8728 == NULL)
+ return -ENOMEM;
+
+ wm8728->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8728);
- ret = wm8728_init(socdev, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8728, &wm8728_dai, 1);
if (ret < 0)
- pr_err("failed to initialise WM8728\n");
-
+ kfree(wm8728);
return ret;
}
-static int wm8728_i2c_remove(struct i2c_client *client)
+static int __devexit wm8728_spi_remove(struct spi_device *spi)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
return 0;
}
-static const struct i2c_device_id wm8728_i2c_id[] = {
- { "wm8728", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
-
-static struct i2c_driver wm8728_i2c_driver = {
+static struct spi_driver wm8728_spi_driver = {
.driver = {
- .name = "WM8728 I2C Codec",
- .owner = THIS_MODULE,
+ .name = "wm8728-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8728_i2c_probe,
- .remove = wm8728_i2c_remove,
- .id_table = wm8728_i2c_id,
+ .probe = wm8728_spi_probe,
+ .remove = __devexit_p(wm8728_spi_remove),
};
+#endif /* CONFIG_SPI_MASTER */
-static int wm8728_add_i2c_device(struct platform_device *pdev,
- const struct wm8728_setup_data *setup)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
+ struct wm8728_priv *wm8728;
int ret;
- ret = i2c_add_driver(&wm8728_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = setup->i2c_address;
- strlcpy(info.type, "wm8728", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n",
- setup->i2c_bus);
- goto err_driver;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
-
- return 0;
-
-err_driver:
- i2c_del_driver(&wm8728_i2c_driver);
- return -ENODEV;
-}
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8728_spi_probe(struct spi_device *spi)
-{
- struct snd_soc_device *socdev = wm8728_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
- int ret;
+ wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL);
+ if (wm8728 == NULL)
+ return -ENOMEM;
- codec->control_data = spi;
+ i2c_set_clientdata(i2c, wm8728);
+ wm8728->control_type = SND_SOC_I2C;
- ret = wm8728_init(socdev, SND_SOC_SPI);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8728, &wm8728_dai, 1);
if (ret < 0)
- dev_err(&spi->dev, "failed to initialise WM8728\n");
-
+ kfree(wm8728);
return ret;
}
-static int __devexit wm8728_spi_remove(struct spi_device *spi)
+static __devexit int wm8728_i2c_remove(struct i2c_client *client)
{
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
-static struct spi_driver wm8728_spi_driver = {
+static const struct i2c_device_id wm8728_i2c_id[] = {
+ { "wm8728", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
+
+static struct i2c_driver wm8728_i2c_driver = {
.driver = {
- .name = "wm8728",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
+ .name = "wm8728-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8728_spi_probe,
- .remove = __devexit_p(wm8728_spi_remove),
+ .probe = wm8728_i2c_probe,
+ .remove = __devexit_p(wm8728_i2c_remove),
+ .id_table = wm8728_i2c_id,
};
-#endif /* CONFIG_SPI_MASTER */
+#endif
-static int wm8728_probe(struct platform_device *pdev)
+static int __init wm8728_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8728_setup_data *setup;
- struct snd_soc_codec *codec;
int ret = 0;
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- socdev->card->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- wm8728_socdev = socdev;
- ret = -ENODEV;
-
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- ret = wm8728_add_i2c_device(pdev, setup);
+ ret = i2c_add_driver(&wm8728_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n",
+ ret);
}
#endif
#if defined(CONFIG_SPI_MASTER)
- if (setup->spi) {
- ret = spi_register_driver(&wm8728_spi_driver);
- if (ret != 0)
- printk(KERN_ERR "can't add spi driver");
+ ret = spi_register_driver(&wm8728_spi_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n",
+ ret);
}
#endif
-
- if (ret != 0)
- kfree(codec);
-
return ret;
}
+module_init(wm8728_modinit);
-/* power down chip */
-static int wm8728_remove(struct platform_device *pdev)
+static void __exit wm8728_exit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec->control_data)
- wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8728_i2c_driver);
#endif
#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver(&wm8728_spi_driver);
#endif
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8728 = {
- .probe = wm8728_probe,
- .remove = wm8728_remove,
- .suspend = wm8728_suspend,
- .resume = wm8728_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728);
-
-static int __init wm8728_modinit(void)
-{
- return snd_soc_register_dai(&wm8728_dai);
-}
-module_init(wm8728_modinit);
-
-static void __exit wm8728_exit(void)
-{
- snd_soc_unregister_dai(&wm8728_dai);
}
module_exit(wm8728_exit);
diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h
index d269c132474b..8aea362ffd47 100644
--- a/sound/soc/codecs/wm8728.h
+++ b/sound/soc/codecs/wm8728.h
@@ -18,13 +18,4 @@
#define WM8728_DACCTL 0x02
#define WM8728_IFCTL 0x03
-struct wm8728_setup_data {
- int spi;
- int i2c_bus;
- unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai wm8728_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8728;
-
#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 0ab9b6355297..e725c09a3e79 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -32,9 +32,6 @@
#include "wm8731.h"
-static struct snd_soc_codec *wm8731_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8731;
-
#define WM8731_NUM_SUPPLIES 4
static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
"AVDD",
@@ -45,10 +42,11 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
/* codec private data */
struct wm8731_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
u16 reg_cache[WM8731_CACHEREGNUM];
unsigned int sysclk;
+ int sysclk_type;
};
@@ -113,6 +111,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls =
SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0),
SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
&wm8731_output_mixer_controls[0],
ARRAY_SIZE(wm8731_output_mixer_controls)),
@@ -130,7 +129,18 @@ SND_SOC_DAPM_INPUT("RLINEIN"),
SND_SOC_DAPM_INPUT("LLINEIN"),
};
+static int wm8731_check_osc(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec);
+
+ return wm8731->sysclk_type == WM8731_SYSCLK_MCLK;
+}
+
static const struct snd_soc_dapm_route intercon[] = {
+ {"DAC", NULL, "OSC", wm8731_check_osc},
+ {"ADC", NULL, "OSC", wm8731_check_osc},
+
/* output mixer */
{"Output Mixer", "Line Bypass Switch", "Line Input"},
{"Output Mixer", "HiFi Playback Switch", "DAC"},
@@ -222,9 +232,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = dai->codec;
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
int i = get_coeff(wm8731->sysclk, params_rate(params));
@@ -252,9 +260,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = dai->codec;
/* set active */
snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
@@ -265,9 +271,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
static void wm8731_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = dai->codec;
/* deactivate */
if (!codec->active) {
@@ -294,6 +298,15 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec;
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
+ switch (clk_id) {
+ case WM8731_SYSCLK_XTAL:
+ case WM8731_SYSCLK_MCLK:
+ wm8731->sysclk_type = clk_id;
+ break;
+ default:
+ return -EINVAL;
+ }
+
switch (freq) {
case 11289600:
case 12000000:
@@ -301,9 +314,14 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
case 16934400:
case 18432000:
wm8731->sysclk = freq;
- return 0;
+ break;
+ default:
+ return -EINVAL;
}
- return -EINVAL;
+
+ snd_soc_dapm_sync(codec);
+
+ return 0;
}
@@ -428,8 +446,8 @@ static struct snd_soc_dai_ops wm8731_dai_ops = {
.set_fmt = wm8731_set_dai_fmt,
};
-struct snd_soc_dai wm8731_dai = {
- .name = "WM8731",
+static struct snd_soc_dai_driver wm8731_dai = {
+ .name = "wm8731-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -445,24 +463,17 @@ struct snd_soc_dai wm8731_dai = {
.ops = &wm8731_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8731_dai);
#ifdef CONFIG_PM
-static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8731_resume(struct platform_device *pdev)
+static int wm8731_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -472,88 +483,15 @@ static int wm8731_resume(struct platform_device *pdev)
#define wm8731_resume NULL
#endif
-static int wm8731_probe(struct platform_device *pdev)
+static int wm8731_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8731_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8731_codec;
- codec = wm8731_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8731_snd_controls,
- ARRAY_SIZE(wm8731_snd_controls));
- wm8731_add_widgets(codec);
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-/* power down chip */
-static int wm8731_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8731 = {
- .probe = wm8731_probe,
- .remove = wm8731_remove,
- .suspend = wm8731_suspend,
- .resume = wm8731_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
-
-static int wm8731_register(struct wm8731_priv *wm8731,
- enum snd_soc_control_type control)
-{
- int ret, i;
- struct snd_soc_codec *codec = &wm8731->codec;
-
- if (wm8731_codec) {
- dev_err(codec->dev, "Another WM8731 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8731);
- codec->name = "WM8731";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8731_set_bias_level;
- codec->dai = &wm8731_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8731_CACHEREGNUM;
- codec->reg_cache = &wm8731->reg_cache;
-
- memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
+ struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0, i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
@@ -563,7 +501,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
wm8731->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
@@ -579,8 +517,6 @@ static int wm8731_register(struct wm8731_priv *wm8731,
goto err_regulator_enable;
}
- wm8731_dai.dev = codec->dev;
-
wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Latch the update bits */
@@ -590,81 +526,80 @@ static int wm8731_register(struct wm8731_priv *wm8731,
snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
/* Disable bypass path by default */
- snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
-
- wm8731_codec = codec;
+ snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0);
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err_regulator_enable;
- }
-
- ret = snd_soc_register_dai(&wm8731_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- snd_soc_unregister_codec(codec);
- goto err_codec;
- }
+ snd_soc_add_controls(codec, wm8731_snd_controls,
+ ARRAY_SIZE(wm8731_snd_controls));
+ wm8731_add_widgets(codec);
/* Regulators will have been enabled by bias management */
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
return 0;
-err_codec:
- snd_soc_unregister_codec(codec);
err_regulator_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
err_regulator_get:
regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
-err:
+
kfree(wm8731);
return ret;
}
-static void wm8731_unregister(struct wm8731_priv *wm8731)
+/* power down chip */
+static int wm8731_remove(struct snd_soc_codec *codec)
{
- wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm8731_dai);
- snd_soc_unregister_codec(&wm8731->codec);
+ struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
+
+ wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
- kfree(wm8731);
- wm8731_codec = NULL;
+
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
+ .probe = wm8731_probe,
+ .remove = wm8731_remove,
+ .suspend = wm8731_suspend,
+ .resume = wm8731_resume,
+ .set_bias_level = wm8731_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8731_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8731_reg,
+};
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8731_spi_probe(struct spi_device *spi)
{
- struct snd_soc_codec *codec;
struct wm8731_priv *wm8731;
+ int ret;
wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
if (wm8731 == NULL)
return -ENOMEM;
- codec = &wm8731->codec;
- codec->control_data = spi;
- codec->dev = &spi->dev;
-
- dev_set_drvdata(&spi->dev, wm8731);
+ wm8731->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8731);
- return wm8731_register(wm8731, SND_SOC_SPI);
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8731, &wm8731_dai, 1);
+ if (ret < 0)
+ kfree(wm8731);
+ return ret;
}
static int __devexit wm8731_spi_remove(struct spi_device *spi)
{
- struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev);
-
- wm8731_unregister(wm8731);
-
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver wm8731_spi_driver = {
.driver = {
- .name = "wm8731",
- .bus = &spi_bus_type,
+ .name = "wm8731-codec",
.owner = THIS_MODULE,
},
.probe = wm8731_spi_probe,
@@ -677,26 +612,26 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8731_priv *wm8731;
- struct snd_soc_codec *codec;
+ int ret;
wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
if (wm8731 == NULL)
return -ENOMEM;
- codec = &wm8731->codec;
-
i2c_set_clientdata(i2c, wm8731);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
+ wm8731->control_type = SND_SOC_I2C;
- return wm8731_register(wm8731, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8731, &wm8731_dai, 1);
+ if (ret < 0)
+ kfree(wm8731);
+ return ret;
}
static __devexit int wm8731_i2c_remove(struct i2c_client *client)
{
- struct wm8731_priv *wm8731 = i2c_get_clientdata(client);
- wm8731_unregister(wm8731);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -708,7 +643,7 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
static struct i2c_driver wm8731_i2c_driver = {
.driver = {
- .name = "wm8731",
+ .name = "wm8731-codec",
.owner = THIS_MODULE,
},
.probe = wm8731_i2c_probe,
@@ -719,7 +654,7 @@ static struct i2c_driver wm8731_i2c_driver = {
static int __init wm8731_modinit(void)
{
- int ret;
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8731_i2c_driver);
if (ret != 0) {
@@ -734,7 +669,7 @@ static int __init wm8731_modinit(void)
ret);
}
#endif
- return 0;
+ return ret;
}
module_init(wm8731_modinit);
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h
index cd7b806e8ad0..e9c0c76ab73b 100644
--- a/sound/soc/codecs/wm8731.h
+++ b/sound/soc/codecs/wm8731.h
@@ -31,10 +31,9 @@
#define WM8731_CACHEREGNUM 10
-#define WM8731_SYSCLK 0
-#define WM8731_DAI 0
+#define WM8731_SYSCLK_XTAL 1
+#define WM8731_SYSCLK_MCLK 2
-extern struct snd_soc_dai wm8731_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8731;
+#define WM8731_DAI 0
#endif
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index b9ea8904ad4b..90e31e9aa6f7 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -30,25 +30,21 @@
#include "wm8741.h"
-static struct snd_soc_codec *wm8741_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8741;
-
#define WM8741_NUM_SUPPLIES 2
static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
"AVDD",
"DVDD",
};
-#define WM8741_NUM_RATES 4
+#define WM8741_NUM_RATES 6
/* codec private data */
struct wm8741_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
u16 reg_cache[WM8741_REGISTER_COUNT];
struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
unsigned int sysclk;
- unsigned int rate_constraint_list[WM8741_NUM_RATES];
- struct snd_pcm_hw_constraint_list rate_constraint;
+ struct snd_pcm_hw_constraint_list *sysclk_constraints;
};
static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = {
@@ -111,10 +107,84 @@ static struct {
int value;
int ratio;
} lrclk_ratios[WM8741_NUM_RATES] = {
- { 1, 256 },
- { 2, 384 },
- { 3, 512 },
- { 4, 768 },
+ { 1, 128 },
+ { 2, 192 },
+ { 3, 256 },
+ { 4, 384 },
+ { 5, 512 },
+ { 6, 768 },
+};
+
+static unsigned int rates_11289[] = {
+ 44100, 88235,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_11289 = {
+ .count = ARRAY_SIZE(rates_11289),
+ .list = rates_11289,
+};
+
+static unsigned int rates_12288[] = {
+ 32000, 48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_12288 = {
+ .count = ARRAY_SIZE(rates_12288),
+ .list = rates_12288,
+};
+
+static unsigned int rates_16384[] = {
+ 32000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_16384 = {
+ .count = ARRAY_SIZE(rates_16384),
+ .list = rates_16384,
+};
+
+static unsigned int rates_16934[] = {
+ 44100, 88235,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_16934 = {
+ .count = ARRAY_SIZE(rates_16934),
+ .list = rates_16934,
+};
+
+static unsigned int rates_18432[] = {
+ 48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_18432 = {
+ .count = ARRAY_SIZE(rates_18432),
+ .list = rates_18432,
+};
+
+static unsigned int rates_22579[] = {
+ 44100, 88235, 1764000
+};
+
+static struct snd_pcm_hw_constraint_list constraints_22579 = {
+ .count = ARRAY_SIZE(rates_22579),
+ .list = rates_22579,
+};
+
+static unsigned int rates_24576[] = {
+ 32000, 48000, 96000, 192000
+};
+
+static struct snd_pcm_hw_constraint_list constraints_24576 = {
+ .count = ARRAY_SIZE(rates_24576),
+ .list = rates_24576,
+};
+
+static unsigned int rates_36864[] = {
+ 48000, 96000, 19200
+};
+
+static struct snd_pcm_hw_constraint_list constraints_36864 = {
+ .count = ARRAY_SIZE(rates_36864),
+ .list = rates_36864,
};
@@ -135,7 +205,7 @@ static int wm8741_startup(struct snd_pcm_substream *substream,
snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
- &wm8741->rate_constraint);
+ wm8741->sysclk_constraints);
return 0;
}
@@ -145,8 +215,7 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
int i;
@@ -196,47 +265,52 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
- unsigned int val;
- int i;
dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq);
- wm8741->sysclk = freq;
-
- wm8741->rate_constraint.count = 0;
-
- for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
- dev_dbg(codec->dev, "index = %d, ratio = %d, freq = %d",
- i, lrclk_ratios[i].ratio, freq);
-
- val = freq / lrclk_ratios[i].ratio;
- /* Check that it's a standard rate since core can't
- * cope with others and having the odd rates confuses
- * constraint matching.
- */
- switch (val) {
- case 32000:
- case 44100:
- case 48000:
- case 64000:
- case 88200:
- case 96000:
- dev_dbg(codec->dev, "Supported sample rate: %dHz\n",
- val);
- wm8741->rate_constraint_list[i] = val;
- wm8741->rate_constraint.count++;
- break;
- default:
- dev_dbg(codec->dev, "Skipping sample rate: %dHz\n",
- val);
- }
+ switch (freq) {
+ case 11289600:
+ wm8741->sysclk_constraints = &constraints_11289;
+ wm8741->sysclk = freq;
+ return 0;
+
+ case 12288000:
+ wm8741->sysclk_constraints = &constraints_12288;
+ wm8741->sysclk = freq;
+ return 0;
+
+ case 16384000:
+ wm8741->sysclk_constraints = &constraints_16384;
+ wm8741->sysclk = freq;
+ return 0;
+
+ case 16934400:
+ wm8741->sysclk_constraints = &constraints_16934;
+ wm8741->sysclk = freq;
+ return 0;
+
+ case 18432000:
+ wm8741->sysclk_constraints = &constraints_18432;
+ wm8741->sysclk = freq;
+ return 0;
+
+ case 22579200:
+ case 33868800:
+ wm8741->sysclk_constraints = &constraints_22579;
+ wm8741->sysclk = freq;
+ return 0;
+
+ case 24576000:
+ wm8741->sysclk_constraints = &constraints_24576;
+ wm8741->sysclk = freq;
+ return 0;
+
+ case 36864000:
+ wm8741->sysclk_constraints = &constraints_36864;
+ wm8741->sysclk = freq;
+ return 0;
}
-
- /* Need at least one supported rate... */
- if (wm8741->rate_constraint.count == 0)
- return -EINVAL;
-
- return 0;
+ return -EINVAL;
}
static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -314,8 +388,8 @@ static struct snd_soc_dai_ops wm8741_dai_ops = {
.set_fmt = wm8741_set_dai_fmt,
};
-struct snd_soc_dai wm8741_dai = {
- .name = "WM8741",
+static struct snd_soc_dai_driver wm8741_dai = {
+ .name = "wm8741",
.playback = {
.stream_name = "Playback",
.channels_min = 2, /* Mono modes not yet supported */
@@ -325,13 +399,10 @@ struct snd_soc_dai wm8741_dai = {
},
.ops = &wm8741_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8741_dai);
#ifdef CONFIG_PM
-static int wm8741_resume(struct platform_device *pdev)
+static int wm8741_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
u16 *cache = codec->reg_cache;
int i;
@@ -348,189 +419,99 @@ static int wm8741_resume(struct platform_device *pdev)
#define wm8741_resume NULL
#endif
-static int wm8741_probe(struct platform_device *pdev)
+static int wm8741_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
+ struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
- if (wm8741_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
- socdev->card->codec = wm8741_codec;
- codec = wm8741_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ ret = wm8741_reset(codec);
if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
+ dev_err(codec->dev, "Failed to issue reset\n");
+ return ret;
}
+ /* Change some default settings - latch VU */
+ wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
+ wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
+ wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
+ wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
+
snd_soc_add_controls(codec, wm8741_snd_controls,
ARRAY_SIZE(wm8741_snd_controls));
wm8741_add_widgets(codec);
- return ret;
-
-pcm_err:
+ dev_dbg(codec->dev, "Successful registration\n");
return ret;
}
-static int wm8741_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8741 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {
.probe = wm8741_probe,
- .remove = wm8741_remove,
.resume = wm8741_resume,
+ .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = &wm8741_reg_defaults,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8741);
-static int wm8741_register(struct wm8741_priv *wm8741,
- enum snd_soc_control_type control)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8741_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- int ret;
- struct snd_soc_codec *codec = &wm8741->codec;
- int i;
-
- if (wm8741_codec) {
- dev_err(codec->dev, "Another WM8741 is registered\n");
- return -EINVAL;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8741);
- codec->name = "WM8741";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = NULL;
- codec->dai = &wm8741_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8741_REGISTER_COUNT;
- codec->reg_cache = &wm8741->reg_cache;
-
- wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0];
- wm8741->rate_constraint.count =
- ARRAY_SIZE(wm8741->rate_constraint_list);
-
- memcpy(codec->reg_cache, wm8741_reg_defaults,
- sizeof(wm8741->reg_cache));
+ struct wm8741_priv *wm8741;
+ int ret, i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
+ wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
+ if (wm8741 == NULL)
+ return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
wm8741->supplies[i].supply = wm8741_supply_names[i];
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies),
+ ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies),
wm8741->supplies);
if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
goto err;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
wm8741->supplies);
if (ret != 0) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+ dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
goto err_get;
}
- ret = wm8741_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- goto err_enable;
- }
-
- wm8741_dai.dev = codec->dev;
-
- /* Change some default settings - latch VU */
- wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
- wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
- wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
- wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
-
- wm8741_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- return ret;
- }
-
- ret = snd_soc_register_dai(&wm8741_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- snd_soc_unregister_codec(codec);
- return ret;
- }
+ i2c_set_clientdata(i2c, wm8741);
+ wm8741->control_type = SND_SOC_I2C;
- dev_dbg(codec->dev, "Successful registration\n");
- return 0;
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8741, &wm8741_dai, 1);
+ if (ret < 0)
+ goto err_enable;
+ return ret;
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
err_get:
regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
-
err:
kfree(wm8741);
return ret;
}
-static void wm8741_unregister(struct wm8741_priv *wm8741)
-{
- regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
-
- snd_soc_unregister_dai(&wm8741_dai);
- snd_soc_unregister_codec(&wm8741->codec);
- kfree(wm8741);
- wm8741_codec = NULL;
-}
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8741_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct wm8741_priv *wm8741;
- struct snd_soc_codec *codec;
-
- wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
- if (wm8741 == NULL)
- return -ENOMEM;
-
- codec = &wm8741->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
- i2c_set_clientdata(i2c, wm8741);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
-
- return wm8741_register(wm8741, SND_SOC_I2C);
-}
-
-static __devexit int wm8741_i2c_remove(struct i2c_client *client)
+static int wm8741_i2c_remove(struct i2c_client *client)
{
struct wm8741_priv *wm8741 = i2c_get_clientdata(client);
- wm8741_unregister(wm8741);
+
+ snd_soc_unregister_codec(&client->dev);
+ regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -540,29 +521,28 @@ static const struct i2c_device_id wm8741_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
-
static struct i2c_driver wm8741_i2c_driver = {
.driver = {
- .name = "WM8741",
+ .name = "wm8741-codec",
.owner = THIS_MODULE,
},
.probe = wm8741_i2c_probe,
- .remove = __devexit_p(wm8741_i2c_remove),
+ .remove = wm8741_i2c_remove,
.id_table = wm8741_i2c_id,
};
#endif
static int __init wm8741_modinit(void)
{
- int ret;
+ int ret = 0;
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8741_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8741 I2C driver: %d\n",
- ret);
- }
+ if (ret != 0)
+ pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
#endif
- return 0;
+
+ return ret;
}
module_init(wm8741_modinit);
diff --git a/sound/soc/codecs/wm8741.h b/sound/soc/codecs/wm8741.h
index fdef6ecd1f6f..56c1b1d4a681 100644
--- a/sound/soc/codecs/wm8741.h
+++ b/sound/soc/codecs/wm8741.h
@@ -208,7 +208,4 @@
#define WM8741_SYSCLK 0
-extern struct snd_soc_dai wm8741_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8741;
-
#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index e2c05e3e323a..6c924cd2cfd4 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -52,7 +52,7 @@ static const u16 wm8750_reg[] = {
/* codec private data */
struct wm8750_priv {
unsigned int sysclk;
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
u16 reg_cache[ARRAY_SIZE(wm8750_reg)];
};
@@ -560,8 +560,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
@@ -649,8 +648,8 @@ static struct snd_soc_dai_ops wm8750_dai_ops = {
.set_sysclk = wm8750_set_dai_sysclk,
};
-struct snd_soc_dai wm8750_dai = {
- .name = "WM8750",
+static struct snd_soc_dai_driver wm8750_dai = {
+ .name = "wm8750-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -665,21 +664,15 @@ struct snd_soc_dai wm8750_dai = {
.formats = WM8750_FORMATS,},
.ops = &wm8750_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8750_dai);
-static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8750_resume(struct platform_device *pdev)
+static int wm8750_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -698,100 +691,21 @@ static int wm8750_resume(struct platform_device *pdev)
return 0;
}
-static struct snd_soc_codec *wm8750_codec;
-
-static int wm8750_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (!wm8750_codec) {
- dev_err(&pdev->dev, "WM8750 codec not yet registered\n");
- return -EINVAL;
- }
-
- socdev->card->codec = wm8750_codec;
- codec = wm8750_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "wm8750: failed to create pcms\n");
- goto err;
- }
-
- snd_soc_add_controls(codec, wm8750_snd_controls,
- ARRAY_SIZE(wm8750_snd_controls));
- wm8750_add_widgets(codec);
-
- return 0;
-
-err:
- return ret;
-}
-
-/* power down chip */
-static int wm8750_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8750 = {
- .probe = wm8750_probe,
- .remove = wm8750_remove,
- .suspend = wm8750_suspend,
- .resume = wm8750_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
-
-/*
- * initialise the WM8750 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8750_register(struct wm8750_priv *wm8750,
- enum snd_soc_control_type control)
+static int wm8750_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = &wm8750->codec;
- int reg, ret = 0;
-
- if (wm8750_codec) {
- dev_err(codec->dev, "Multiple WM8750 devices not supported\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "WM8750";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_STANDBY;
- codec->set_bias_level = wm8750_set_bias_level;
- codec->dai = &wm8750_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1;
- codec->reg_cache = &wm8750->reg_cache;
- snd_soc_codec_set_drvdata(codec, wm8750);
-
- memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache));
+ struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
+ int reg, ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
ret = wm8750_reset(codec);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
- goto err;
+ return ret;
}
/* charge output caps */
@@ -815,150 +729,130 @@ static int wm8750_register(struct wm8750_priv *wm8750,
reg = snd_soc_read(codec, WM8750_RINVOL);
snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
- wm8750_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dais(&wm8750_dai, 1);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
- goto err_codec;
- }
-
- return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8750);
+ snd_soc_add_controls(codec, wm8750_snd_controls,
+ ARRAY_SIZE(wm8750_snd_controls));
+ wm8750_add_widgets(codec);
return ret;
}
-static void wm8750_unregister(struct wm8750_priv *wm8750)
+static int wm8750_remove(struct snd_soc_codec *codec)
{
- wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dais(&wm8750_dai, 1);
- snd_soc_unregister_codec(&wm8750->codec);
- kfree(wm8750);
- wm8750_codec = NULL;
+ wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-/*
- * WM8750 2 wire address is determined by GPIO5
- * state during powerup.
- * low = 0x1a
- * high = 0x1b
- */
+static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
+ .probe = wm8750_probe,
+ .remove = wm8750_remove,
+ .suspend = wm8750_suspend,
+ .resume = wm8750_resume,
+ .set_bias_level = wm8750_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8750_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8750_reg,
+};
-static int wm8750_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8750_spi_probe(struct spi_device *spi)
{
- struct snd_soc_codec *codec;
struct wm8750_priv *wm8750;
+ int ret;
wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
if (wm8750 == NULL)
return -ENOMEM;
- codec = &wm8750->codec;
- codec->control_data = i2c;
- i2c_set_clientdata(i2c, wm8750);
-
- codec->dev = &i2c->dev;
+ wm8750->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8750);
- return wm8750_register(wm8750, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8750, &wm8750_dai, 1);
+ if (ret < 0)
+ kfree(wm8750);
+ return ret;
}
-static int wm8750_i2c_remove(struct i2c_client *client)
+static int __devexit wm8750_spi_remove(struct spi_device *spi)
{
- struct wm8750_priv *wm8750 = i2c_get_clientdata(client);
- wm8750_unregister(wm8750);
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
return 0;
}
-static const struct i2c_device_id wm8750_i2c_id[] = {
- { "wm8750", 0 },
- { "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
-
-static struct i2c_driver wm8750_i2c_driver = {
+static struct spi_driver wm8750_spi_driver = {
.driver = {
- .name = "WM8750 I2C Codec",
- .owner = THIS_MODULE,
+ .name = "wm8750-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8750_i2c_probe,
- .remove = wm8750_i2c_remove,
- .id_table = wm8750_i2c_id,
+ .probe = wm8750_spi_probe,
+ .remove = __devexit_p(wm8750_spi_remove),
};
-#endif
+#endif /* CONFIG_SPI_MASTER */
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8750_spi_probe(struct spi_device *spi)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_codec *codec;
struct wm8750_priv *wm8750;
+ int ret;
wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
if (wm8750 == NULL)
return -ENOMEM;
- codec = &wm8750->codec;
- codec->control_data = spi;
- codec->dev = &spi->dev;
-
- dev_set_drvdata(&spi->dev, wm8750);
+ i2c_set_clientdata(i2c, wm8750);
+ wm8750->control_type = SND_SOC_I2C;
- return wm8750_register(wm8750, SND_SOC_SPI);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8750, &wm8750_dai, 1);
+ if (ret < 0)
+ kfree(wm8750);
+ return ret;
}
-static int __devexit wm8750_spi_remove(struct spi_device *spi)
+static __devexit int wm8750_i2c_remove(struct i2c_client *client)
{
- struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev);
- wm8750_unregister(wm8750);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
-static const struct spi_device_id wm8750_spi_id[] = {
+static const struct i2c_device_id wm8750_i2c_id[] = {
{ "wm8750", 0 },
{ "wm8987", 0 },
{ }
};
-MODULE_DEVICE_TABLE(spi, wm8750_spi_id);
+MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
-static struct spi_driver wm8750_spi_driver = {
+static struct i2c_driver wm8750_i2c_driver = {
.driver = {
- .name = "WM8750 SPI Codec",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
+ .name = "wm8750-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8750_spi_probe,
- .remove = __devexit_p(wm8750_spi_remove),
- .id_table = wm8750_spi_id,
+ .probe = wm8750_i2c_probe,
+ .remove = __devexit_p(wm8750_i2c_remove),
+ .id_table = wm8750_i2c_id,
};
#endif
static int __init wm8750_modinit(void)
{
- int ret;
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8750_i2c_driver);
- if (ret != 0)
- pr_err("Failed to register WM8750 I2C driver: %d\n", ret);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n",
+ ret);
+ }
#endif
#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&wm8750_spi_driver);
- if (ret != 0)
- pr_err("Failed to register WM8750 SPI driver: %d\n", ret);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n",
+ ret);
+ }
#endif
- return 0;
+ return ret;
}
module_init(wm8750_modinit);
diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h
index 1dc100e19cfe..121427c047fb 100644
--- a/sound/soc/codecs/wm8750.h
+++ b/sound/soc/codecs/wm8750.h
@@ -57,13 +57,4 @@
#define WM8750_SYSCLK 0
-struct wm8750_setup_data {
- int spi;
- int i2c_bus;
- unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai wm8750_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8750;
-
#endif
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index b59f349c5218..8f679a13f2bc 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -57,7 +57,7 @@ module_param(caps_charge, int, 0);
MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
- unsigned int mode);
+ struct snd_soc_dai *dai, unsigned int hifi);
/*
* wm8753 register cache
@@ -85,10 +85,11 @@ static const u16 wm8753_reg[] = {
/* codec private data */
struct wm8753_priv {
+ enum snd_soc_control_type control_type;
unsigned int sysclk;
unsigned int pcmclk;
- struct snd_soc_codec codec;
u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
+ int dai_func;
};
/*
@@ -228,6 +229,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+ struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
return 0;
@@ -235,8 +237,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
mode &= 0xfff3;
mode |= (ucontrol->value.integer.value[0] << 2);
- wm8753_write(codec, WM8753_IOCTL, mode);
- wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]);
+ wm8753->dai_func = ucontrol->value.integer.value[0];
return 1;
}
@@ -904,6 +905,13 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
+static int wm8753_pcm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ wm8753_set_dai_mode(dai->codec, dai, 0);
+ return 0;
+}
+
/*
* Set PCM DAI bit size and sample rate.
*/
@@ -912,8 +920,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
@@ -1138,6 +1145,13 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
+static int wm8753_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ wm8753_set_dai_mode(dai->codec, dai, 1);
+ return 0;
+}
+
/*
* Set PCM DAI bit size and sample rate.
*/
@@ -1146,8 +1160,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
@@ -1240,12 +1253,12 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
+ struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
/* the digital mute covers the HiFi and Voice DAC's on the WM8753.
* make sure we check if they are not both active when we mute */
- if (mute && dai->id == 1) {
- if (!wm8753_dai[WM8753_DAI_VOICE].playback.active ||
- !wm8753_dai[WM8753_DAI_HIFI].playback.active)
+ if (mute && wm8753->dai_func == 1) {
+ if (!codec->active)
wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
} else {
if (mute)
@@ -1303,6 +1316,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,
* 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
*/
static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {
+ .startup = wm8753_i2s_startup,
.hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode1h_set_dai_fmt,
@@ -1312,6 +1326,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {
};
static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {
+ .startup = wm8753_pcm_startup,
.hw_params = wm8753_pcm_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode1v_set_dai_fmt,
@@ -1321,6 +1336,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {
};
static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {
+ .startup = wm8753_pcm_startup,
.hw_params = wm8753_pcm_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode2_set_dai_fmt,
@@ -1330,6 +1346,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {
};
static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = {
+ .startup = wm8753_i2s_startup,
.hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode3_4_set_dai_fmt,
@@ -1339,6 +1356,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = {
};
static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = {
+ .startup = wm8753_i2s_startup,
.hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode3_4_set_dai_fmt,
@@ -1347,10 +1365,9 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = {
.set_sysclk = wm8753_set_dai_sysclk,
};
-static const struct snd_soc_dai wm8753_all_dai[] = {
+static struct snd_soc_dai_driver wm8753_all_dai[] = {
/* DAI HiFi mode 1 */
-{ .name = "WM8753 HiFi",
- .id = 1,
+{ .name = "wm8753-hifi",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -1366,8 +1383,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.ops = &wm8753_dai_ops_hifi_mode1,
},
/* DAI Voice mode 1 */
-{ .name = "WM8753 Voice",
- .id = 1,
+{ .name = "wm8753-voice",
.playback = {
.stream_name = "Voice Playback",
.channels_min = 1,
@@ -1383,12 +1399,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.ops = &wm8753_dai_ops_voice_mode1,
},
/* DAI HiFi mode 2 - dummy */
-{ .name = "WM8753 HiFi",
- .id = 2,
+{ .name = "wm8753-hifi",
},
/* DAI Voice mode 2 */
-{ .name = "WM8753 Voice",
- .id = 2,
+{ .name = "wm8753-voice",
.playback = {
.stream_name = "Voice Playback",
.channels_min = 1,
@@ -1404,8 +1418,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.ops = &wm8753_dai_ops_voice_mode2,
},
/* DAI HiFi mode 3 */
-{ .name = "WM8753 HiFi",
- .id = 3,
+{ .name = "wm8753-hifi",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -1421,12 +1434,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.ops = &wm8753_dai_ops_hifi_mode3,
},
/* DAI Voice mode 3 - dummy */
-{ .name = "WM8753 Voice",
- .id = 3,
+{ .name = "wm8753-voice",
},
/* DAI HiFi mode 4 */
-{ .name = "WM8753 HiFi",
- .id = 4,
+{ .name = "wm8753-hifi",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -1442,58 +1453,31 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.ops = &wm8753_dai_ops_hifi_mode4,
},
/* DAI Voice mode 4 - dummy */
-{ .name = "WM8753 Voice",
- .id = 4,
+{ .name = "wm8753-voice",
},
};
-struct snd_soc_dai wm8753_dai[] = {
+static struct snd_soc_dai_driver wm8753_dai[] = {
{
- .name = "WM8753 DAI 0",
+ .name = "wm8753-aif0",
},
{
- .name = "WM8753 DAI 1",
+ .name = "wm8753-aif1",
},
};
-EXPORT_SYMBOL_GPL(wm8753_dai);
-static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
+static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
+ struct snd_soc_dai *dai, unsigned int hifi)
{
- if (mode < 4) {
- int playback_active, capture_active, codec_active, pop_wait;
- void *private_data;
- struct list_head list;
-
- playback_active = wm8753_dai[0].playback.active;
- capture_active = wm8753_dai[0].capture.active;
- codec_active = wm8753_dai[0].active;
- private_data = wm8753_dai[0].private_data;
- pop_wait = wm8753_dai[0].pop_wait;
- list = wm8753_dai[0].list;
- wm8753_dai[0] = wm8753_all_dai[mode << 1];
- wm8753_dai[0].playback.active = playback_active;
- wm8753_dai[0].capture.active = capture_active;
- wm8753_dai[0].active = codec_active;
- wm8753_dai[0].private_data = private_data;
- wm8753_dai[0].pop_wait = pop_wait;
- wm8753_dai[0].list = list;
-
- playback_active = wm8753_dai[1].playback.active;
- capture_active = wm8753_dai[1].capture.active;
- codec_active = wm8753_dai[1].active;
- private_data = wm8753_dai[1].private_data;
- pop_wait = wm8753_dai[1].pop_wait;
- list = wm8753_dai[1].list;
- wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1];
- wm8753_dai[1].playback.active = playback_active;
- wm8753_dai[1].capture.active = capture_active;
- wm8753_dai[1].active = codec_active;
- wm8753_dai[1].private_data = private_data;
- wm8753_dai[1].pop_wait = pop_wait;
- wm8753_dai[1].list = list;
+ struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+
+ if (wm8753->dai_func < 4) {
+ if (hifi)
+ dai->driver = &wm8753_all_dai[wm8753->dai_func << 1];
+ else
+ dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
}
- wm8753_dai[0].codec = codec;
- wm8753_dai[1].codec = codec;
+ wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func);
}
static void wm8753_work(struct work_struct *work)
@@ -1503,19 +1487,14 @@ static void wm8753_work(struct work_struct *work)
wm8753_set_bias_level(codec, codec->bias_level);
}
-static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8753_resume(struct platform_device *pdev)
+static int wm8753_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -1547,41 +1526,6 @@ static int wm8753_resume(struct platform_device *pdev)
return 0;
}
-static struct snd_soc_codec *wm8753_codec;
-
-static int wm8753_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (!wm8753_codec) {
- dev_err(&pdev->dev, "WM8753 codec not yet registered\n");
- return -EINVAL;
- }
-
- socdev->card->codec = wm8753_codec;
- codec = wm8753_codec;
-
- wm8753_set_dai_mode(codec, 0);
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "wm8753: failed to create pcms\n");
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8753_snd_controls,
- ARRAY_SIZE(wm8753_snd_controls));
- wm8753_add_widgets(codec);
-
- return 0;
-
-pcm_err:
- return ret;
-}
-
/*
* This function forces any delayed work to be queued and run.
*/
@@ -1601,62 +1545,28 @@ static int run_delayed_work(struct delayed_work *dwork)
return ret;
}
-/* power down chip */
-static int wm8753_remove(struct platform_device *pdev)
+static int wm8753_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8753 = {
- .probe = wm8753_probe,
- .remove = wm8753_remove,
- .suspend = wm8753_suspend,
- .resume = wm8753_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
+ struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0, reg;
-static int wm8753_register(struct wm8753_priv *wm8753)
-{
- int ret, i;
- struct snd_soc_codec *codec = &wm8753->codec;
- u16 reg;
+ INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
- if (wm8753_codec) {
- dev_err(codec->dev, "Multiple WM8753 devices not supported\n");
- ret = -EINVAL;
- goto err;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "WM8753";
- codec->owner = THIS_MODULE;
- codec->read = wm8753_read_reg_cache;
- codec->write = wm8753_write;
- codec->bias_level = SND_SOC_BIAS_STANDBY;
- codec->set_bias_level = wm8753_set_bias_level;
- codec->dai = wm8753_dai;
- codec->num_dai = 2;
- codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1;
- codec->reg_cache = &wm8753->reg_cache;
- snd_soc_codec_set_drvdata(codec, wm8753);
-
- memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache));
- INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
-
ret = wm8753_reset(codec);
if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- goto err;
+ dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+ return ret;
}
+ wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ wm8753->dai_func = 0;
+
/* charge output caps */
wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
schedule_delayed_work(&codec->delayed_work,
@@ -1684,165 +1594,133 @@ static int wm8753_register(struct wm8753_priv *wm8753)
reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
- wm8753_codec = codec;
-
- for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++)
- wm8753_dai[i].dev = codec->dev;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
- goto err_codec;
- }
+ snd_soc_add_controls(codec, wm8753_snd_controls,
+ ARRAY_SIZE(wm8753_snd_controls));
+ wm8753_add_widgets(codec);
return 0;
-
-err_codec:
- run_delayed_work(&codec->delayed_work);
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8753);
- return ret;
}
-static void wm8753_unregister(struct wm8753_priv *wm8753)
+/* power down chip */
+static int wm8753_remove(struct snd_soc_codec *codec)
{
- wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF);
- run_delayed_work(&wm8753->codec.delayed_work);
- snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
- snd_soc_unregister_codec(&wm8753->codec);
- kfree(wm8753);
- wm8753_codec = NULL;
+ run_delayed_work(&codec->delayed_work);
+ wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
}
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
+ .probe = wm8753_probe,
+ .remove = wm8753_remove,
+ .suspend = wm8753_suspend,
+ .resume = wm8753_resume,
+ .set_bias_level = wm8753_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8753_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8753_reg,
+};
-static int wm8753_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8753_spi_probe(struct spi_device *spi)
{
- struct snd_soc_codec *codec;
struct wm8753_priv *wm8753;
+ int ret;
wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
if (wm8753 == NULL)
return -ENOMEM;
- codec = &wm8753->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
- codec->control_data = i2c;
- i2c_set_clientdata(i2c, wm8753);
-
- codec->dev = &i2c->dev;
+ wm8753->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8753);
- return wm8753_register(wm8753);
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
+ if (ret < 0)
+ kfree(wm8753);
+ return ret;
}
-static int wm8753_i2c_remove(struct i2c_client *client)
+static int __devexit wm8753_spi_remove(struct spi_device *spi)
{
- struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
- wm8753_unregister(wm8753);
- return 0;
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
+ return 0;
}
-static const struct i2c_device_id wm8753_i2c_id[] = {
- { "wm8753", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
-
-static struct i2c_driver wm8753_i2c_driver = {
+static struct spi_driver wm8753_spi_driver = {
.driver = {
- .name = "wm8753",
- .owner = THIS_MODULE,
+ .name = "wm8753-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8753_i2c_probe,
- .remove = wm8753_i2c_remove,
- .id_table = wm8753_i2c_id,
+ .probe = wm8753_spi_probe,
+ .remove = __devexit_p(wm8753_spi_remove),
};
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
-{
- struct spi_transfer t;
- struct spi_message m;
- u8 msg[2];
-
- if (len <= 0)
- return 0;
+#endif /* CONFIG_SPI_MASTER */
- msg[0] = data[0];
- msg[1] = data[1];
-
- spi_message_init(&m);
- memset(&t, 0, (sizeof t));
-
- t.tx_buf = &msg[0];
- t.len = len;
-
- spi_message_add_tail(&t, &m);
- spi_sync(spi, &m);
-
- return len;
-}
-
-static int __devinit wm8753_spi_probe(struct spi_device *spi)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_codec *codec;
struct wm8753_priv *wm8753;
+ int ret;
wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
if (wm8753 == NULL)
return -ENOMEM;
- codec = &wm8753->codec;
- codec->control_data = spi;
- codec->hw_write = (hw_write_t)wm8753_spi_write;
- codec->dev = &spi->dev;
+ i2c_set_clientdata(i2c, wm8753);
+ wm8753->control_type = SND_SOC_I2C;
- dev_set_drvdata(&spi->dev, wm8753);
-
- return wm8753_register(wm8753);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
+ if (ret < 0)
+ kfree(wm8753);
+ return ret;
}
-static int __devexit wm8753_spi_remove(struct spi_device *spi)
+static __devexit int wm8753_i2c_remove(struct i2c_client *client)
{
- struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev);
- wm8753_unregister(wm8753);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
-static struct spi_driver wm8753_spi_driver = {
+static const struct i2c_device_id wm8753_i2c_id[] = {
+ { "wm8753", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
+
+static struct i2c_driver wm8753_i2c_driver = {
.driver = {
- .name = "wm8753",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
+ .name = "wm8753-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8753_spi_probe,
- .remove = __devexit_p(wm8753_spi_remove),
+ .probe = wm8753_i2c_probe,
+ .remove = __devexit_p(wm8753_i2c_remove),
+ .id_table = wm8753_i2c_id,
};
#endif
static int __init wm8753_modinit(void)
{
- int ret;
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8753_i2c_driver);
- if (ret != 0)
- pr_err("Failed to register WM8753 I2C driver: %d\n", ret);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n",
+ ret);
+ }
#endif
#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&wm8753_spi_driver);
- if (ret != 0)
- pr_err("Failed to register WM8753 SPI driver: %d\n", ret);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8753 SPI driver: %d\n",
+ ret);
+ }
#endif
- return 0;
+ return ret;
}
module_init(wm8753_modinit);
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
index 57b2ba244040..94edac144bcb 100644
--- a/sound/soc/codecs/wm8753.h
+++ b/sound/soc/codecs/wm8753.h
@@ -115,7 +115,4 @@
#define WM8753_DAI_HIFI 0
#define WM8753_DAI_VOICE 1
-extern struct snd_soc_dai wm8753_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_wm8753;
-
#endif
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index f8154e661524..0132a27140ae 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -31,20 +31,12 @@
#include "wm8776.h"
-static struct snd_soc_codec *wm8776_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8776;
-
/* codec private data */
struct wm8776_priv {
- struct snd_soc_codec codec;
- u16 reg_cache[WM8776_CACHEREGNUM];
+ enum snd_soc_control_type control_type;
int sysclk[2];
};
-#ifdef CONFIG_SPI_MASTER
-static int wm8776_spi_write(struct spi_device *spi, const char *data, int len);
-#endif
-
static const u16 wm8776_reg[WM8776_CACHEREGNUM] = {
0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */
0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */
@@ -144,7 +136,7 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
struct snd_soc_codec *codec = dai->codec;
int reg, iface, master;
- switch (dai->id) {
+ switch (dai->driver->id) {
case WM8776_DAI_DAC:
reg = WM8776_DACIFCTRL;
master = 0x80;
@@ -226,7 +218,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
iface = 0;
- switch (dai->id) {
+ switch (dai->driver->id) {
case WM8776_DAI_DAC:
iface_reg = WM8776_DACIFCTRL;
master = 0x80;
@@ -260,7 +252,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
/* Only need to set MCLK/LRCLK ratio if we're master */
if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) {
for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) {
- if (wm8776->sysclk[dai->id] / params_rate(params)
+ if (wm8776->sysclk[dai->driver->id] / params_rate(params)
== mclk_ratios[i])
break;
}
@@ -268,7 +260,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
if (i == ARRAY_SIZE(mclk_ratios)) {
dev_err(codec->dev,
"Unable to configure MCLK ratio %d/%d\n",
- wm8776->sysclk[dai->id], params_rate(params));
+ wm8776->sysclk[dai->driver->id], params_rate(params));
return -EINVAL;
}
@@ -298,9 +290,9 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai,
struct snd_soc_codec *codec = dai->codec;
struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
- BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk));
+ BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk));
- wm8776->sysclk[dai->id] = freq;
+ wm8776->sysclk[dai->driver->id] = freq;
return 0;
}
@@ -350,10 +342,10 @@ static struct snd_soc_dai_ops wm8776_adc_ops = {
.set_sysclk = wm8776_set_sysclk,
};
-struct snd_soc_dai wm8776_dai[] = {
+static struct snd_soc_dai_driver wm8776_dai[] = {
{
- .name = "WM8776 Playback",
- .id = WM8776_DAI_DAC,
+ .name = "wm8776-hifi-playback",
+ .id = WM8776_DAI_DAC,
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -364,8 +356,8 @@ struct snd_soc_dai wm8776_dai[] = {
.ops = &wm8776_dac_ops,
},
{
- .name = "WM8776 Capture",
- .id = WM8776_DAI_ADC,
+ .name = "wm8776-hifi-capture",
+ .id = WM8776_DAI_ADC,
.capture = {
.stream_name = "Capture",
.channels_min = 2,
@@ -376,23 +368,17 @@ struct snd_soc_dai wm8776_dai[] = {
.ops = &wm8776_adc_ops,
},
};
-EXPORT_SYMBOL_GPL(wm8776_dai);
#ifdef CONFIG_PM
-static int wm8776_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8776_resume(struct platform_device *pdev)
+static int wm8776_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -415,27 +401,30 @@ static int wm8776_resume(struct platform_device *pdev)
#define wm8776_resume NULL
#endif
-static int wm8776_probe(struct platform_device *pdev)
+static int wm8776_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
+ struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
- if (wm8776_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
- socdev->card->codec = wm8776_codec;
- codec = wm8776_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ ret = wm8776_reset(codec);
if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
+ dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+ return ret;
}
+ wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ /* Latch the update bits; right channel only since we always
+ * update both. */
+ snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
+
snd_soc_add_controls(codec, wm8776_snd_controls,
ARRAY_SIZE(wm8776_snd_controls));
snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets,
@@ -443,169 +432,56 @@ static int wm8776_probe(struct platform_device *pdev)
snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
return ret;
-
-pcm_err:
- return ret;
}
/* power down chip */
-static int wm8776_remove(struct platform_device *pdev)
+static int wm8776_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
+ wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_wm8776 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm8776 = {
.probe = wm8776_probe,
.remove = wm8776_remove,
.suspend = wm8776_suspend,
.resume = wm8776_resume,
+ .set_bias_level = wm8776_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8776_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8776_reg,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776);
-
-static int wm8776_register(struct wm8776_priv *wm8776,
- enum snd_soc_control_type control)
-{
- int ret, i;
- struct snd_soc_codec *codec = &wm8776->codec;
-
- if (wm8776_codec) {
- dev_err(codec->dev, "Another WM8776 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8776);
- codec->name = "WM8776";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8776_set_bias_level;
- codec->dai = wm8776_dai;
- codec->num_dai = ARRAY_SIZE(wm8776_dai);
- codec->reg_cache_size = WM8776_CACHEREGNUM;
- codec->reg_cache = &wm8776->reg_cache;
-
- memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg));
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
-
- for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++)
- wm8776_dai[i].dev = codec->dev;
-
- ret = wm8776_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
- goto err;
- }
-
- wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- /* Latch the update bits; right channel only since we always
- * update both. */
- snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
- snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
-
- wm8776_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
- goto err_codec;
- }
-
- return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8776);
- return ret;
-}
-
-static void wm8776_unregister(struct wm8776_priv *wm8776)
-{
- wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
- snd_soc_unregister_codec(&wm8776->codec);
- kfree(wm8776);
- wm8776_codec = NULL;
-}
#if defined(CONFIG_SPI_MASTER)
-static int wm8776_spi_write(struct spi_device *spi, const char *data, int len)
-{
- struct spi_transfer t;
- struct spi_message m;
- u8 msg[2];
-
- if (len <= 0)
- return 0;
-
- msg[0] = data[0];
- msg[1] = data[1];
-
- spi_message_init(&m);
- memset(&t, 0, (sizeof t));
-
- t.tx_buf = &msg[0];
- t.len = len;
-
- spi_message_add_tail(&t, &m);
- spi_sync(spi, &m);
-
- return len;
-}
-
static int __devinit wm8776_spi_probe(struct spi_device *spi)
{
- struct snd_soc_codec *codec;
struct wm8776_priv *wm8776;
+ int ret;
wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
if (wm8776 == NULL)
return -ENOMEM;
- codec = &wm8776->codec;
- codec->control_data = spi;
- codec->hw_write = (hw_write_t)wm8776_spi_write;
- codec->dev = &spi->dev;
+ wm8776->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8776);
- dev_set_drvdata(&spi->dev, wm8776);
-
- return wm8776_register(wm8776, SND_SOC_SPI);
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
+ if (ret < 0)
+ kfree(wm8776);
+ return ret;
}
static int __devexit wm8776_spi_remove(struct spi_device *spi)
{
- struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev);
-
- wm8776_unregister(wm8776);
-
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver wm8776_spi_driver = {
.driver = {
- .name = "wm8776",
- .bus = &spi_bus_type,
+ .name = "wm8776-codec",
.owner = THIS_MODULE,
},
.probe = wm8776_spi_probe,
@@ -618,27 +494,26 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8776_priv *wm8776;
- struct snd_soc_codec *codec;
+ int ret;
wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
if (wm8776 == NULL)
return -ENOMEM;
- codec = &wm8776->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
i2c_set_clientdata(i2c, wm8776);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
+ wm8776->control_type = SND_SOC_I2C;
- return wm8776_register(wm8776, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
+ if (ret < 0)
+ kfree(wm8776);
+ return ret;
}
static __devexit int wm8776_i2c_remove(struct i2c_client *client)
{
- struct wm8776_priv *wm8776 = i2c_get_clientdata(client);
- wm8776_unregister(wm8776);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -650,7 +525,7 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
static struct i2c_driver wm8776_i2c_driver = {
.driver = {
- .name = "wm8776",
+ .name = "wm8776-codec",
.owner = THIS_MODULE,
},
.probe = wm8776_i2c_probe,
@@ -661,22 +536,22 @@ static struct i2c_driver wm8776_i2c_driver = {
static int __init wm8776_modinit(void)
{
- int ret;
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8776_i2c_driver);
if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n",
+ printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n",
ret);
}
#endif
#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&wm8776_spi_driver);
if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n",
+ printk(KERN_ERR "Failed to register wm8776 SPI driver: %d\n",
ret);
}
#endif
- return 0;
+ return ret;
}
module_init(wm8776_modinit);
diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h
index 6606d25d2d83..4cf1c8e0bfc9 100644
--- a/sound/soc/codecs/wm8776.h
+++ b/sound/soc/codecs/wm8776.h
@@ -45,7 +45,4 @@
#define WM8776_DAI_DAC 0
#define WM8776_DAI_ADC 1
-extern struct snd_soc_dai wm8776_dai[];
-extern struct snd_soc_codec_device soc_codec_dev_wm8776;
-
#endif
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
new file mode 100644
index 000000000000..4599e8e95aa2
--- /dev/null
+++ b/sound/soc/codecs/wm8804.c
@@ -0,0 +1,833 @@
+/*
+ * wm8804.c -- WM8804 S/PDIF transceiver driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8804.h"
+
+#define WM8804_NUM_SUPPLIES 2
+static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
+ "PVDD",
+ "DVDD"
+};
+
+static const u8 wm8804_reg_defs[] = {
+ 0x05, /* R0 - RST/DEVID1 */
+ 0x88, /* R1 - DEVID2 */
+ 0x04, /* R2 - DEVREV */
+ 0x21, /* R3 - PLL1 */
+ 0xFD, /* R4 - PLL2 */
+ 0x36, /* R5 - PLL3 */
+ 0x07, /* R6 - PLL4 */
+ 0x16, /* R7 - PLL5 */
+ 0x18, /* R8 - PLL6 */
+ 0xFF, /* R9 - SPDMODE */
+ 0x00, /* R10 - INTMASK */
+ 0x00, /* R11 - INTSTAT */
+ 0x00, /* R12 - SPDSTAT */
+ 0x00, /* R13 - RXCHAN1 */
+ 0x00, /* R14 - RXCHAN2 */
+ 0x00, /* R15 - RXCHAN3 */
+ 0x00, /* R16 - RXCHAN4 */
+ 0x00, /* R17 - RXCHAN5 */
+ 0x00, /* R18 - SPDTX1 */
+ 0x00, /* R19 - SPDTX2 */
+ 0x00, /* R20 - SPDTX3 */
+ 0x71, /* R21 - SPDTX4 */
+ 0x0B, /* R22 - SPDTX5 */
+ 0x70, /* R23 - GPO0 */
+ 0x57, /* R24 - GPO1 */
+ 0x00, /* R25 */
+ 0x42, /* R26 - GPO2 */
+ 0x06, /* R27 - AIFTX */
+ 0x06, /* R28 - AIFRX */
+ 0x80, /* R29 - SPDRX1 */
+ 0x07, /* R30 - PWRDN */
+};
+
+struct wm8804_priv {
+ enum snd_soc_control_type control_type;
+ struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
+ struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
+ struct snd_soc_codec *codec;
+};
+
+static int txsrc_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+static int txsrc_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+/*
+ * We can't use the same notifier block for more than one supply and
+ * there's no way I can see to get from a callback to the caller
+ * except container_of().
+ */
+#define WM8804_REGULATOR_EVENT(n) \
+static int wm8804_regulator_event_##n(struct notifier_block *nb, \
+ unsigned long event, void *data) \
+{ \
+ struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
+ disable_nb[n]); \
+ if (event & REGULATOR_EVENT_DISABLE) { \
+ wm8804->codec->cache_sync = 1; \
+ } \
+ return 0; \
+}
+
+WM8804_REGULATOR_EVENT(0)
+WM8804_REGULATOR_EVENT(1)
+
+static const char *txsrc_text[] = { "S/PDIF RX", "AIF" };
+static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text);
+
+static const struct snd_kcontrol_new wm8804_snd_controls[] = {
+ SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put),
+ SOC_SINGLE("TX Playback Switch", WM8804_PWRDN, 2, 1, 1),
+ SOC_SINGLE("AIF Playback Switch", WM8804_PWRDN, 4, 1, 1)
+};
+
+static int txsrc_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec;
+ unsigned int src;
+
+ codec = snd_kcontrol_chip(kcontrol);
+ src = snd_soc_read(codec, WM8804_SPDTX4);
+ if (src & 0x40)
+ ucontrol->value.integer.value[0] = 1;
+ else
+ ucontrol->value.integer.value[0] = 0;
+
+ return 0;
+}
+
+static int txsrc_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec;
+ unsigned int src, txpwr;
+
+ codec = snd_kcontrol_chip(kcontrol);
+
+ if (ucontrol->value.integer.value[0] != 0
+ && ucontrol->value.integer.value[0] != 1)
+ return -EINVAL;
+
+ src = snd_soc_read(codec, WM8804_SPDTX4);
+ switch ((src & 0x40) >> 6) {
+ case 0:
+ if (!ucontrol->value.integer.value[0])
+ return 0;
+ break;
+ case 1:
+ if (ucontrol->value.integer.value[1])
+ return 0;
+ break;
+ }
+
+ /* save the current power state of the transmitter */
+ txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4;
+ /* power down the transmitter */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4);
+ /* set the tx source */
+ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x40,
+ ucontrol->value.integer.value[0] << 6);
+
+ if (ucontrol->value.integer.value[0]) {
+ /* power down the receiver */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0x2);
+ /* power up the AIF */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x10, 0);
+ } else {
+ /* don't power down the AIF -- may be used as an output */
+ /* power up the receiver */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0);
+ }
+
+ /* restore the transmitter's configuration */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr);
+
+ return 0;
+}
+
+static int wm8804_volatile(unsigned int reg)
+{
+ switch (reg) {
+ case WM8804_RST_DEVID1:
+ case WM8804_DEVID2:
+ case WM8804_DEVREV:
+ case WM8804_INTSTAT:
+ case WM8804_SPDSTAT:
+ case WM8804_RXCHAN1:
+ case WM8804_RXCHAN2:
+ case WM8804_RXCHAN3:
+ case WM8804_RXCHAN4:
+ case WM8804_RXCHAN5:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int wm8804_reset(struct snd_soc_codec *codec)
+{
+ return snd_soc_write(codec, WM8804_RST_DEVID1, 0x0);
+}
+
+static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec;
+ u16 format, master, bcp, lrp;
+
+ codec = dai->codec;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ format = 0x2;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ format = 0x0;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ format = 0x1;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ format = 0x3;
+ break;
+ default:
+ dev_err(dai->dev, "Unknown dai format\n");
+ return -EINVAL;
+ }
+
+ /* set data format */
+ snd_soc_update_bits(codec, WM8804_AIFTX, 0x3, format);
+ snd_soc_update_bits(codec, WM8804_AIFRX, 0x3, format);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ master = 0;
+ break;
+ default:
+ dev_err(dai->dev, "Unknown master/slave configuration\n");
+ return -EINVAL;
+ }
+
+ /* set master/slave mode */
+ snd_soc_update_bits(codec, WM8804_AIFRX, 0x40, master << 6);
+
+ bcp = lrp = 0;
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ bcp = lrp = 1;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ bcp = 1;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ lrp = 1;
+ break;
+ default:
+ dev_err(dai->dev, "Unknown polarity configuration\n");
+ return -EINVAL;
+ }
+
+ /* set frame inversion */
+ snd_soc_update_bits(codec, WM8804_AIFTX, 0x10 | 0x20,
+ (bcp << 4) | (lrp << 5));
+ snd_soc_update_bits(codec, WM8804_AIFRX, 0x10 | 0x20,
+ (bcp << 4) | (lrp << 5));
+ return 0;
+}
+
+static int wm8804_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec;
+ u16 blen;
+
+ codec = dai->codec;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ blen = 0x0;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ blen = 0x1;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ blen = 0x2;
+ break;
+ default:
+ dev_err(dai->dev, "Unsupported word length: %u\n",
+ params_format(params));
+ return -EINVAL;
+ }
+
+ /* set word length */
+ snd_soc_update_bits(codec, WM8804_AIFTX, 0xc, blen << 2);
+ snd_soc_update_bits(codec, WM8804_AIFRX, 0xc, blen << 2);
+
+ return 0;
+}
+
+struct pll_div {
+ u32 prescale:1;
+ u32 mclkdiv:1;
+ u32 freqmode:2;
+ u32 n:4;
+ u32 k:22;
+};
+
+/* PLL rate to output rate divisions */
+static struct {
+ unsigned int div;
+ unsigned int freqmode;
+ unsigned int mclkdiv;
+} post_table[] = {
+ { 2, 0, 0 },
+ { 4, 0, 1 },
+ { 4, 1, 0 },
+ { 8, 1, 1 },
+ { 8, 2, 0 },
+ { 16, 2, 1 },
+ { 12, 3, 0 },
+ { 24, 3, 1 }
+};
+
+#define FIXED_PLL_SIZE ((1ULL << 22) * 10)
+static int pll_factors(struct pll_div *pll_div, unsigned int target,
+ unsigned int source)
+{
+ u64 Kpart;
+ unsigned long int K, Ndiv, Nmod, tmp;
+ int i;
+
+ /*
+ * Scale the output frequency up; the PLL should run in the
+ * region of 90-100MHz.
+ */
+ for (i = 0; i < ARRAY_SIZE(post_table); i++) {
+ tmp = target * post_table[i].div;
+ if (tmp >= 90000000 && tmp <= 100000000) {
+ pll_div->freqmode = post_table[i].freqmode;
+ pll_div->mclkdiv = post_table[i].mclkdiv;
+ target *= post_table[i].div;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(post_table)) {
+ pr_err("%s: Unable to scale output frequency: %uHz\n",
+ __func__, target);
+ return -EINVAL;
+ }
+
+ pll_div->prescale = 0;
+ Ndiv = target / source;
+ if (Ndiv < 5) {
+ source >>= 1;
+ pll_div->prescale = 1;
+ Ndiv = target / source;
+ }
+
+ if (Ndiv < 5 || Ndiv > 13) {
+ pr_err("%s: WM8804 N value is not within the recommended range: %lu\n",
+ __func__, Ndiv);
+ return -EINVAL;
+ }
+ pll_div->n = Ndiv;
+
+ Nmod = target % source;
+ Kpart = FIXED_PLL_SIZE * (u64)Nmod;
+
+ do_div(Kpart, source);
+
+ K = Kpart & 0xffffffff;
+ if ((K % 10) >= 5)
+ K += 5;
+ K /= 10;
+ pll_div->k = K;
+
+ return 0;
+}
+
+static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id,
+ int source, unsigned int freq_in,
+ unsigned int freq_out)
+{
+ struct snd_soc_codec *codec;
+
+ codec = dai->codec;
+ if (!freq_in || !freq_out) {
+ /* disable the PLL */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1);
+ return 0;
+ } else {
+ int ret;
+ struct pll_div pll_div;
+
+ ret = pll_factors(&pll_div, freq_out, freq_in);
+ if (ret)
+ return ret;
+
+ /* power down the PLL before reprogramming it */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1);
+
+ if (!freq_in || !freq_out)
+ return 0;
+
+ /* set PLLN and PRESCALE */
+ snd_soc_update_bits(codec, WM8804_PLL4, 0xf | 0x10,
+ pll_div.n | (pll_div.prescale << 4));
+ /* set mclkdiv and freqmode */
+ snd_soc_update_bits(codec, WM8804_PLL5, 0x3 | 0x8,
+ pll_div.freqmode | (pll_div.mclkdiv << 3));
+ /* set PLLK */
+ snd_soc_write(codec, WM8804_PLL1, pll_div.k & 0xff);
+ snd_soc_write(codec, WM8804_PLL2, (pll_div.k >> 8) & 0xff);
+ snd_soc_write(codec, WM8804_PLL3, pll_div.k >> 16);
+
+ /* power up the PLL */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0);
+ }
+
+ return 0;
+}
+
+static int wm8804_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec;
+
+ codec = dai->codec;
+
+ switch (clk_id) {
+ case WM8804_TX_CLKSRC_MCLK:
+ if ((freq >= 10000000 && freq <= 14400000)
+ || (freq >= 16280000 && freq <= 27000000))
+ snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0x80);
+ else {
+ dev_err(dai->dev, "OSCCLOCK is not within the "
+ "recommended range: %uHz\n", freq);
+ return -EINVAL;
+ }
+ break;
+ case WM8804_TX_CLKSRC_PLL:
+ snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0);
+ break;
+ case WM8804_CLKOUT_SRC_CLK1:
+ snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0);
+ break;
+ case WM8804_CLKOUT_SRC_OSCCLK:
+ snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0x8);
+ break;
+ default:
+ dev_err(dai->dev, "Unknown clock source: %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
+ int div_id, int div)
+{
+ struct snd_soc_codec *codec;
+
+ codec = dai->codec;
+ switch (div_id) {
+ case WM8804_CLKOUT_DIV:
+ snd_soc_update_bits(codec, WM8804_PLL5, 0x30,
+ (div & 0x3) << 4);
+ break;
+ default:
+ dev_err(dai->dev, "Unknown clock divider: %d\n", div_id);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void wm8804_sync_cache(struct snd_soc_codec *codec)
+{
+ short i;
+ u8 *cache;
+
+ if (!codec->cache_sync)
+ return;
+
+ codec->cache_only = 0;
+ cache = codec->reg_cache;
+ for (i = 0; i < codec->driver->reg_cache_size; i++) {
+ if (i == WM8804_RST_DEVID1 || cache[i] == wm8804_reg_defs[i])
+ continue;
+ snd_soc_write(codec, i, cache[i]);
+ }
+ codec->cache_sync = 0;
+}
+
+static int wm8804_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ int ret;
+ struct wm8804_priv *wm8804;
+
+ wm8804 = snd_soc_codec_get_drvdata(codec);
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ /* power up the OSC and the PLL */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
+ wm8804->supplies);
+ if (ret) {
+ dev_err(codec->dev,
+ "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+ wm8804_sync_cache(codec);
+ }
+ /* power down the OSC and the PLL */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
+ break;
+ case SND_SOC_BIAS_OFF:
+ /* power down the OSC and the PLL */
+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
+ regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies),
+ wm8804->supplies);
+ break;
+ }
+
+ codec->bias_level = level;
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8804_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+ wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int wm8804_resume(struct snd_soc_codec *codec)
+{
+ wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+#else
+#define wm8804_suspend NULL
+#define wm8804_resume NULL
+#endif
+
+static int wm8804_remove(struct snd_soc_codec *codec)
+{
+ struct wm8804_priv *wm8804;
+ int i;
+
+ wm8804 = snd_soc_codec_get_drvdata(codec);
+ wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
+ regulator_unregister_notifier(wm8804->supplies[i].consumer,
+ &wm8804->disable_nb[i]);
+ regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
+ return 0;
+}
+
+static int wm8804_probe(struct snd_soc_codec *codec)
+{
+ struct wm8804_priv *wm8804;
+ int i, id1, id2, ret;
+
+ wm8804 = snd_soc_codec_get_drvdata(codec);
+ wm8804->codec = codec;
+
+ codec->idle_bias_off = 1;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, wm8804->control_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
+ wm8804->supplies[i].supply = wm8804_supply_names[i];
+
+ ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
+ wm8804->supplies);
+ if (ret) {
+ dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
+ wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
+
+ /* This should really be moved into the regulator core */
+ for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
+ ret = regulator_register_notifier(wm8804->supplies[i].consumer,
+ &wm8804->disable_nb[i]);
+ if (ret != 0) {
+ dev_err(codec->dev,
+ "Failed to register regulator notifier: %d\n",
+ ret);
+ }
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
+ wm8804->supplies);
+ if (ret) {
+ dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_reg_get;
+ }
+
+ id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
+ if (id1 < 0) {
+ dev_err(codec->dev, "Failed to read device ID: %d\n", id1);
+ ret = id1;
+ goto err_reg_enable;
+ }
+
+ id2 = snd_soc_read(codec, WM8804_DEVID2);
+ if (id2 < 0) {
+ dev_err(codec->dev, "Failed to read device ID: %d\n", id2);
+ ret = id2;
+ goto err_reg_enable;
+ }
+
+ id2 = (id2 << 8) | id1;
+
+ if (id2 != ((wm8804_reg_defs[WM8804_DEVID2] << 8)
+ | wm8804_reg_defs[WM8804_RST_DEVID1])) {
+ dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
+ ret = -EINVAL;
+ goto err_reg_enable;
+ }
+
+ ret = snd_soc_read(codec, WM8804_DEVREV);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to read device revision: %d\n",
+ ret);
+ goto err_reg_enable;
+ }
+ dev_info(codec->dev, "revision %c\n", ret + 'A');
+
+ ret = wm8804_reset(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+ goto err_reg_enable;
+ }
+
+ wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ snd_soc_add_controls(codec, wm8804_snd_controls,
+ ARRAY_SIZE(wm8804_snd_controls));
+ return 0;
+
+err_reg_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
+err_reg_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
+ return ret;
+}
+
+static struct snd_soc_dai_ops wm8804_dai_ops = {
+ .hw_params = wm8804_hw_params,
+ .set_fmt = wm8804_set_fmt,
+ .set_sysclk = wm8804_set_sysclk,
+ .set_clkdiv = wm8804_set_clkdiv,
+ .set_pll = wm8804_set_pll
+};
+
+#define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_driver wm8804_dai = {
+ .name = "wm8804-spdif",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = WM8804_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = WM8804_FORMATS,
+ },
+ .ops = &wm8804_dai_ops,
+ .symmetric_rates = 1
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
+ .probe = wm8804_probe,
+ .remove = wm8804_remove,
+ .suspend = wm8804_suspend,
+ .resume = wm8804_resume,
+ .set_bias_level = wm8804_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8804_reg_defs),
+ .reg_word_size = sizeof(u8),
+ .reg_cache_default = wm8804_reg_defs,
+ .volatile_register = wm8804_volatile
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8804_spi_probe(struct spi_device *spi)
+{
+ struct wm8804_priv *wm8804;
+ int ret;
+
+ wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+ if (!wm8804)
+ return -ENOMEM;
+
+ wm8804->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8804);
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8804, &wm8804_dai, 1);
+ if (ret < 0)
+ kfree(wm8804);
+ return ret;
+}
+
+static int __devexit wm8804_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
+ return 0;
+}
+
+static struct spi_driver wm8804_spi_driver = {
+ .driver = {
+ .name = "wm8804",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8804_spi_probe,
+ .remove = __devexit_p(wm8804_spi_remove)
+};
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8804_priv *wm8804;
+ int ret;
+
+ wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+ if (!wm8804)
+ return -ENOMEM;
+
+ wm8804->control_type = SND_SOC_I2C;
+ i2c_set_clientdata(i2c, wm8804);
+
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8804, &wm8804_dai, 1);
+ if (ret < 0)
+ kfree(wm8804);
+ return ret;
+}
+
+static __devexit int wm8804_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+static const struct i2c_device_id wm8804_i2c_id[] = {
+ { "wm8804", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
+
+static struct i2c_driver wm8804_i2c_driver = {
+ .driver = {
+ .name = "wm8804",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8804_i2c_probe,
+ .remove = __devexit_p(wm8804_i2c_remove),
+ .id_table = wm8804_i2c_id
+};
+#endif
+
+static int __init wm8804_modinit(void)
+{
+ int ret = 0;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8804_i2c_driver);
+ if (ret) {
+ printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n",
+ ret);
+ }
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ ret = spi_register_driver(&wm8804_spi_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8804 SPI driver: %d\n",
+ ret);
+ }
+#endif
+ return ret;
+}
+module_init(wm8804_modinit);
+
+static void __exit wm8804_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8804_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8804_spi_driver);
+#endif
+}
+module_exit(wm8804_exit);
+
+MODULE_DESCRIPTION("ASoC WM8804 driver");
+MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8804.h b/sound/soc/codecs/wm8804.h
new file mode 100644
index 000000000000..8ec14f5573cb
--- /dev/null
+++ b/sound/soc/codecs/wm8804.h
@@ -0,0 +1,61 @@
+/*
+ * wm8804.h -- WM8804 S/PDIF transceiver driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8804_H
+#define _WM8804_H
+
+/*
+ * Register values.
+ */
+#define WM8804_RST_DEVID1 0x00
+#define WM8804_DEVID2 0x01
+#define WM8804_DEVREV 0x02
+#define WM8804_PLL1 0x03
+#define WM8804_PLL2 0x04
+#define WM8804_PLL3 0x05
+#define WM8804_PLL4 0x06
+#define WM8804_PLL5 0x07
+#define WM8804_PLL6 0x08
+#define WM8804_SPDMODE 0x09
+#define WM8804_INTMASK 0x0A
+#define WM8804_INTSTAT 0x0B
+#define WM8804_SPDSTAT 0x0C
+#define WM8804_RXCHAN1 0x0D
+#define WM8804_RXCHAN2 0x0E
+#define WM8804_RXCHAN3 0x0F
+#define WM8804_RXCHAN4 0x10
+#define WM8804_RXCHAN5 0x11
+#define WM8804_SPDTX1 0x12
+#define WM8804_SPDTX2 0x13
+#define WM8804_SPDTX3 0x14
+#define WM8804_SPDTX4 0x15
+#define WM8804_SPDTX5 0x16
+#define WM8804_GPO0 0x17
+#define WM8804_GPO1 0x18
+#define WM8804_GPO2 0x1A
+#define WM8804_AIFTX 0x1B
+#define WM8804_AIFRX 0x1C
+#define WM8804_SPDRX1 0x1D
+#define WM8804_PWRDN 0x1E
+
+#define WM8804_REGISTER_COUNT 30
+#define WM8804_MAX_REGISTER 0x1E
+
+#define WM8804_TX_CLKSRC_MCLK 1
+#define WM8804_TX_CLKSRC_PLL 2
+
+#define WM8804_CLKOUT_SRC_CLK1 3
+#define WM8804_CLKOUT_SRC_OSCCLK 4
+
+#define WM8804_CLKOUT_DIV 1
+
+#endif /* _WM8804_H */
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 5da17a704e5a..aca4b1ea10bb 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/spi/spi.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -137,11 +138,8 @@
#define WM8900_LRC_MASK 0xfc00
-struct snd_soc_codec_device soc_codec_dev_wm8900;
-
struct wm8900_priv {
- struct snd_soc_codec codec;
-
+ enum snd_soc_control_type control_type;
u16 reg_cache[WM8900_MAXREG];
u32 fll_in; /* FLL input frequency */
@@ -188,7 +186,6 @@ static int wm8900_volatile_register(unsigned int reg)
{
switch (reg) {
case WM8900_REG_ID:
- case WM8900_REG_POWER1:
return 1;
default:
return 0;
@@ -627,8 +624,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 reg;
reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
@@ -1015,8 +1011,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = {
.digital_mute = wm8900_digital_mute,
};
-struct snd_soc_dai wm8900_dai = {
- .name = "WM8900 HiFi",
+static struct snd_soc_dai_driver wm8900_dai = {
+ .name = "wm8900-hifi",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -1033,7 +1029,6 @@ struct snd_soc_dai wm8900_dai = {
},
.ops = &wm8900_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8900_dai);
static int wm8900_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
@@ -1128,10 +1123,8 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
int fll_out = wm8900->fll_out;
int fll_in = wm8900->fll_in;
@@ -1140,7 +1133,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
/* Stop the FLL in an orderly fashion */
ret = wm8900_set_fll(codec, 0, 0, 0);
if (ret != 0) {
- dev_err(&pdev->dev, "Failed to stop FLL\n");
+ dev_err(codec->dev, "Failed to stop FLL\n");
return ret;
}
@@ -1152,10 +1145,8 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int wm8900_resume(struct platform_device *pdev)
+static int wm8900_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
u16 *cache;
int i, ret;
@@ -1176,7 +1167,7 @@ static int wm8900_resume(struct platform_device *pdev)
ret = wm8900_set_fll(codec, 0, fll_in, fll_out);
if (ret != 0) {
- dev_err(&pdev->dev, "Failed to restart FLL\n");
+ dev_err(codec->dev, "Failed to restart FLL\n");
return ret;
}
}
@@ -1186,61 +1177,28 @@ static int wm8900_resume(struct platform_device *pdev)
snd_soc_write(codec, i, cache[i]);
kfree(cache);
} else
- dev_err(&pdev->dev, "Unable to allocate register cache\n");
+ dev_err(codec->dev, "Unable to allocate register cache\n");
return 0;
}
-static struct snd_soc_codec *wm8900_codec;
-
-static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8900_probe(struct snd_soc_codec *codec)
{
- struct wm8900_priv *wm8900;
- struct snd_soc_codec *codec;
- unsigned int reg;
- int ret;
-
- wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
- if (wm8900 == NULL)
- return -ENOMEM;
+ struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0, reg;
- codec = &wm8900->codec;
- snd_soc_codec_set_drvdata(codec, wm8900);
- codec->reg_cache = &wm8900->reg_cache[0];
- codec->reg_cache_size = WM8900_MAXREG;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "WM8900";
- codec->owner = THIS_MODULE;
- codec->dai = &wm8900_dai;
- codec->num_dai = 1;
- codec->control_data = i2c;
- codec->set_bias_level = wm8900_set_bias_level;
- codec->volatile_register = wm8900_volatile_register;
- codec->dev = &i2c->dev;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type);
if (ret != 0) {
- dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
reg = snd_soc_read(codec, WM8900_REG_ID);
if (reg != 0x8900) {
- dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
- ret = -ENODEV;
- goto err;
+ dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg);
+ return -ENODEV;
}
- /* Read back from the chip */
- reg = snd_soc_read(codec, WM8900_REG_POWER1);
- reg = (reg >> 12) & 0xf;
- dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
-
wm8900_reset(codec);
/* Turn the chip on */
@@ -1271,43 +1229,94 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
/* Set the DAC and mixer output bias */
snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
- wm8900_dai.dev = &i2c->dev;
+ snd_soc_add_controls(codec, wm8900_snd_controls,
+ ARRAY_SIZE(wm8900_snd_controls));
+ wm8900_add_widgets(codec);
- wm8900_codec = codec;
+ return 0;
+}
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
+/* power down chip */
+static int wm8900_remove(struct snd_soc_codec *codec)
+{
+ wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
- ret = snd_soc_register_dai(&wm8900_dai);
- if (ret != 0) {
- dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
+static struct snd_soc_codec_driver soc_codec_dev_wm8900 = {
+ .probe = wm8900_probe,
+ .remove = wm8900_remove,
+ .suspend = wm8900_suspend,
+ .resume = wm8900_resume,
+ .set_bias_level = wm8900_set_bias_level,
+ .volatile_register = wm8900_volatile_register,
+ .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8900_reg_defaults,
+};
- return ret;
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8900_spi_probe(struct spi_device *spi)
+{
+ struct wm8900_priv *wm8900;
+ int ret;
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8900);
- wm8900_codec = NULL;
+ wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
+ if (wm8900 == NULL)
+ return -ENOMEM;
+
+ wm8900->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8900);
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8900, &wm8900_dai, 1);
+ if (ret < 0)
+ kfree(wm8900);
return ret;
}
-static __devexit int wm8900_i2c_remove(struct i2c_client *client)
+static int __devexit wm8900_spi_remove(struct spi_device *spi)
{
- snd_soc_unregister_dai(&wm8900_dai);
- snd_soc_unregister_codec(wm8900_codec);
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
+ return 0;
+}
- wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF);
+static struct spi_driver wm8900_spi_driver = {
+ .driver = {
+ .name = "wm8900-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8900_spi_probe,
+ .remove = __devexit_p(wm8900_spi_remove),
+};
+#endif /* CONFIG_SPI_MASTER */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8900_priv *wm8900;
+ int ret;
+
+ wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
+ if (wm8900 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, wm8900);
+ wm8900->control_type = SND_SOC_I2C;
- wm8900_dai.dev = NULL;
- kfree(snd_soc_codec_get_drvdata(wm8900_codec));
- wm8900_codec = NULL;
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8900, &wm8900_dai, 1);
+ if (ret < 0)
+ kfree(wm8900);
+ return ret;
+}
+static __devexit int wm8900_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1319,71 +1328,44 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
static struct i2c_driver wm8900_i2c_driver = {
.driver = {
- .name = "WM8900",
+ .name = "wm8900-codec",
.owner = THIS_MODULE,
},
- .probe = wm8900_i2c_probe,
- .remove = __devexit_p(wm8900_i2c_remove),
+ .probe = wm8900_i2c_probe,
+ .remove = __devexit_p(wm8900_i2c_remove),
.id_table = wm8900_i2c_id,
};
+#endif
-static int wm8900_probe(struct platform_device *pdev)
+static int __init wm8900_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
int ret = 0;
-
- if (!wm8900_codec) {
- dev_err(&pdev->dev, "I2C client not yet instantiated\n");
- return -ENODEV;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8900_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n",
+ ret);
}
-
- codec = wm8900_codec;
- socdev->card->codec = codec;
-
- /* Register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to register new PCMs\n");
- goto pcm_err;
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ ret = spi_register_driver(&wm8900_spi_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n",
+ ret);
}
-
- snd_soc_add_controls(codec, wm8900_snd_controls,
- ARRAY_SIZE(wm8900_snd_controls));
- wm8900_add_widgets(codec);
-
-pcm_err:
+#endif
return ret;
}
-
-/* power down chip */
-static int wm8900_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8900 = {
- .probe = wm8900_probe,
- .remove = wm8900_remove,
- .suspend = wm8900_suspend,
- .resume = wm8900_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
-
-static int __init wm8900_modinit(void)
-{
- return i2c_add_driver(&wm8900_i2c_driver);
-}
module_init(wm8900_modinit);
static void __exit wm8900_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8900_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8900_spi_driver);
+#endif
}
module_exit(wm8900_exit);
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h
index fd15007d10c7..583f257e799b 100644
--- a/sound/soc/codecs/wm8900.h
+++ b/sound/soc/codecs/wm8900.h
@@ -52,7 +52,4 @@
#define WM8900_DAC_CLKDIV_5_5 0x14
#define WM8900_DAC_CLKDIV_6 0x18
-extern struct snd_soc_dai wm8900_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8900;
-
#endif
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index bf08282d5ee5..622b60238a82 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -213,10 +213,11 @@ static u16 wm8903_reg_defaults[] = {
};
struct wm8903_priv {
- struct snd_soc_codec codec;
+
u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)];
int sysclk;
+ int irq;
/* Reference counts */
int class_w_users;
@@ -252,7 +253,6 @@ static int wm8903_volatile_register(unsigned int reg)
static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
{
u16 reg[5];
- struct i2c_client *i2c = codec->control_data;
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
BUG_ON(start > 48);
@@ -262,7 +262,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
reg[0] | WM8903_WSEQ_ENA);
- dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
+ dev_dbg(codec->dev, "Starting sequence at %d\n", start);
snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,
start | WM8903_WSEQ_START);
@@ -277,7 +277,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
} while (reg[4] & WM8903_WSEQ_BUSY);
- dev_dbg(&i2c->dev, "Sequence complete\n");
+ dev_dbg(codec->dev, "Sequence complete\n");
/* Disable the sequencer again if we enabled it */
snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
@@ -422,7 +422,6 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
struct snd_soc_codec *codec = widget->codec;
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
- struct i2c_client *i2c = codec->control_data;
u16 reg;
int ret;
@@ -431,7 +430,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
/* Turn it off if we're about to enable bypass */
if (ucontrol->value.integer.value[0]) {
if (wm8903->class_w_users == 0) {
- dev_dbg(&i2c->dev, "Disabling Class W\n");
+ dev_dbg(codec->dev, "Disabling Class W\n");
snd_soc_write(codec, WM8903_CLASS_W_0, reg &
~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));
}
@@ -444,14 +443,14 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
/* If we've just disabled the last bypass path turn Class W on */
if (!ucontrol->value.integer.value[0]) {
if (wm8903->class_w_users == 1) {
- dev_dbg(&i2c->dev, "Enabling Class W\n");
+ dev_dbg(codec->dev, "Enabling Class W\n");
snd_soc_write(codec, WM8903_CLASS_W_0, reg |
WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
}
wm8903->class_w_users--;
}
- dev_dbg(&i2c->dev, "Bypass use count now %d\n",
+ dev_dbg(codec->dev, "Bypass use count now %d\n",
wm8903->class_w_users);
return ret;
@@ -935,7 +934,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec)
static int wm8903_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct i2c_client *i2c = codec->control_data;
u16 reg, reg2;
switch (level) {
@@ -974,7 +972,7 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
/* By default no bypass paths are enabled so
* enable Class W support.
*/
- dev_dbg(&i2c->dev, "Enabling Class W\n");
+ dev_dbg(codec->dev, "Enabling Class W\n");
snd_soc_write(codec, WM8903_CLASS_W_0, reg |
WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
}
@@ -1228,10 +1226,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
- struct i2c_client *i2c = codec->control_data;
struct snd_pcm_runtime *master_runtime;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -1245,7 +1241,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
if (wm8903->master_substream) {
master_runtime = wm8903->master_substream->runtime;
- dev_dbg(&i2c->dev, "Constraining to %d bits\n",
+ dev_dbg(codec->dev, "Constraining to %d bits\n",
master_runtime->sample_bits);
snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -1264,8 +1260,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -1284,10 +1279,8 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec =rtd->codec;
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
- struct i2c_client *i2c = codec->control_data;
int fs = params_rate(params);
int bclk;
int bclk_div;
@@ -1306,7 +1299,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
if (substream == wm8903->slave_substream) {
- dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
+ dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");
return 0;
}
@@ -1332,7 +1325,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
switch (sample_rates[dsp_config].rate) {
case 88200:
case 96000:
- dev_err(&i2c->dev, "%dHz unsupported by ADC\n",
+ dev_err(codec->dev, "%dHz unsupported by ADC\n",
fs);
return -EINVAL;
@@ -1340,7 +1333,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
break;
}
- dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate);
+ dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate);
clock1 &= ~WM8903_SAMPLE_RATE_MASK;
clock1 |= sample_rates[dsp_config].value;
@@ -1366,7 +1359,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n",
+ dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n",
wm8903->sysclk, fs);
/* We may not have an MCLK which allows us to generate exactly
@@ -1401,12 +1394,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT;
clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT;
- dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n",
+ dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n",
clk_sys_ratios[clk_config].rate,
clk_sys_ratios[clk_config].mode,
clk_sys_ratios[clk_config].div);
- dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys);
+ dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys);
/* We may not get quite the right frequency if using
* approximate clocks so look for the closest match that is
@@ -1428,7 +1421,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
aif2 &= ~WM8903_BCLK_DIV_MASK;
aif3 &= ~WM8903_LRCLK_RATE_MASK;
- dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n",
+ dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n",
bclk_divs[bclk_div].ratio / 10, bclk,
(clk_sys * 10) / bclk_divs[bclk_div].ratio);
@@ -1504,8 +1497,8 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect);
static irqreturn_t wm8903_irq(int irq, void *data)
{
- struct wm8903_priv *wm8903 = data;
- struct snd_soc_codec *codec = &wm8903->codec;
+ struct snd_soc_codec *codec = data;
+ struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
int mic_report;
int int_pol;
int int_val = 0;
@@ -1586,8 +1579,8 @@ static struct snd_soc_dai_ops wm8903_dai_ops = {
.set_sysclk = wm8903_set_dai_sysclk,
};
-struct snd_soc_dai wm8903_dai = {
- .name = "WM8903",
+static struct snd_soc_dai_driver wm8903_dai = {
+ .name = "wm8903-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -1605,23 +1598,16 @@ struct snd_soc_dai wm8903_dai = {
.ops = &wm8903_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8903_dai);
-static int wm8903_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8903_resume(struct platform_device *pdev)
+static int wm8903_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
- struct i2c_client *i2c = codec->control_data;
int i;
u16 *reg_cache = codec->reg_cache;
u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults),
@@ -1637,65 +1623,37 @@ static int wm8903_resume(struct platform_device *pdev)
snd_soc_write(codec, i, tmp_cache[i]);
kfree(tmp_cache);
} else {
- dev_err(&i2c->dev, "Failed to allocate temporary cache\n");
+ dev_err(codec->dev, "Failed to allocate temporary cache\n");
}
return 0;
}
-static struct snd_soc_codec *wm8903_codec;
-
-static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8903_probe(struct snd_soc_codec *codec)
{
- struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
- struct wm8903_priv *wm8903;
- struct snd_soc_codec *codec;
+ struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
+ struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
int ret, i;
int trigger, irq_pol;
u16 val;
- wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
- if (wm8903 == NULL)
- return -ENOMEM;
-
- codec = &wm8903->codec;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->dev = &i2c->dev;
- codec->name = "WM8903";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8903_set_bias_level;
- codec->dai = &wm8903_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
- codec->reg_cache = &wm8903->reg_cache[0];
- snd_soc_codec_set_drvdata(codec, wm8903);
- codec->volatile_register = wm8903_volatile_register;
init_completion(&wm8903->wseq);
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
-
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
if (ret != 0) {
- dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
- dev_err(&i2c->dev,
+ dev_err(codec->dev,
"Device with ID register %x is not a WM8903\n", val);
return -ENODEV;
}
val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
- dev_info(&i2c->dev, "WM8903 revision %d\n",
+ dev_info(codec->dev, "WM8903 revision %d\n",
val & WM8903_CHIP_REV_MASK);
wm8903_reset(codec);
@@ -1721,7 +1679,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
wm8903->mic_delay = pdata->micdet_delay;
}
- if (i2c->irq) {
+ if (wm8903->irq) {
if (pdata && pdata->irq_active_low) {
trigger = IRQF_TRIGGER_LOW;
irq_pol = WM8903_IRQ_POL;
@@ -1733,13 +1691,13 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL,
WM8903_IRQ_POL, irq_pol);
- ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq,
+ ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq,
trigger | IRQF_ONESHOT,
- "wm8903", wm8903);
+ "wm8903", codec);
if (ret != 0) {
- dev_err(&i2c->dev, "Failed to request IRQ: %d\n",
+ dev_err(codec->dev, "Failed to request IRQ: %d\n",
ret);
- goto err;
+ return ret;
}
/* Enable write sequencer interrupts */
@@ -1781,133 +1739,96 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
val |= WM8903_DAC_MUTEMODE;
snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val);
- wm8903_dai.dev = &i2c->dev;
- wm8903_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
- goto err_irq;
- }
-
- ret = snd_soc_register_dai(&wm8903_dai);
- if (ret != 0) {
- dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
- return ret;
+ snd_soc_add_controls(codec, wm8903_snd_controls,
+ ARRAY_SIZE(wm8903_snd_controls));
+ wm8903_add_widgets(codec);
-err_codec:
- snd_soc_unregister_codec(codec);
-err_irq:
- if (i2c->irq)
- free_irq(i2c->irq, wm8903);
-err:
- wm8903_codec = NULL;
- kfree(wm8903);
return ret;
}
-static __devexit int wm8903_i2c_remove(struct i2c_client *client)
+/* power down chip */
+static int wm8903_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- struct wm8903_priv *priv = snd_soc_codec_get_drvdata(codec);
+ wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
- snd_soc_unregister_dai(&wm8903_dai);
- snd_soc_unregister_codec(codec);
+static struct snd_soc_codec_driver soc_codec_dev_wm8903 = {
+ .probe = wm8903_probe,
+ .remove = wm8903_remove,
+ .suspend = wm8903_suspend,
+ .resume = wm8903_resume,
+ .set_bias_level = wm8903_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8903_reg_defaults,
+ .volatile_register = wm8903_volatile_register,
+};
- wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8903_priv *wm8903;
+ int ret;
- if (client->irq)
- free_irq(client->irq, priv);
+ wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
+ if (wm8903 == NULL)
+ return -ENOMEM;
- kfree(priv);
+ i2c_set_clientdata(i2c, wm8903);
+ wm8903->irq = i2c->irq;
- wm8903_codec = NULL;
- wm8903_dai.dev = NULL;
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8903, &wm8903_dai, 1);
+ if (ret < 0)
+ kfree(wm8903);
+ return ret;
+}
+static __devexit int wm8903_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
-/* i2c codec control layer */
static const struct i2c_device_id wm8903_i2c_id[] = {
- { "wm8903", 0 },
- { }
+ { "wm8903", 0 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id);
static struct i2c_driver wm8903_i2c_driver = {
.driver = {
- .name = "WM8903",
+ .name = "wm8903-codec",
.owner = THIS_MODULE,
},
- .probe = wm8903_i2c_probe,
- .remove = __devexit_p(wm8903_i2c_remove),
+ .probe = wm8903_i2c_probe,
+ .remove = __devexit_p(wm8903_i2c_remove),
.id_table = wm8903_i2c_id,
};
+#endif
-static int wm8903_probe(struct platform_device *pdev)
+static int __init wm8903_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
int ret = 0;
-
- if (!wm8903_codec) {
- dev_err(&pdev->dev, "I2C device not yet probed\n");
- goto err;
- }
-
- socdev->card->codec = wm8903_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to create pcms\n");
- goto err;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8903_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n",
+ ret);
}
-
- snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls,
- ARRAY_SIZE(wm8903_snd_controls));
- wm8903_add_widgets(socdev->card->codec);
-
+#endif
return ret;
-
-err:
- return ret;
-}
-
-/* power down chip */
-static int wm8903_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec->control_data)
- wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8903 = {
- .probe = wm8903_probe,
- .remove = wm8903_remove,
- .suspend = wm8903_suspend,
- .resume = wm8903_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
-
-static int __init wm8903_modinit(void)
-{
- return i2c_add_driver(&wm8903_i2c_driver);
}
module_init(wm8903_modinit);
static void __exit wm8903_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8903_i2c_driver);
+#endif
}
module_exit(wm8903_exit);
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
index ce384a2ad820..996435e681e5 100644
--- a/sound/soc/codecs/wm8903.h
+++ b/sound/soc/codecs/wm8903.h
@@ -15,9 +15,6 @@
#include <linux/i2c.h>
-extern struct snd_soc_dai wm8903_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8903;
-
extern int wm8903_mic_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack,
int det, int shrt);
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index f7dcabf6283c..fca60a0b57b8 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -31,9 +31,6 @@
#include "wm8904.h"
-static struct snd_soc_codec *wm8904_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8904;
-
enum wm8904_type {
WM8904,
WM8912,
@@ -52,10 +49,11 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
/* codec private data */
struct wm8904_priv {
- struct snd_soc_codec codec;
+
u16 reg_cache[WM8904_MAX_REGISTER + 1];
enum wm8904_type devtype;
+ void *control_data;
struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
@@ -689,7 +687,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
+ struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata;
int value = ucontrol->value.integer.value[0];
@@ -760,7 +758,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
+ struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata;
int value = ucontrol->value.integer.value[0];
@@ -2218,8 +2216,8 @@ static struct snd_soc_dai_ops wm8904_dai_ops = {
.digital_mute = wm8904_digital_mute,
};
-struct snd_soc_dai wm8904_dai = {
- .name = "WM8904",
+static struct snd_soc_dai_driver wm8904_dai = {
+ .name = "wm8904-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -2237,24 +2235,17 @@ struct snd_soc_dai wm8904_dai = {
.ops = &wm8904_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8904_dai);
#ifdef CONFIG_PM
-static int wm8904_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8904_resume(struct platform_device *pdev)
+static int wm8904_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -2264,9 +2255,9 @@ static int wm8904_resume(struct platform_device *pdev)
#define wm8904_resume NULL
#endif
-static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904)
+static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = &wm8904->codec;
+ struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata;
struct snd_kcontrol_new control =
SOC_ENUM_EXT("EQ Mode",
@@ -2315,20 +2306,20 @@ static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904)
wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
- ret = snd_soc_add_controls(&wm8904->codec, &control, 1);
+ ret = snd_soc_add_controls(codec, &control, 1);
if (ret != 0)
- dev_err(wm8904->codec.dev,
+ dev_err(codec->dev,
"Failed to add ReTune Mobile control: %d\n", ret);
}
-static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
+static void wm8904_handle_pdata(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = &wm8904->codec;
+ struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata;
int ret, i;
if (!pdata) {
- snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls,
+ snd_soc_add_controls(codec, wm8904_eq_controls,
ARRAY_SIZE(wm8904_eq_controls));
return;
}
@@ -2344,7 +2335,7 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
wm8904->drc_texts = kmalloc(sizeof(char *)
* pdata->num_drc_cfgs, GFP_KERNEL);
if (!wm8904->drc_texts) {
- dev_err(wm8904->codec.dev,
+ dev_err(codec->dev,
"Failed to allocate %d DRC config texts\n",
pdata->num_drc_cfgs);
return;
@@ -2356,9 +2347,9 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
wm8904->drc_enum.max = pdata->num_drc_cfgs;
wm8904->drc_enum.texts = wm8904->drc_texts;
- ret = snd_soc_add_controls(&wm8904->codec, &control, 1);
+ ret = snd_soc_add_controls(codec, &control, 1);
if (ret != 0)
- dev_err(wm8904->codec.dev,
+ dev_err(codec->dev,
"Failed to add DRC mode control: %d\n", ret);
wm8904_set_drc(codec);
@@ -2368,89 +2359,19 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
pdata->num_retune_mobile_cfgs);
if (pdata->num_retune_mobile_cfgs)
- wm8904_handle_retune_mobile_pdata(wm8904);
+ wm8904_handle_retune_mobile_pdata(codec);
else
- snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls,
+ snd_soc_add_controls(codec, wm8904_eq_controls,
ARRAY_SIZE(wm8904_eq_controls));
}
-static int wm8904_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8904_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
- socdev->card->codec = wm8904_codec;
- codec = wm8904_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- wm8904_handle_pdata(snd_soc_codec_get_drvdata(codec));
-
- wm8904_add_widgets(codec);
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-static int wm8904_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8904 = {
- .probe = wm8904_probe,
- .remove = wm8904_remove,
- .suspend = wm8904_suspend,
- .resume = wm8904_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904);
-
-static int wm8904_register(struct wm8904_priv *wm8904,
- enum snd_soc_control_type control)
+static int wm8904_probe(struct snd_soc_codec *codec)
{
+ struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
struct wm8904_pdata *pdata = wm8904->pdata;
- int ret;
- struct snd_soc_codec *codec = &wm8904->codec;
- int i;
-
- if (wm8904_codec) {
- dev_err(codec->dev, "Another WM8904 is registered\n");
- ret = -EINVAL;
- goto err;
- }
+ int ret, i;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8904);
- codec->name = "WM8904";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8904_set_bias_level;
- codec->dai = &wm8904_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8904_MAX_REGISTER;
- codec->reg_cache = &wm8904->reg_cache;
- codec->volatile_register = wm8904_volatile_register;
codec->cache_sync = 1;
codec->idle_bias_off = 1;
@@ -2463,16 +2384,13 @@ static int wm8904_register(struct wm8904_priv *wm8904,
default:
dev_err(codec->dev, "Unknown device type %d\n",
wm8904->devtype);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
- memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg));
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
@@ -2482,7 +2400,7 @@ static int wm8904_register(struct wm8904_priv *wm8904,
wm8904->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies),
@@ -2517,8 +2435,6 @@ static int wm8904_register(struct wm8904_priv *wm8904,
goto err_enable;
}
- wm8904_dai.dev = codec->dev;
-
/* Change some default settings - latch VU and enable ZC */
wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
@@ -2563,72 +2479,70 @@ static int wm8904_register(struct wm8904_priv *wm8904,
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
- wm8904_codec = codec;
+ wm8904_handle_pdata(codec);
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err_enable;
- }
-
- ret = snd_soc_register_dai(&wm8904_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
+ wm8904_add_widgets(codec);
return 0;
-err_codec:
- snd_soc_unregister_codec(codec);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
err_get:
regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
-err:
- kfree(wm8904);
return ret;
}
-static void wm8904_unregister(struct wm8904_priv *wm8904)
+static int wm8904_remove(struct snd_soc_codec *codec)
{
- wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF);
+ struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
+
+ wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
- snd_soc_unregister_dai(&wm8904_dai);
- snd_soc_unregister_codec(&wm8904->codec);
- kfree(wm8904);
- wm8904_codec = NULL;
+ kfree(wm8904->retune_mobile_texts);
+ kfree(wm8904->drc_texts);
+
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
+ .probe = wm8904_probe,
+ .remove = wm8904_remove,
+ .suspend = wm8904_suspend,
+ .resume = wm8904_resume,
+ .set_bias_level = wm8904_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8904_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8904_reg,
+ .volatile_register = wm8904_volatile_register,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8904_priv *wm8904;
- struct snd_soc_codec *codec;
+ int ret;
wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);
if (wm8904 == NULL)
return -ENOMEM;
- codec = &wm8904->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
wm8904->devtype = id->driver_data;
-
i2c_set_clientdata(i2c, wm8904);
- codec->control_data = i2c;
+ wm8904->control_data = i2c;
wm8904->pdata = i2c->dev.platform_data;
- codec->dev = &i2c->dev;
-
- return wm8904_register(wm8904, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8904, &wm8904_dai, 1);
+ if (ret < 0)
+ kfree(wm8904);
+ return ret;
}
static __devexit int wm8904_i2c_remove(struct i2c_client *client)
{
- struct wm8904_priv *wm8904 = i2c_get_clientdata(client);
- wm8904_unregister(wm8904);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -2641,7 +2555,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
static struct i2c_driver wm8904_i2c_driver = {
.driver = {
- .name = "WM8904",
+ .name = "wm8904-codec",
.owner = THIS_MODULE,
},
.probe = wm8904_i2c_probe,
@@ -2652,15 +2566,15 @@ static struct i2c_driver wm8904_i2c_driver = {
static int __init wm8904_modinit(void)
{
- int ret;
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8904_i2c_driver);
if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n",
+ printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
ret);
}
#endif
- return 0;
+ return ret;
}
module_init(wm8904_modinit);
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h
index abe5059b3004..9e8c84188ba7 100644
--- a/sound/soc/codecs/wm8904.h
+++ b/sound/soc/codecs/wm8904.h
@@ -21,9 +21,6 @@
#define WM8904_FLL_LRCLK 3
#define WM8904_FLL_FREE_RUNNING 4
-extern struct snd_soc_dai wm8904_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8904;
-
/*
* Register values.
*/
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index f0c11138e610..2cb16f895c46 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -44,7 +44,8 @@
struct wm8940_priv {
unsigned int sysclk;
u16 reg_cache[WM8940_CACHEREGNUM];
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
};
static u16 wm8940_reg_defaults[] = {
@@ -365,8 +366,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F;
u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1;
u16 companding = snd_soc_read(codec,
@@ -636,8 +636,8 @@ static struct snd_soc_dai_ops wm8940_dai_ops = {
.set_pll = wm8940_set_dai_pll,
};
-struct snd_soc_dai wm8940_dai = {
- .name = "WM8940",
+static struct snd_soc_dai_driver wm8940_dai = {
+ .name = "wm8940-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -655,20 +655,14 @@ struct snd_soc_dai wm8940_dai = {
.ops = &wm8940_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8940_dai);
-static int wm8940_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
-static int wm8940_resume(struct platform_device *pdev)
+static int wm8940_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
int ret;
u8 data[3];
@@ -697,108 +691,26 @@ error_ret:
return ret;
}
-static struct snd_soc_codec *wm8940_codec;
-
-static int wm8940_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
-
- int ret = 0;
-
- if (wm8940_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8940_codec;
- codec = wm8940_codec;
-
- mutex_init(&codec->mutex);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- ret = snd_soc_add_controls(codec, wm8940_snd_controls,
- ARRAY_SIZE(wm8940_snd_controls));
- if (ret)
- goto error_free_pcms;
- ret = wm8940_add_widgets(codec);
- if (ret)
- goto error_free_pcms;
-
- return ret;
-
-error_free_pcms:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-pcm_err:
- return ret;
-}
-
-static int wm8940_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8940 = {
- .probe = wm8940_probe,
- .remove = wm8940_remove,
- .suspend = wm8940_suspend,
- .resume = wm8940_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940);
-
-static int wm8940_register(struct wm8940_priv *wm8940,
- enum snd_soc_control_type control)
+static int wm8940_probe(struct snd_soc_codec *codec)
{
- struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data;
- struct snd_soc_codec *codec = &wm8940->codec;
+ struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec);
+ struct wm8940_setup_data *pdata = codec->dev->platform_data;
int ret;
u16 reg;
- if (wm8940_codec) {
- dev_err(codec->dev, "Another WM8940 is registered\n");
- return -EINVAL;
- }
-
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8940);
- codec->name = "WM8940";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8940_set_bias_level;
- codec->dai = &wm8940_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults);
- codec->reg_cache = &wm8940->reg_cache;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
+ codec->control_data = wm8940->control_data;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- memcpy(codec->reg_cache, wm8940_reg_defaults,
- sizeof(wm8940_reg_defaults));
-
ret = wm8940_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
return ret;
}
- wm8940_dai.dev = codec->dev;
-
wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
ret = snd_soc_write(codec, WM8940_POWER1, 0x180);
@@ -814,64 +726,60 @@ static int wm8940_register(struct wm8940_priv *wm8940,
return ret;
}
-
- wm8940_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+ ret = snd_soc_add_controls(codec, wm8940_snd_controls,
+ ARRAY_SIZE(wm8940_snd_controls));
+ if (ret)
return ret;
- }
-
- ret = snd_soc_register_dai(&wm8940_dai);
- if (ret) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- snd_soc_unregister_codec(codec);
+ ret = wm8940_add_widgets(codec);
+ if (ret)
return ret;
- }
- return 0;
+ return ret;
+;
}
-static void wm8940_unregister(struct wm8940_priv *wm8940)
+static int wm8940_remove(struct snd_soc_codec *codec)
{
- wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm8940_dai);
- snd_soc_unregister_codec(&wm8940->codec);
- kfree(wm8940);
- wm8940_codec = NULL;
+ wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
-static int wm8940_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
+ .probe = wm8940_probe,
+ .remove = wm8940_remove,
+ .suspend = wm8940_suspend,
+ .resume = wm8940_resume,
+ .set_bias_level = wm8940_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8940_reg_defaults,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- int ret;
struct wm8940_priv *wm8940;
- struct snd_soc_codec *codec;
+ int ret;
- wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL);
+ wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL);
if (wm8940 == NULL)
return -ENOMEM;
- codec = &wm8940->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
i2c_set_clientdata(i2c, wm8940);
- codec->control_data = i2c;
- codec->dev = &i2c->dev;
+ wm8940->control_data = i2c;
- ret = wm8940_register(wm8940, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8940, &wm8940_dai, 1);
if (ret < 0)
kfree(wm8940);
-
return ret;
}
-static int __devexit wm8940_i2c_remove(struct i2c_client *client)
+static __devexit int wm8940_i2c_remove(struct i2c_client *client)
{
- struct wm8940_priv *wm8940 = i2c_get_clientdata(client);
-
- wm8940_unregister(wm8940);
-
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -883,29 +791,34 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
static struct i2c_driver wm8940_i2c_driver = {
.driver = {
- .name = "WM8940 I2C Codec",
+ .name = "wm8940-codec",
.owner = THIS_MODULE,
},
- .probe = wm8940_i2c_probe,
- .remove = __devexit_p(wm8940_i2c_remove),
+ .probe = wm8940_i2c_probe,
+ .remove = __devexit_p(wm8940_i2c_remove),
.id_table = wm8940_i2c_id,
};
+#endif
static int __init wm8940_modinit(void)
{
- int ret;
-
+ int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8940_i2c_driver);
- if (ret)
- printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n",
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n",
ret);
+ }
+#endif
return ret;
}
module_init(wm8940_modinit);
static void __exit wm8940_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8940_i2c_driver);
+#endif
}
module_exit(wm8940_exit);
diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h
index 8410eed3ef84..907fe192e9e0 100644
--- a/sound/soc/codecs/wm8940.h
+++ b/sound/soc/codecs/wm8940.h
@@ -15,8 +15,6 @@ struct wm8940_setup_data {
#define WM8940_VROI_30K 1
unsigned int vroi:1;
};
-extern struct snd_soc_dai wm8940_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8940;
/* WM8940 register space */
#define WM8940_SOFTRESET 0x00
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 5f025593d84d..f89ad6c9a80b 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -30,9 +30,6 @@
#include "wm8955.h"
-static struct snd_soc_codec *wm8955_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8955;
-
#define WM8955_NUM_SUPPLIES 4
static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
"DCVDD",
@@ -43,7 +40,8 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
/* codec private data */
struct wm8955_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+
u16 reg_cache[WM8955_MAX_REGISTER + 1];
unsigned int mclk_rate;
@@ -52,8 +50,6 @@ struct wm8955_priv {
int fs;
struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
-
- struct wm8955_pdata *pdata;
};
static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
@@ -870,8 +866,8 @@ static struct snd_soc_dai_ops wm8955_dai_ops = {
.digital_mute = wm8955_digital_mute,
};
-struct snd_soc_dai wm8955_dai = {
- .name = "WM8955",
+static struct snd_soc_dai_driver wm8955_dai = {
+ .name = "wm8955-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
@@ -881,24 +877,17 @@ struct snd_soc_dai wm8955_dai = {
},
.ops = &wm8955_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8955_dai);
#ifdef CONFIG_PM
-static int wm8955_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8955_resume(struct platform_device *pdev)
+static int wm8955_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -908,86 +897,16 @@ static int wm8955_resume(struct platform_device *pdev)
#define wm8955_resume NULL
#endif
-static int wm8955_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8955_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8955_codec;
- codec = wm8955_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- wm8955_add_widgets(codec);
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-static int wm8955_remove(struct platform_device *pdev)
+static int wm8955_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8955 = {
- .probe = wm8955_probe,
- .remove = wm8955_remove,
- .suspend = wm8955_suspend,
- .resume = wm8955_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955);
-
-static int wm8955_register(struct wm8955_priv *wm8955,
- enum snd_soc_control_type control)
-{
- int ret;
- struct snd_soc_codec *codec = &wm8955->codec;
- int i;
-
- if (wm8955_codec) {
- dev_err(codec->dev, "Another WM8955 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8955);
- codec->name = "WM8955";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8955_set_bias_level;
- codec->dai = &wm8955_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8955_MAX_REGISTER;
- codec->reg_cache = &wm8955->reg_cache;
-
- memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg));
+ struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+ struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
+ int ret, i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++)
@@ -997,7 +916,7 @@ static int wm8955_register(struct wm8955_priv *wm8955,
wm8955->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err;
+ return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies),
@@ -1013,8 +932,6 @@ static int wm8955_register(struct wm8955_priv *wm8955,
goto err_enable;
}
- wm8955_dai.dev = codec->dev;
-
/* Change some default settings - latch VU and enable ZC */
wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
@@ -1028,12 +945,12 @@ static int wm8955_register(struct wm8955_priv *wm8955,
wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
/* Set platform data values */
- if (wm8955->pdata) {
- if (wm8955->pdata->out2_speaker)
+ if (pdata) {
+ if (pdata->out2_speaker)
wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]
|= WM8955_ROUT2INV;
- if (wm8955->pdata->monoin_diff)
+ if (pdata->monoin_diff)
wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]
|= WM8955_DMEN;
}
@@ -1043,70 +960,60 @@ static int wm8955_register(struct wm8955_priv *wm8955,
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
- wm8955_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err_enable;
- }
-
- ret = snd_soc_register_dai(&wm8955_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
+ wm8955_add_widgets(codec);
return 0;
-err_codec:
- snd_soc_unregister_codec(codec);
err_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
err_get:
regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
-err:
- kfree(wm8955);
return ret;
}
-static void wm8955_unregister(struct wm8955_priv *wm8955)
+static int wm8955_remove(struct snd_soc_codec *codec)
{
- wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF);
+ struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+
+ wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
- snd_soc_unregister_dai(&wm8955_dai);
- snd_soc_unregister_codec(&wm8955->codec);
- kfree(wm8955);
- wm8955_codec = NULL;
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
+ .probe = wm8955_probe,
+ .remove = wm8955_remove,
+ .suspend = wm8955_suspend,
+ .resume = wm8955_resume,
+ .set_bias_level = wm8955_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8955_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8955_reg,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8955_priv *wm8955;
- struct snd_soc_codec *codec;
+ int ret;
wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
if (wm8955 == NULL)
return -ENOMEM;
- codec = &wm8955->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
i2c_set_clientdata(i2c, wm8955);
- codec->control_data = i2c;
- wm8955->pdata = i2c->dev.platform_data;
-
- codec->dev = &i2c->dev;
- return wm8955_register(wm8955, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8955, &wm8955_dai, 1);
+ if (ret < 0)
+ kfree(wm8955);
+ return ret;
}
static __devexit int wm8955_i2c_remove(struct i2c_client *client)
{
- struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
- wm8955_unregister(wm8955);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1118,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
static struct i2c_driver wm8955_i2c_driver = {
.driver = {
- .name = "wm8955",
+ .name = "wm8955-codec",
.owner = THIS_MODULE,
},
.probe = wm8955_i2c_probe,
@@ -1129,7 +1036,7 @@ static struct i2c_driver wm8955_i2c_driver = {
static int __init wm8955_modinit(void)
{
- int ret;
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8955_i2c_driver);
if (ret != 0) {
@@ -1137,7 +1044,7 @@ static int __init wm8955_modinit(void)
ret);
}
#endif
- return 0;
+ return ret;
}
module_init(wm8955_modinit);
diff --git a/sound/soc/codecs/wm8955.h b/sound/soc/codecs/wm8955.h
index ae349c8531f6..d13fd5c5fa63 100644
--- a/sound/soc/codecs/wm8955.h
+++ b/sound/soc/codecs/wm8955.h
@@ -15,9 +15,6 @@
#define WM8955_CLK_MCLK 1
-extern struct snd_soc_dai wm8955_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8955;
-
/*
* Register values.
*/
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 3c6ee61f6c95..8d5efb333c33 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -29,8 +29,6 @@
#define AUDIO_NAME "wm8960"
-struct snd_soc_codec_device soc_codec_dev_wm8960;
-
/* R25 - Power 1 */
#define WM8960_VMID_MASK 0x180
#define WM8960_VREF 0x40
@@ -75,7 +73,10 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
struct wm8960_priv {
u16 reg_cache[WM8960_CACHEREGNUM];
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
+ int (*set_bias_level)(struct snd_soc_codec *,
+ enum snd_soc_bias_level level);
struct snd_soc_dapm_widget *lout1;
struct snd_soc_dapm_widget *rout1;
struct snd_soc_dapm_widget *out3;
@@ -507,8 +508,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
int i;
@@ -849,6 +849,14 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
return 0;
}
+static int wm8960_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+
+ return wm8960->set_bias_level(codec, level);
+}
+
#define WM8960_RATES SNDRV_PCM_RATE_8000_48000
#define WM8960_FORMATS \
@@ -863,8 +871,8 @@ static struct snd_soc_dai_ops wm8960_dai_ops = {
.set_pll = wm8960_set_dai_pll,
};
-struct snd_soc_dai wm8960_dai = {
- .name = "WM8960",
+static struct snd_soc_dai_driver wm8960_dai = {
+ .name = "wm8960-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -880,21 +888,18 @@ struct snd_soc_dai wm8960_dai = {
.ops = &wm8960_dai_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8960_dai);
-static int wm8960_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
- codec->set_bias_level(codec, SND_SOC_BIAS_OFF);
+ wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8960_resume(struct platform_device *pdev)
+static int wm8960_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -906,78 +911,19 @@ static int wm8960_resume(struct platform_device *pdev)
codec->hw_write(codec->control_data, data, 2);
}
- codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
+ wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
-static struct snd_soc_codec *wm8960_codec;
-
-static int wm8960_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8960_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8960_codec;
- codec = wm8960_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8960_snd_controls,
- ARRAY_SIZE(wm8960_snd_controls));
- wm8960_add_widgets(codec);
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-/* power down chip */
-static int wm8960_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8960 = {
- .probe = wm8960_probe,
- .remove = wm8960_remove,
- .suspend = wm8960_suspend,
- .resume = wm8960_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
-
-static int wm8960_register(struct wm8960_priv *wm8960,
- enum snd_soc_control_type control)
+static int wm8960_probe(struct snd_soc_codec *codec)
{
- struct wm8960_data *pdata = wm8960->codec.dev->platform_data;
- struct snd_soc_codec *codec = &wm8960->codec;
+ struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+ struct wm8960_data *pdata = dev_get_platdata(codec->dev);
int ret;
u16 reg;
- if (wm8960_codec) {
- dev_err(codec->dev, "Another WM8960 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- codec->set_bias_level = wm8960_set_bias_level_out3;
+ wm8960->set_bias_level = wm8960_set_bias_level_out3;
+ codec->control_data = wm8960->control_data;
if (!pdata) {
dev_warn(codec->dev, "No platform data supplied\n");
@@ -988,39 +934,22 @@ static int wm8960_register(struct wm8960_priv *wm8960,
}
if (pdata->capless)
- codec->set_bias_level = wm8960_set_bias_level_capless;
+ wm8960->set_bias_level = wm8960_set_bias_level_capless;
}
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8960);
- codec->name = "WM8960";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->dai = &wm8960_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8960_CACHEREGNUM;
- codec->reg_cache = &wm8960->reg_cache;
-
- memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
ret = wm8960_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
- goto err;
+ return ret;
}
- wm8960_dai.dev = codec->dev;
-
- codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Latch the update bits */
reg = snd_soc_read(codec, WM8960_LINVOL);
@@ -1044,62 +973,58 @@ static int wm8960_register(struct wm8960_priv *wm8960,
reg = snd_soc_read(codec, WM8960_ROUT2);
snd_soc_write(codec, WM8960_ROUT2, reg | 0x100);
- wm8960_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&wm8960_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
+ snd_soc_add_controls(codec, wm8960_snd_controls,
+ ARRAY_SIZE(wm8960_snd_controls));
+ wm8960_add_widgets(codec);
return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8960);
- return ret;
}
-static void wm8960_unregister(struct wm8960_priv *wm8960)
+/* power down chip */
+static int wm8960_remove(struct snd_soc_codec *codec)
{
- wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm8960_dai);
- snd_soc_unregister_codec(&wm8960->codec);
- kfree(wm8960);
- wm8960_codec = NULL;
+ struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+
+ wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
+ .probe = wm8960_probe,
+ .remove = wm8960_remove,
+ .suspend = wm8960_suspend,
+ .resume = wm8960_resume,
+ .set_bias_level = wm8960_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8960_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8960_reg,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8960_priv *wm8960;
- struct snd_soc_codec *codec;
+ int ret;
wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);
if (wm8960 == NULL)
return -ENOMEM;
- codec = &wm8960->codec;
-
i2c_set_clientdata(i2c, wm8960);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
+ wm8960->control_data = i2c;
- return wm8960_register(wm8960, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8960, &wm8960_dai, 1);
+ if (ret < 0)
+ kfree(wm8960);
+ return ret;
}
static __devexit int wm8960_i2c_remove(struct i2c_client *client)
{
- struct wm8960_priv *wm8960 = i2c_get_clientdata(client);
- wm8960_unregister(wm8960);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1111,35 +1036,37 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
static struct i2c_driver wm8960_i2c_driver = {
.driver = {
- .name = "wm8960",
+ .name = "wm8960-codec",
.owner = THIS_MODULE,
},
.probe = wm8960_i2c_probe,
.remove = __devexit_p(wm8960_i2c_remove),
.id_table = wm8960_i2c_id,
};
+#endif
static int __init wm8960_modinit(void)
{
- int ret;
-
+ int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8960_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
ret);
}
-
+#endif
return ret;
}
module_init(wm8960_modinit);
static void __exit wm8960_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8960_i2c_driver);
+#endif
}
module_exit(wm8960_exit);
-
MODULE_DESCRIPTION("ASoC WM8960 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h
index a5ef65481b86..2d8163d7004b 100644
--- a/sound/soc/codecs/wm8960.h
+++ b/sound/soc/codecs/wm8960.h
@@ -110,7 +110,4 @@
#define WM8960_OPCLK_DIV_5_5 (4 << 0)
#define WM8960_OPCLK_DIV_6 (5 << 0)
-extern struct snd_soc_dai wm8960_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8960;
-
#endif
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 2549d3a297ab..8340485c9851 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -288,7 +288,7 @@ static u16 wm8961_reg_defaults[] = {
};
struct wm8961_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
int sysclk;
u16 reg_cache[WM8961_MAX_REGISTER];
};
@@ -711,7 +711,7 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream,
if (fs <= 24000)
reg |= WM8961_DACSLOPE;
else
- reg &= WM8961_DACSLOPE;
+ reg &= ~WM8961_DACSLOPE;
snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
return 0;
@@ -736,7 +736,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
freq /= 2;
} else {
dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq);
- reg &= WM8961_MCLKDIV;
+ reg &= ~WM8961_MCLKDIV;
}
snd_soc_write(codec, WM8961_CLOCKING1, reg);
@@ -940,8 +940,8 @@ static struct snd_soc_dai_ops wm8961_dai_ops = {
.set_clkdiv = wm8961_set_clkdiv,
};
-struct snd_soc_dai wm8961_dai = {
- .name = "WM8961",
+static struct snd_soc_dai_driver wm8961_dai = {
+ .name = "wm8961-hifi",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -956,140 +956,22 @@ struct snd_soc_dai wm8961_dai = {
.formats = WM8961_FORMATS,},
.ops = &wm8961_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8961_dai);
-
-static struct snd_soc_codec *wm8961_codec;
-
-static int wm8961_probe(struct platform_device *pdev)
+static int wm8961_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
int ret = 0;
-
- if (wm8961_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8961_codec;
- codec = wm8961_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8961_snd_controls,
- ARRAY_SIZE(wm8961_snd_controls));
- snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
- ARRAY_SIZE(wm8961_dapm_widgets));
- snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-static int wm8961_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int wm8961_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- return 0;
-}
-
-static int wm8961_resume(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- for (i = 0; i < codec->reg_cache_size; i++) {
- if (reg_cache[i] == wm8961_reg_defaults[i])
- continue;
-
- if (i == WM8961_SOFTWARE_RESET)
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
-
- wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- return 0;
-}
-#else
-#define wm8961_suspend NULL
-#define wm8961_resume NULL
-#endif
-
-struct snd_soc_codec_device soc_codec_dev_wm8961 = {
- .probe = wm8961_probe,
- .remove = wm8961_remove,
- .suspend = wm8961_suspend,
- .resume = wm8961_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961);
-
-static int wm8961_register(struct wm8961_priv *wm8961)
-{
- struct snd_soc_codec *codec = &wm8961->codec;
- int ret;
u16 reg;
- if (wm8961_codec) {
- dev_err(codec->dev, "Another WM8961 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8961);
- codec->name = "WM8961";
- codec->owner = THIS_MODULE;
- codec->dai = &wm8961_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache);
- codec->reg_cache = &wm8961->reg_cache;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8961_set_bias_level;
- codec->volatile_register = wm8961_volatile_register;
-
- memcpy(codec->reg_cache, wm8961_reg_defaults,
- sizeof(wm8961_reg_defaults));
-
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET);
if (reg != 0x1801) {
dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
/* This isn't volatile - readback doesn't correspond to write */
@@ -1102,7 +984,7 @@ static int wm8961_register(struct wm8961_priv *wm8961)
ret = wm8961_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
- goto err;
+ return ret;
}
/* Enable class W */
@@ -1140,64 +1022,89 @@ static int wm8961_register(struct wm8961_priv *wm8961)
wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- wm8961_dai.dev = codec->dev;
+ snd_soc_add_controls(codec, wm8961_snd_controls,
+ ARRAY_SIZE(wm8961_snd_controls));
+ snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
+ ARRAY_SIZE(wm8961_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
- wm8961_codec = codec;
+ return 0;
+}
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
+static int wm8961_remove(struct snd_soc_codec *codec)
+{
+ wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
- ret = snd_soc_register_dai(&wm8961_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
+#ifdef CONFIG_PM
+static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+ wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8961);
- return ret;
}
-static void wm8961_unregister(struct wm8961_priv *wm8961)
+static int wm8961_resume(struct snd_soc_codec *codec)
{
- wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm8961_dai);
- snd_soc_unregister_codec(&wm8961->codec);
- kfree(wm8961);
- wm8961_codec = NULL;
+ u16 *reg_cache = codec->reg_cache;
+ int i;
+
+ for (i = 0; i < codec->driver->reg_cache_size; i++) {
+ if (reg_cache[i] == wm8961_reg_defaults[i])
+ continue;
+
+ if (i == WM8961_SOFTWARE_RESET)
+ continue;
+
+ snd_soc_write(codec, i, reg_cache[i]);
+ }
+
+ wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
}
+#else
+#define wm8961_suspend NULL
+#define wm8961_resume NULL
+#endif
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8961 = {
+ .probe = wm8961_probe,
+ .remove = wm8961_remove,
+ .suspend = wm8961_suspend,
+ .resume = wm8961_resume,
+ .set_bias_level = wm8961_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8961_reg_defaults),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8961_reg_defaults,
+ .volatile_register = wm8961_volatile_register,
+};
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8961_priv *wm8961;
- struct snd_soc_codec *codec;
+ int ret;
wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL);
if (wm8961 == NULL)
return -ENOMEM;
- codec = &wm8961->codec;
-
i2c_set_clientdata(i2c, wm8961);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
- return wm8961_register(wm8961);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8961, &wm8961_dai, 1);
+ if (ret < 0)
+ kfree(wm8961);
+ return ret;
}
static __devexit int wm8961_i2c_remove(struct i2c_client *client)
{
- struct wm8961_priv *wm8961 = i2c_get_clientdata(client);
- wm8961_unregister(wm8961);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1209,35 +1116,37 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
static struct i2c_driver wm8961_i2c_driver = {
.driver = {
- .name = "wm8961",
+ .name = "wm8961-codec",
.owner = THIS_MODULE,
},
.probe = wm8961_i2c_probe,
.remove = __devexit_p(wm8961_i2c_remove),
.id_table = wm8961_i2c_id,
};
+#endif
static int __init wm8961_modinit(void)
{
- int ret;
-
+ int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8961_i2c_driver);
if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n",
+ printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n",
ret);
}
-
+#endif
return ret;
}
module_init(wm8961_modinit);
static void __exit wm8961_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8961_i2c_driver);
+#endif
}
module_exit(wm8961_exit);
-
MODULE_DESCRIPTION("ASoC WM8961 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h
index 5513bfd720d6..1d736e5701c8 100644
--- a/sound/soc/codecs/wm8961.h
+++ b/sound/soc/codecs/wm8961.h
@@ -11,9 +11,6 @@
#include <sound/soc.h>
-extern struct snd_soc_codec_device soc_codec_dev_wm8961;
-extern struct snd_soc_dai wm8961_dai;
-
#define WM8961_BCLK 1
#define WM8961_LRCLK 2
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
new file mode 100644
index 000000000000..e8092745a207
--- /dev/null
+++ b/sound/soc/codecs/wm8962.c
@@ -0,0 +1,3980 @@
+/*
+ * wm8962.c -- WM8962 ALSA SoC Audio driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm8962.h>
+
+#include "wm8962.h"
+
+#define WM8962_NUM_SUPPLIES 8
+static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
+ "DCVDD",
+ "DBVDD",
+ "AVDD",
+ "CPVDD",
+ "MICVDD",
+ "PLLVDD",
+ "SPKVDD1",
+ "SPKVDD2",
+};
+
+/* codec private data */
+struct wm8962_priv {
+ struct snd_soc_codec *codec;
+
+ u16 reg_cache[WM8962_MAX_REGISTER + 1];
+
+ int sysclk;
+ int sysclk_rate;
+
+ int bclk; /* Desired BCLK */
+ int lrclk;
+
+ int fll_src;
+ int fll_fref;
+ int fll_fout;
+
+ struct delayed_work mic_work;
+ struct snd_soc_jack *jack;
+
+ struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES];
+ struct notifier_block disable_nb[WM8962_NUM_SUPPLIES];
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ struct input_dev *beep;
+ struct work_struct beep_work;
+ int beep_rate;
+#endif
+
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio_chip;
+#endif
+};
+
+/* We can't use the same notifier block for more than one supply and
+ * there's no way I can see to get from a callback to the caller
+ * except container_of().
+ */
+#define WM8962_REGULATOR_EVENT(n) \
+static int wm8962_regulator_event_##n(struct notifier_block *nb, \
+ unsigned long event, void *data) \
+{ \
+ struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
+ disable_nb[n]); \
+ if (event & REGULATOR_EVENT_DISABLE) { \
+ wm8962->codec->cache_sync = 1; \
+ } \
+ return 0; \
+}
+
+WM8962_REGULATOR_EVENT(0)
+WM8962_REGULATOR_EVENT(1)
+WM8962_REGULATOR_EVENT(2)
+WM8962_REGULATOR_EVENT(3)
+WM8962_REGULATOR_EVENT(4)
+WM8962_REGULATOR_EVENT(5)
+WM8962_REGULATOR_EVENT(6)
+WM8962_REGULATOR_EVENT(7)
+
+static const u16 wm8962_reg[WM8962_MAX_REGISTER + 1] = {
+ [0] = 0x009F, /* R0 - Left Input volume */
+ [1] = 0x049F, /* R1 - Right Input volume */
+ [2] = 0x0000, /* R2 - HPOUTL volume */
+ [3] = 0x0000, /* R3 - HPOUTR volume */
+ [4] = 0x0020, /* R4 - Clocking1 */
+ [5] = 0x0018, /* R5 - ADC & DAC Control 1 */
+ [6] = 0x2008, /* R6 - ADC & DAC Control 2 */
+ [7] = 0x000A, /* R7 - Audio Interface 0 */
+ [8] = 0x01E4, /* R8 - Clocking2 */
+ [9] = 0x0300, /* R9 - Audio Interface 1 */
+ [10] = 0x00C0, /* R10 - Left DAC volume */
+ [11] = 0x00C0, /* R11 - Right DAC volume */
+
+ [14] = 0x0040, /* R14 - Audio Interface 2 */
+ [15] = 0x6243, /* R15 - Software Reset */
+
+ [17] = 0x007B, /* R17 - ALC1 */
+ [18] = 0x0000, /* R18 - ALC2 */
+ [19] = 0x1C32, /* R19 - ALC3 */
+ [20] = 0x3200, /* R20 - Noise Gate */
+ [21] = 0x00C0, /* R21 - Left ADC volume */
+ [22] = 0x00C0, /* R22 - Right ADC volume */
+ [23] = 0x0160, /* R23 - Additional control(1) */
+ [24] = 0x0000, /* R24 - Additional control(2) */
+ [25] = 0x0000, /* R25 - Pwr Mgmt (1) */
+ [26] = 0x0000, /* R26 - Pwr Mgmt (2) */
+ [27] = 0x0010, /* R27 - Additional Control (3) */
+ [28] = 0x0000, /* R28 - Anti-pop */
+
+ [30] = 0x005E, /* R30 - Clocking 3 */
+ [31] = 0x0000, /* R31 - Input mixer control (1) */
+ [32] = 0x0145, /* R32 - Left input mixer volume */
+ [33] = 0x0145, /* R33 - Right input mixer volume */
+ [34] = 0x0009, /* R34 - Input mixer control (2) */
+ [35] = 0x0003, /* R35 - Input bias control */
+ [37] = 0x0008, /* R37 - Left input PGA control */
+ [38] = 0x0008, /* R38 - Right input PGA control */
+
+ [40] = 0x0000, /* R40 - SPKOUTL volume */
+ [41] = 0x0000, /* R41 - SPKOUTR volume */
+
+ [47] = 0x0000, /* R47 - Thermal Shutdown Status */
+ [48] = 0x8027, /* R48 - Additional Control (4) */
+ [49] = 0x0010, /* R49 - Class D Control 1 */
+
+ [51] = 0x0003, /* R51 - Class D Control 2 */
+
+ [56] = 0x0506, /* R56 - Clocking 4 */
+ [57] = 0x0000, /* R57 - DAC DSP Mixing (1) */
+ [58] = 0x0000, /* R58 - DAC DSP Mixing (2) */
+
+ [60] = 0x0300, /* R60 - DC Servo 0 */
+ [61] = 0x0300, /* R61 - DC Servo 1 */
+
+ [64] = 0x0810, /* R64 - DC Servo 4 */
+
+ [66] = 0x0000, /* R66 - DC Servo 6 */
+
+ [68] = 0x001B, /* R68 - Analogue PGA Bias */
+ [69] = 0x0000, /* R69 - Analogue HP 0 */
+
+ [71] = 0x01FB, /* R71 - Analogue HP 2 */
+ [72] = 0x0000, /* R72 - Charge Pump 1 */
+
+ [82] = 0x0004, /* R82 - Charge Pump B */
+
+ [87] = 0x0000, /* R87 - Write Sequencer Control 1 */
+
+ [90] = 0x0000, /* R90 - Write Sequencer Control 2 */
+
+ [93] = 0x0000, /* R93 - Write Sequencer Control 3 */
+ [94] = 0x0000, /* R94 - Control Interface */
+
+ [99] = 0x0000, /* R99 - Mixer Enables */
+ [100] = 0x0000, /* R100 - Headphone Mixer (1) */
+ [101] = 0x0000, /* R101 - Headphone Mixer (2) */
+ [102] = 0x013F, /* R102 - Headphone Mixer (3) */
+ [103] = 0x013F, /* R103 - Headphone Mixer (4) */
+
+ [105] = 0x0000, /* R105 - Speaker Mixer (1) */
+ [106] = 0x0000, /* R106 - Speaker Mixer (2) */
+ [107] = 0x013F, /* R107 - Speaker Mixer (3) */
+ [108] = 0x013F, /* R108 - Speaker Mixer (4) */
+ [109] = 0x0003, /* R109 - Speaker Mixer (5) */
+ [110] = 0x0002, /* R110 - Beep Generator (1) */
+
+ [115] = 0x0006, /* R115 - Oscillator Trim (3) */
+ [116] = 0x0026, /* R116 - Oscillator Trim (4) */
+
+ [119] = 0x0000, /* R119 - Oscillator Trim (7) */
+
+ [124] = 0x0011, /* R124 - Analogue Clocking1 */
+ [125] = 0x004B, /* R125 - Analogue Clocking2 */
+ [126] = 0x000D, /* R126 - Analogue Clocking3 */
+ [127] = 0x0000, /* R127 - PLL Software Reset */
+
+ [129] = 0x0000, /* R129 - PLL2 */
+
+ [131] = 0x0000, /* R131 - PLL 4 */
+
+ [136] = 0x0067, /* R136 - PLL 9 */
+ [137] = 0x001C, /* R137 - PLL 10 */
+ [138] = 0x0071, /* R138 - PLL 11 */
+ [139] = 0x00C7, /* R139 - PLL 12 */
+ [140] = 0x0067, /* R140 - PLL 13 */
+ [141] = 0x0048, /* R141 - PLL 14 */
+ [142] = 0x0022, /* R142 - PLL 15 */
+ [143] = 0x0097, /* R143 - PLL 16 */
+
+ [155] = 0x000C, /* R155 - FLL Control (1) */
+ [156] = 0x0039, /* R156 - FLL Control (2) */
+ [157] = 0x0180, /* R157 - FLL Control (3) */
+
+ [159] = 0x0032, /* R159 - FLL Control (5) */
+ [160] = 0x0018, /* R160 - FLL Control (6) */
+ [161] = 0x007D, /* R161 - FLL Control (7) */
+ [162] = 0x0008, /* R162 - FLL Control (8) */
+
+ [252] = 0x0005, /* R252 - General test 1 */
+
+ [256] = 0x0000, /* R256 - DF1 */
+ [257] = 0x0000, /* R257 - DF2 */
+ [258] = 0x0000, /* R258 - DF3 */
+ [259] = 0x0000, /* R259 - DF4 */
+ [260] = 0x0000, /* R260 - DF5 */
+ [261] = 0x0000, /* R261 - DF6 */
+ [262] = 0x0000, /* R262 - DF7 */
+
+ [264] = 0x0000, /* R264 - LHPF1 */
+ [265] = 0x0000, /* R265 - LHPF2 */
+
+ [268] = 0x0000, /* R268 - THREED1 */
+ [269] = 0x0000, /* R269 - THREED2 */
+ [270] = 0x0000, /* R270 - THREED3 */
+ [271] = 0x0000, /* R271 - THREED4 */
+
+ [276] = 0x000C, /* R276 - DRC 1 */
+ [277] = 0x0925, /* R277 - DRC 2 */
+ [278] = 0x0000, /* R278 - DRC 3 */
+ [279] = 0x0000, /* R279 - DRC 4 */
+ [280] = 0x0000, /* R280 - DRC 5 */
+
+ [285] = 0x0000, /* R285 - Tloopback */
+
+ [335] = 0x0004, /* R335 - EQ1 */
+ [336] = 0x6318, /* R336 - EQ2 */
+ [337] = 0x6300, /* R337 - EQ3 */
+ [338] = 0x0FCA, /* R338 - EQ4 */
+ [339] = 0x0400, /* R339 - EQ5 */
+ [340] = 0x00D8, /* R340 - EQ6 */
+ [341] = 0x1EB5, /* R341 - EQ7 */
+ [342] = 0xF145, /* R342 - EQ8 */
+ [343] = 0x0B75, /* R343 - EQ9 */
+ [344] = 0x01C5, /* R344 - EQ10 */
+ [345] = 0x1C58, /* R345 - EQ11 */
+ [346] = 0xF373, /* R346 - EQ12 */
+ [347] = 0x0A54, /* R347 - EQ13 */
+ [348] = 0x0558, /* R348 - EQ14 */
+ [349] = 0x168E, /* R349 - EQ15 */
+ [350] = 0xF829, /* R350 - EQ16 */
+ [351] = 0x07AD, /* R351 - EQ17 */
+ [352] = 0x1103, /* R352 - EQ18 */
+ [353] = 0x0564, /* R353 - EQ19 */
+ [354] = 0x0559, /* R354 - EQ20 */
+ [355] = 0x4000, /* R355 - EQ21 */
+ [356] = 0x6318, /* R356 - EQ22 */
+ [357] = 0x6300, /* R357 - EQ23 */
+ [358] = 0x0FCA, /* R358 - EQ24 */
+ [359] = 0x0400, /* R359 - EQ25 */
+ [360] = 0x00D8, /* R360 - EQ26 */
+ [361] = 0x1EB5, /* R361 - EQ27 */
+ [362] = 0xF145, /* R362 - EQ28 */
+ [363] = 0x0B75, /* R363 - EQ29 */
+ [364] = 0x01C5, /* R364 - EQ30 */
+ [365] = 0x1C58, /* R365 - EQ31 */
+ [366] = 0xF373, /* R366 - EQ32 */
+ [367] = 0x0A54, /* R367 - EQ33 */
+ [368] = 0x0558, /* R368 - EQ34 */
+ [369] = 0x168E, /* R369 - EQ35 */
+ [370] = 0xF829, /* R370 - EQ36 */
+ [371] = 0x07AD, /* R371 - EQ37 */
+ [372] = 0x1103, /* R372 - EQ38 */
+ [373] = 0x0564, /* R373 - EQ39 */
+ [374] = 0x0559, /* R374 - EQ40 */
+ [375] = 0x4000, /* R375 - EQ41 */
+
+ [513] = 0x0000, /* R513 - GPIO 2 */
+ [514] = 0x0000, /* R514 - GPIO 3 */
+
+ [516] = 0x8100, /* R516 - GPIO 5 */
+ [517] = 0x8100, /* R517 - GPIO 6 */
+
+ [560] = 0x0000, /* R560 - Interrupt Status 1 */
+ [561] = 0x0000, /* R561 - Interrupt Status 2 */
+
+ [568] = 0x0030, /* R568 - Interrupt Status 1 Mask */
+ [569] = 0xFFED, /* R569 - Interrupt Status 2 Mask */
+
+ [576] = 0x0000, /* R576 - Interrupt Control */
+
+ [584] = 0x002D, /* R584 - IRQ Debounce */
+
+ [586] = 0x0000, /* R586 - MICINT Source Pol */
+
+ [768] = 0x1C00, /* R768 - DSP2 Power Management */
+
+ [1037] = 0x0000, /* R1037 - DSP2_ExecControl */
+
+ [8192] = 0x0000, /* R8192 - DSP2 Instruction RAM 0 */
+
+ [9216] = 0x0030, /* R9216 - DSP2 Address RAM 2 */
+ [9217] = 0x0000, /* R9217 - DSP2 Address RAM 1 */
+ [9218] = 0x0000, /* R9218 - DSP2 Address RAM 0 */
+
+ [12288] = 0x0000, /* R12288 - DSP2 Data1 RAM 1 */
+ [12289] = 0x0000, /* R12289 - DSP2 Data1 RAM 0 */
+
+ [13312] = 0x0000, /* R13312 - DSP2 Data2 RAM 1 */
+ [13313] = 0x0000, /* R13313 - DSP2 Data2 RAM 0 */
+
+ [14336] = 0x0000, /* R14336 - DSP2 Data3 RAM 1 */
+ [14337] = 0x0000, /* R14337 - DSP2 Data3 RAM 0 */
+
+ [15360] = 0x000A, /* R15360 - DSP2 Coeff RAM 0 */
+
+ [16384] = 0x0000, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
+ [16385] = 0x0000, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
+ [16386] = 0x0000, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
+ [16387] = 0x0000, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
+ [16388] = 0x0000, /* R16388 - SOUNDSTAGE_ENABLES_1 */
+ [16389] = 0x0000, /* R16389 - SOUNDSTAGE_ENABLES_0 */
+
+ [16896] = 0x0002, /* R16896 - HDBASS_AI_1 */
+ [16897] = 0xBD12, /* R16897 - HDBASS_AI_0 */
+ [16898] = 0x007C, /* R16898 - HDBASS_AR_1 */
+ [16899] = 0x586C, /* R16899 - HDBASS_AR_0 */
+ [16900] = 0x0053, /* R16900 - HDBASS_B_1 */
+ [16901] = 0x8121, /* R16901 - HDBASS_B_0 */
+ [16902] = 0x003F, /* R16902 - HDBASS_K_1 */
+ [16903] = 0x8BD8, /* R16903 - HDBASS_K_0 */
+ [16904] = 0x0032, /* R16904 - HDBASS_N1_1 */
+ [16905] = 0xF52D, /* R16905 - HDBASS_N1_0 */
+ [16906] = 0x0065, /* R16906 - HDBASS_N2_1 */
+ [16907] = 0xAC8C, /* R16907 - HDBASS_N2_0 */
+ [16908] = 0x006B, /* R16908 - HDBASS_N3_1 */
+ [16909] = 0xE087, /* R16909 - HDBASS_N3_0 */
+ [16910] = 0x0072, /* R16910 - HDBASS_N4_1 */
+ [16911] = 0x1483, /* R16911 - HDBASS_N4_0 */
+ [16912] = 0x0072, /* R16912 - HDBASS_N5_1 */
+ [16913] = 0x1483, /* R16913 - HDBASS_N5_0 */
+ [16914] = 0x0043, /* R16914 - HDBASS_X1_1 */
+ [16915] = 0x3525, /* R16915 - HDBASS_X1_0 */
+ [16916] = 0x0006, /* R16916 - HDBASS_X2_1 */
+ [16917] = 0x6A4A, /* R16917 - HDBASS_X2_0 */
+ [16918] = 0x0043, /* R16918 - HDBASS_X3_1 */
+ [16919] = 0x6079, /* R16919 - HDBASS_X3_0 */
+ [16920] = 0x0008, /* R16920 - HDBASS_ATK_1 */
+ [16921] = 0x0000, /* R16921 - HDBASS_ATK_0 */
+ [16922] = 0x0001, /* R16922 - HDBASS_DCY_1 */
+ [16923] = 0x0000, /* R16923 - HDBASS_DCY_0 */
+ [16924] = 0x0059, /* R16924 - HDBASS_PG_1 */
+ [16925] = 0x999A, /* R16925 - HDBASS_PG_0 */
+
+ [17048] = 0x0083, /* R17408 - HPF_C_1 */
+ [17049] = 0x98AD, /* R17409 - HPF_C_0 */
+
+ [17920] = 0x007F, /* R17920 - ADCL_RETUNE_C1_1 */
+ [17921] = 0xFFFF, /* R17921 - ADCL_RETUNE_C1_0 */
+ [17922] = 0x0000, /* R17922 - ADCL_RETUNE_C2_1 */
+ [17923] = 0x0000, /* R17923 - ADCL_RETUNE_C2_0 */
+ [17924] = 0x0000, /* R17924 - ADCL_RETUNE_C3_1 */
+ [17925] = 0x0000, /* R17925 - ADCL_RETUNE_C3_0 */
+ [17926] = 0x0000, /* R17926 - ADCL_RETUNE_C4_1 */
+ [17927] = 0x0000, /* R17927 - ADCL_RETUNE_C4_0 */
+ [17928] = 0x0000, /* R17928 - ADCL_RETUNE_C5_1 */
+ [17929] = 0x0000, /* R17929 - ADCL_RETUNE_C5_0 */
+ [17930] = 0x0000, /* R17930 - ADCL_RETUNE_C6_1 */
+ [17931] = 0x0000, /* R17931 - ADCL_RETUNE_C6_0 */
+ [17932] = 0x0000, /* R17932 - ADCL_RETUNE_C7_1 */
+ [17933] = 0x0000, /* R17933 - ADCL_RETUNE_C7_0 */
+ [17934] = 0x0000, /* R17934 - ADCL_RETUNE_C8_1 */
+ [17935] = 0x0000, /* R17935 - ADCL_RETUNE_C8_0 */
+ [17936] = 0x0000, /* R17936 - ADCL_RETUNE_C9_1 */
+ [17937] = 0x0000, /* R17937 - ADCL_RETUNE_C9_0 */
+ [17938] = 0x0000, /* R17938 - ADCL_RETUNE_C10_1 */
+ [17939] = 0x0000, /* R17939 - ADCL_RETUNE_C10_0 */
+ [17940] = 0x0000, /* R17940 - ADCL_RETUNE_C11_1 */
+ [17941] = 0x0000, /* R17941 - ADCL_RETUNE_C11_0 */
+ [17942] = 0x0000, /* R17942 - ADCL_RETUNE_C12_1 */
+ [17943] = 0x0000, /* R17943 - ADCL_RETUNE_C12_0 */
+ [17944] = 0x0000, /* R17944 - ADCL_RETUNE_C13_1 */
+ [17945] = 0x0000, /* R17945 - ADCL_RETUNE_C13_0 */
+ [17946] = 0x0000, /* R17946 - ADCL_RETUNE_C14_1 */
+ [17947] = 0x0000, /* R17947 - ADCL_RETUNE_C14_0 */
+ [17948] = 0x0000, /* R17948 - ADCL_RETUNE_C15_1 */
+ [17949] = 0x0000, /* R17949 - ADCL_RETUNE_C15_0 */
+ [17950] = 0x0000, /* R17950 - ADCL_RETUNE_C16_1 */
+ [17951] = 0x0000, /* R17951 - ADCL_RETUNE_C16_0 */
+ [17952] = 0x0000, /* R17952 - ADCL_RETUNE_C17_1 */
+ [17953] = 0x0000, /* R17953 - ADCL_RETUNE_C17_0 */
+ [17954] = 0x0000, /* R17954 - ADCL_RETUNE_C18_1 */
+ [17955] = 0x0000, /* R17955 - ADCL_RETUNE_C18_0 */
+ [17956] = 0x0000, /* R17956 - ADCL_RETUNE_C19_1 */
+ [17957] = 0x0000, /* R17957 - ADCL_RETUNE_C19_0 */
+ [17958] = 0x0000, /* R17958 - ADCL_RETUNE_C20_1 */
+ [17959] = 0x0000, /* R17959 - ADCL_RETUNE_C20_0 */
+ [17960] = 0x0000, /* R17960 - ADCL_RETUNE_C21_1 */
+ [17961] = 0x0000, /* R17961 - ADCL_RETUNE_C21_0 */
+ [17962] = 0x0000, /* R17962 - ADCL_RETUNE_C22_1 */
+ [17963] = 0x0000, /* R17963 - ADCL_RETUNE_C22_0 */
+ [17964] = 0x0000, /* R17964 - ADCL_RETUNE_C23_1 */
+ [17965] = 0x0000, /* R17965 - ADCL_RETUNE_C23_0 */
+ [17966] = 0x0000, /* R17966 - ADCL_RETUNE_C24_1 */
+ [17967] = 0x0000, /* R17967 - ADCL_RETUNE_C24_0 */
+ [17968] = 0x0000, /* R17968 - ADCL_RETUNE_C25_1 */
+ [17969] = 0x0000, /* R17969 - ADCL_RETUNE_C25_0 */
+ [17970] = 0x0000, /* R17970 - ADCL_RETUNE_C26_1 */
+ [17971] = 0x0000, /* R17971 - ADCL_RETUNE_C26_0 */
+ [17972] = 0x0000, /* R17972 - ADCL_RETUNE_C27_1 */
+ [17973] = 0x0000, /* R17973 - ADCL_RETUNE_C27_0 */
+ [17974] = 0x0000, /* R17974 - ADCL_RETUNE_C28_1 */
+ [17975] = 0x0000, /* R17975 - ADCL_RETUNE_C28_0 */
+ [17976] = 0x0000, /* R17976 - ADCL_RETUNE_C29_1 */
+ [17977] = 0x0000, /* R17977 - ADCL_RETUNE_C29_0 */
+ [17978] = 0x0000, /* R17978 - ADCL_RETUNE_C30_1 */
+ [17979] = 0x0000, /* R17979 - ADCL_RETUNE_C30_0 */
+ [17980] = 0x0000, /* R17980 - ADCL_RETUNE_C31_1 */
+ [17981] = 0x0000, /* R17981 - ADCL_RETUNE_C31_0 */
+ [17982] = 0x0000, /* R17982 - ADCL_RETUNE_C32_1 */
+ [17983] = 0x0000, /* R17983 - ADCL_RETUNE_C32_0 */
+
+ [18432] = 0x0020, /* R18432 - RETUNEADC_PG2_1 */
+ [18433] = 0x0000, /* R18433 - RETUNEADC_PG2_0 */
+ [18434] = 0x0040, /* R18434 - RETUNEADC_PG_1 */
+ [18435] = 0x0000, /* R18435 - RETUNEADC_PG_0 */
+
+ [18944] = 0x007F, /* R18944 - ADCR_RETUNE_C1_1 */
+ [18945] = 0xFFFF, /* R18945 - ADCR_RETUNE_C1_0 */
+ [18946] = 0x0000, /* R18946 - ADCR_RETUNE_C2_1 */
+ [18947] = 0x0000, /* R18947 - ADCR_RETUNE_C2_0 */
+ [18948] = 0x0000, /* R18948 - ADCR_RETUNE_C3_1 */
+ [18949] = 0x0000, /* R18949 - ADCR_RETUNE_C3_0 */
+ [18950] = 0x0000, /* R18950 - ADCR_RETUNE_C4_1 */
+ [18951] = 0x0000, /* R18951 - ADCR_RETUNE_C4_0 */
+ [18952] = 0x0000, /* R18952 - ADCR_RETUNE_C5_1 */
+ [18953] = 0x0000, /* R18953 - ADCR_RETUNE_C5_0 */
+ [18954] = 0x0000, /* R18954 - ADCR_RETUNE_C6_1 */
+ [18955] = 0x0000, /* R18955 - ADCR_RETUNE_C6_0 */
+ [18956] = 0x0000, /* R18956 - ADCR_RETUNE_C7_1 */
+ [18957] = 0x0000, /* R18957 - ADCR_RETUNE_C7_0 */
+ [18958] = 0x0000, /* R18958 - ADCR_RETUNE_C8_1 */
+ [18959] = 0x0000, /* R18959 - ADCR_RETUNE_C8_0 */
+ [18960] = 0x0000, /* R18960 - ADCR_RETUNE_C9_1 */
+ [18961] = 0x0000, /* R18961 - ADCR_RETUNE_C9_0 */
+ [18962] = 0x0000, /* R18962 - ADCR_RETUNE_C10_1 */
+ [18963] = 0x0000, /* R18963 - ADCR_RETUNE_C10_0 */
+ [18964] = 0x0000, /* R18964 - ADCR_RETUNE_C11_1 */
+ [18965] = 0x0000, /* R18965 - ADCR_RETUNE_C11_0 */
+ [18966] = 0x0000, /* R18966 - ADCR_RETUNE_C12_1 */
+ [18967] = 0x0000, /* R18967 - ADCR_RETUNE_C12_0 */
+ [18968] = 0x0000, /* R18968 - ADCR_RETUNE_C13_1 */
+ [18969] = 0x0000, /* R18969 - ADCR_RETUNE_C13_0 */
+ [18970] = 0x0000, /* R18970 - ADCR_RETUNE_C14_1 */
+ [18971] = 0x0000, /* R18971 - ADCR_RETUNE_C14_0 */
+ [18972] = 0x0000, /* R18972 - ADCR_RETUNE_C15_1 */
+ [18973] = 0x0000, /* R18973 - ADCR_RETUNE_C15_0 */
+ [18974] = 0x0000, /* R18974 - ADCR_RETUNE_C16_1 */
+ [18975] = 0x0000, /* R18975 - ADCR_RETUNE_C16_0 */
+ [18976] = 0x0000, /* R18976 - ADCR_RETUNE_C17_1 */
+ [18977] = 0x0000, /* R18977 - ADCR_RETUNE_C17_0 */
+ [18978] = 0x0000, /* R18978 - ADCR_RETUNE_C18_1 */
+ [18979] = 0x0000, /* R18979 - ADCR_RETUNE_C18_0 */
+ [18980] = 0x0000, /* R18980 - ADCR_RETUNE_C19_1 */
+ [18981] = 0x0000, /* R18981 - ADCR_RETUNE_C19_0 */
+ [18982] = 0x0000, /* R18982 - ADCR_RETUNE_C20_1 */
+ [18983] = 0x0000, /* R18983 - ADCR_RETUNE_C20_0 */
+ [18984] = 0x0000, /* R18984 - ADCR_RETUNE_C21_1 */
+ [18985] = 0x0000, /* R18985 - ADCR_RETUNE_C21_0 */
+ [18986] = 0x0000, /* R18986 - ADCR_RETUNE_C22_1 */
+ [18987] = 0x0000, /* R18987 - ADCR_RETUNE_C22_0 */
+ [18988] = 0x0000, /* R18988 - ADCR_RETUNE_C23_1 */
+ [18989] = 0x0000, /* R18989 - ADCR_RETUNE_C23_0 */
+ [18990] = 0x0000, /* R18990 - ADCR_RETUNE_C24_1 */
+ [18991] = 0x0000, /* R18991 - ADCR_RETUNE_C24_0 */
+ [18992] = 0x0000, /* R18992 - ADCR_RETUNE_C25_1 */
+ [18993] = 0x0000, /* R18993 - ADCR_RETUNE_C25_0 */
+ [18994] = 0x0000, /* R18994 - ADCR_RETUNE_C26_1 */
+ [18995] = 0x0000, /* R18995 - ADCR_RETUNE_C26_0 */
+ [18996] = 0x0000, /* R18996 - ADCR_RETUNE_C27_1 */
+ [18997] = 0x0000, /* R18997 - ADCR_RETUNE_C27_0 */
+ [18998] = 0x0000, /* R18998 - ADCR_RETUNE_C28_1 */
+ [18999] = 0x0000, /* R18999 - ADCR_RETUNE_C28_0 */
+ [19000] = 0x0000, /* R19000 - ADCR_RETUNE_C29_1 */
+ [19001] = 0x0000, /* R19001 - ADCR_RETUNE_C29_0 */
+ [19002] = 0x0000, /* R19002 - ADCR_RETUNE_C30_1 */
+ [19003] = 0x0000, /* R19003 - ADCR_RETUNE_C30_0 */
+ [19004] = 0x0000, /* R19004 - ADCR_RETUNE_C31_1 */
+ [19005] = 0x0000, /* R19005 - ADCR_RETUNE_C31_0 */
+ [19006] = 0x0000, /* R19006 - ADCR_RETUNE_C32_1 */
+ [19007] = 0x0000, /* R19007 - ADCR_RETUNE_C32_0 */
+
+ [19456] = 0x007F, /* R19456 - DACL_RETUNE_C1_1 */
+ [19457] = 0xFFFF, /* R19457 - DACL_RETUNE_C1_0 */
+ [19458] = 0x0000, /* R19458 - DACL_RETUNE_C2_1 */
+ [19459] = 0x0000, /* R19459 - DACL_RETUNE_C2_0 */
+ [19460] = 0x0000, /* R19460 - DACL_RETUNE_C3_1 */
+ [19461] = 0x0000, /* R19461 - DACL_RETUNE_C3_0 */
+ [19462] = 0x0000, /* R19462 - DACL_RETUNE_C4_1 */
+ [19463] = 0x0000, /* R19463 - DACL_RETUNE_C4_0 */
+ [19464] = 0x0000, /* R19464 - DACL_RETUNE_C5_1 */
+ [19465] = 0x0000, /* R19465 - DACL_RETUNE_C5_0 */
+ [19466] = 0x0000, /* R19466 - DACL_RETUNE_C6_1 */
+ [19467] = 0x0000, /* R19467 - DACL_RETUNE_C6_0 */
+ [19468] = 0x0000, /* R19468 - DACL_RETUNE_C7_1 */
+ [19469] = 0x0000, /* R19469 - DACL_RETUNE_C7_0 */
+ [19470] = 0x0000, /* R19470 - DACL_RETUNE_C8_1 */
+ [19471] = 0x0000, /* R19471 - DACL_RETUNE_C8_0 */
+ [19472] = 0x0000, /* R19472 - DACL_RETUNE_C9_1 */
+ [19473] = 0x0000, /* R19473 - DACL_RETUNE_C9_0 */
+ [19474] = 0x0000, /* R19474 - DACL_RETUNE_C10_1 */
+ [19475] = 0x0000, /* R19475 - DACL_RETUNE_C10_0 */
+ [19476] = 0x0000, /* R19476 - DACL_RETUNE_C11_1 */
+ [19477] = 0x0000, /* R19477 - DACL_RETUNE_C11_0 */
+ [19478] = 0x0000, /* R19478 - DACL_RETUNE_C12_1 */
+ [19479] = 0x0000, /* R19479 - DACL_RETUNE_C12_0 */
+ [19480] = 0x0000, /* R19480 - DACL_RETUNE_C13_1 */
+ [19481] = 0x0000, /* R19481 - DACL_RETUNE_C13_0 */
+ [19482] = 0x0000, /* R19482 - DACL_RETUNE_C14_1 */
+ [19483] = 0x0000, /* R19483 - DACL_RETUNE_C14_0 */
+ [19484] = 0x0000, /* R19484 - DACL_RETUNE_C15_1 */
+ [19485] = 0x0000, /* R19485 - DACL_RETUNE_C15_0 */
+ [19486] = 0x0000, /* R19486 - DACL_RETUNE_C16_1 */
+ [19487] = 0x0000, /* R19487 - DACL_RETUNE_C16_0 */
+ [19488] = 0x0000, /* R19488 - DACL_RETUNE_C17_1 */
+ [19489] = 0x0000, /* R19489 - DACL_RETUNE_C17_0 */
+ [19490] = 0x0000, /* R19490 - DACL_RETUNE_C18_1 */
+ [19491] = 0x0000, /* R19491 - DACL_RETUNE_C18_0 */
+ [19492] = 0x0000, /* R19492 - DACL_RETUNE_C19_1 */
+ [19493] = 0x0000, /* R19493 - DACL_RETUNE_C19_0 */
+ [19494] = 0x0000, /* R19494 - DACL_RETUNE_C20_1 */
+ [19495] = 0x0000, /* R19495 - DACL_RETUNE_C20_0 */
+ [19496] = 0x0000, /* R19496 - DACL_RETUNE_C21_1 */
+ [19497] = 0x0000, /* R19497 - DACL_RETUNE_C21_0 */
+ [19498] = 0x0000, /* R19498 - DACL_RETUNE_C22_1 */
+ [19499] = 0x0000, /* R19499 - DACL_RETUNE_C22_0 */
+ [19500] = 0x0000, /* R19500 - DACL_RETUNE_C23_1 */
+ [19501] = 0x0000, /* R19501 - DACL_RETUNE_C23_0 */
+ [19502] = 0x0000, /* R19502 - DACL_RETUNE_C24_1 */
+ [19503] = 0x0000, /* R19503 - DACL_RETUNE_C24_0 */
+ [19504] = 0x0000, /* R19504 - DACL_RETUNE_C25_1 */
+ [19505] = 0x0000, /* R19505 - DACL_RETUNE_C25_0 */
+ [19506] = 0x0000, /* R19506 - DACL_RETUNE_C26_1 */
+ [19507] = 0x0000, /* R19507 - DACL_RETUNE_C26_0 */
+ [19508] = 0x0000, /* R19508 - DACL_RETUNE_C27_1 */
+ [19509] = 0x0000, /* R19509 - DACL_RETUNE_C27_0 */
+ [19510] = 0x0000, /* R19510 - DACL_RETUNE_C28_1 */
+ [19511] = 0x0000, /* R19511 - DACL_RETUNE_C28_0 */
+ [19512] = 0x0000, /* R19512 - DACL_RETUNE_C29_1 */
+ [19513] = 0x0000, /* R19513 - DACL_RETUNE_C29_0 */
+ [19514] = 0x0000, /* R19514 - DACL_RETUNE_C30_1 */
+ [19515] = 0x0000, /* R19515 - DACL_RETUNE_C30_0 */
+ [19516] = 0x0000, /* R19516 - DACL_RETUNE_C31_1 */
+ [19517] = 0x0000, /* R19517 - DACL_RETUNE_C31_0 */
+ [19518] = 0x0000, /* R19518 - DACL_RETUNE_C32_1 */
+ [19519] = 0x0000, /* R19519 - DACL_RETUNE_C32_0 */
+
+ [19968] = 0x0020, /* R19968 - RETUNEDAC_PG2_1 */
+ [19969] = 0x0000, /* R19969 - RETUNEDAC_PG2_0 */
+ [19970] = 0x0040, /* R19970 - RETUNEDAC_PG_1 */
+ [19971] = 0x0000, /* R19971 - RETUNEDAC_PG_0 */
+
+ [20480] = 0x007F, /* R20480 - DACR_RETUNE_C1_1 */
+ [20481] = 0xFFFF, /* R20481 - DACR_RETUNE_C1_0 */
+ [20482] = 0x0000, /* R20482 - DACR_RETUNE_C2_1 */
+ [20483] = 0x0000, /* R20483 - DACR_RETUNE_C2_0 */
+ [20484] = 0x0000, /* R20484 - DACR_RETUNE_C3_1 */
+ [20485] = 0x0000, /* R20485 - DACR_RETUNE_C3_0 */
+ [20486] = 0x0000, /* R20486 - DACR_RETUNE_C4_1 */
+ [20487] = 0x0000, /* R20487 - DACR_RETUNE_C4_0 */
+ [20488] = 0x0000, /* R20488 - DACR_RETUNE_C5_1 */
+ [20489] = 0x0000, /* R20489 - DACR_RETUNE_C5_0 */
+ [20490] = 0x0000, /* R20490 - DACR_RETUNE_C6_1 */
+ [20491] = 0x0000, /* R20491 - DACR_RETUNE_C6_0 */
+ [20492] = 0x0000, /* R20492 - DACR_RETUNE_C7_1 */
+ [20493] = 0x0000, /* R20493 - DACR_RETUNE_C7_0 */
+ [20494] = 0x0000, /* R20494 - DACR_RETUNE_C8_1 */
+ [20495] = 0x0000, /* R20495 - DACR_RETUNE_C8_0 */
+ [20496] = 0x0000, /* R20496 - DACR_RETUNE_C9_1 */
+ [20497] = 0x0000, /* R20497 - DACR_RETUNE_C9_0 */
+ [20498] = 0x0000, /* R20498 - DACR_RETUNE_C10_1 */
+ [20499] = 0x0000, /* R20499 - DACR_RETUNE_C10_0 */
+ [20500] = 0x0000, /* R20500 - DACR_RETUNE_C11_1 */
+ [20501] = 0x0000, /* R20501 - DACR_RETUNE_C11_0 */
+ [20502] = 0x0000, /* R20502 - DACR_RETUNE_C12_1 */
+ [20503] = 0x0000, /* R20503 - DACR_RETUNE_C12_0 */
+ [20504] = 0x0000, /* R20504 - DACR_RETUNE_C13_1 */
+ [20505] = 0x0000, /* R20505 - DACR_RETUNE_C13_0 */
+ [20506] = 0x0000, /* R20506 - DACR_RETUNE_C14_1 */
+ [20507] = 0x0000, /* R20507 - DACR_RETUNE_C14_0 */
+ [20508] = 0x0000, /* R20508 - DACR_RETUNE_C15_1 */
+ [20509] = 0x0000, /* R20509 - DACR_RETUNE_C15_0 */
+ [20510] = 0x0000, /* R20510 - DACR_RETUNE_C16_1 */
+ [20511] = 0x0000, /* R20511 - DACR_RETUNE_C16_0 */
+ [20512] = 0x0000, /* R20512 - DACR_RETUNE_C17_1 */
+ [20513] = 0x0000, /* R20513 - DACR_RETUNE_C17_0 */
+ [20514] = 0x0000, /* R20514 - DACR_RETUNE_C18_1 */
+ [20515] = 0x0000, /* R20515 - DACR_RETUNE_C18_0 */
+ [20516] = 0x0000, /* R20516 - DACR_RETUNE_C19_1 */
+ [20517] = 0x0000, /* R20517 - DACR_RETUNE_C19_0 */
+ [20518] = 0x0000, /* R20518 - DACR_RETUNE_C20_1 */
+ [20519] = 0x0000, /* R20519 - DACR_RETUNE_C20_0 */
+ [20520] = 0x0000, /* R20520 - DACR_RETUNE_C21_1 */
+ [20521] = 0x0000, /* R20521 - DACR_RETUNE_C21_0 */
+ [20522] = 0x0000, /* R20522 - DACR_RETUNE_C22_1 */
+ [20523] = 0x0000, /* R20523 - DACR_RETUNE_C22_0 */
+ [20524] = 0x0000, /* R20524 - DACR_RETUNE_C23_1 */
+ [20525] = 0x0000, /* R20525 - DACR_RETUNE_C23_0 */
+ [20526] = 0x0000, /* R20526 - DACR_RETUNE_C24_1 */
+ [20527] = 0x0000, /* R20527 - DACR_RETUNE_C24_0 */
+ [20528] = 0x0000, /* R20528 - DACR_RETUNE_C25_1 */
+ [20529] = 0x0000, /* R20529 - DACR_RETUNE_C25_0 */
+ [20530] = 0x0000, /* R20530 - DACR_RETUNE_C26_1 */
+ [20531] = 0x0000, /* R20531 - DACR_RETUNE_C26_0 */
+ [20532] = 0x0000, /* R20532 - DACR_RETUNE_C27_1 */
+ [20533] = 0x0000, /* R20533 - DACR_RETUNE_C27_0 */
+ [20534] = 0x0000, /* R20534 - DACR_RETUNE_C28_1 */
+ [20535] = 0x0000, /* R20535 - DACR_RETUNE_C28_0 */
+ [20536] = 0x0000, /* R20536 - DACR_RETUNE_C29_1 */
+ [20537] = 0x0000, /* R20537 - DACR_RETUNE_C29_0 */
+ [20538] = 0x0000, /* R20538 - DACR_RETUNE_C30_1 */
+ [20539] = 0x0000, /* R20539 - DACR_RETUNE_C30_0 */
+ [20540] = 0x0000, /* R20540 - DACR_RETUNE_C31_1 */
+ [20541] = 0x0000, /* R20541 - DACR_RETUNE_C31_0 */
+ [20542] = 0x0000, /* R20542 - DACR_RETUNE_C32_1 */
+ [20543] = 0x0000, /* R20543 - DACR_RETUNE_C32_0 */
+
+ [20992] = 0x008C, /* R20992 - VSS_XHD2_1 */
+ [20993] = 0x0200, /* R20993 - VSS_XHD2_0 */
+ [20994] = 0x0035, /* R20994 - VSS_XHD3_1 */
+ [20995] = 0x0700, /* R20995 - VSS_XHD3_0 */
+ [20996] = 0x003A, /* R20996 - VSS_XHN1_1 */
+ [20997] = 0x4100, /* R20997 - VSS_XHN1_0 */
+ [20998] = 0x008B, /* R20998 - VSS_XHN2_1 */
+ [20999] = 0x7D00, /* R20999 - VSS_XHN2_0 */
+ [21000] = 0x003A, /* R21000 - VSS_XHN3_1 */
+ [21001] = 0x4100, /* R21001 - VSS_XHN3_0 */
+ [21002] = 0x008C, /* R21002 - VSS_XLA_1 */
+ [21003] = 0xFEE8, /* R21003 - VSS_XLA_0 */
+ [21004] = 0x0078, /* R21004 - VSS_XLB_1 */
+ [21005] = 0x0000, /* R21005 - VSS_XLB_0 */
+ [21006] = 0x003F, /* R21006 - VSS_XLG_1 */
+ [21007] = 0xB260, /* R21007 - VSS_XLG_0 */
+ [21008] = 0x002D, /* R21008 - VSS_PG2_1 */
+ [21009] = 0x1818, /* R21009 - VSS_PG2_0 */
+ [21010] = 0x0020, /* R21010 - VSS_PG_1 */
+ [21011] = 0x0000, /* R21011 - VSS_PG_0 */
+ [21012] = 0x00F1, /* R21012 - VSS_XTD1_1 */
+ [21013] = 0x8340, /* R21013 - VSS_XTD1_0 */
+ [21014] = 0x00FB, /* R21014 - VSS_XTD2_1 */
+ [21015] = 0x8300, /* R21015 - VSS_XTD2_0 */
+ [21016] = 0x00EE, /* R21016 - VSS_XTD3_1 */
+ [21017] = 0xAEC0, /* R21017 - VSS_XTD3_0 */
+ [21018] = 0x00FB, /* R21018 - VSS_XTD4_1 */
+ [21019] = 0xAC40, /* R21019 - VSS_XTD4_0 */
+ [21020] = 0x00F1, /* R21020 - VSS_XTD5_1 */
+ [21021] = 0x7F80, /* R21021 - VSS_XTD5_0 */
+ [21022] = 0x00F4, /* R21022 - VSS_XTD6_1 */
+ [21023] = 0x3B40, /* R21023 - VSS_XTD6_0 */
+ [21024] = 0x00F5, /* R21024 - VSS_XTD7_1 */
+ [21025] = 0xFB00, /* R21025 - VSS_XTD7_0 */
+ [21026] = 0x00EA, /* R21026 - VSS_XTD8_1 */
+ [21027] = 0x10C0, /* R21027 - VSS_XTD8_0 */
+ [21028] = 0x00FC, /* R21028 - VSS_XTD9_1 */
+ [21029] = 0xC580, /* R21029 - VSS_XTD9_0 */
+ [21030] = 0x00E2, /* R21030 - VSS_XTD10_1 */
+ [21031] = 0x75C0, /* R21031 - VSS_XTD10_0 */
+ [21032] = 0x0004, /* R21032 - VSS_XTD11_1 */
+ [21033] = 0xB480, /* R21033 - VSS_XTD11_0 */
+ [21034] = 0x00D4, /* R21034 - VSS_XTD12_1 */
+ [21035] = 0xF980, /* R21035 - VSS_XTD12_0 */
+ [21036] = 0x0004, /* R21036 - VSS_XTD13_1 */
+ [21037] = 0x9140, /* R21037 - VSS_XTD13_0 */
+ [21038] = 0x00D8, /* R21038 - VSS_XTD14_1 */
+ [21039] = 0xA480, /* R21039 - VSS_XTD14_0 */
+ [21040] = 0x0002, /* R21040 - VSS_XTD15_1 */
+ [21041] = 0x3DC0, /* R21041 - VSS_XTD15_0 */
+ [21042] = 0x00CF, /* R21042 - VSS_XTD16_1 */
+ [21043] = 0x7A80, /* R21043 - VSS_XTD16_0 */
+ [21044] = 0x00DC, /* R21044 - VSS_XTD17_1 */
+ [21045] = 0x0600, /* R21045 - VSS_XTD17_0 */
+ [21046] = 0x00F2, /* R21046 - VSS_XTD18_1 */
+ [21047] = 0xDAC0, /* R21047 - VSS_XTD18_0 */
+ [21048] = 0x00BA, /* R21048 - VSS_XTD19_1 */
+ [21049] = 0xF340, /* R21049 - VSS_XTD19_0 */
+ [21050] = 0x000A, /* R21050 - VSS_XTD20_1 */
+ [21051] = 0x7940, /* R21051 - VSS_XTD20_0 */
+ [21052] = 0x001C, /* R21052 - VSS_XTD21_1 */
+ [21053] = 0x0680, /* R21053 - VSS_XTD21_0 */
+ [21054] = 0x00FD, /* R21054 - VSS_XTD22_1 */
+ [21055] = 0x2D00, /* R21055 - VSS_XTD22_0 */
+ [21056] = 0x001C, /* R21056 - VSS_XTD23_1 */
+ [21057] = 0xE840, /* R21057 - VSS_XTD23_0 */
+ [21058] = 0x000D, /* R21058 - VSS_XTD24_1 */
+ [21059] = 0xDC40, /* R21059 - VSS_XTD24_0 */
+ [21060] = 0x00FC, /* R21060 - VSS_XTD25_1 */
+ [21061] = 0x9D00, /* R21061 - VSS_XTD25_0 */
+ [21062] = 0x0009, /* R21062 - VSS_XTD26_1 */
+ [21063] = 0x5580, /* R21063 - VSS_XTD26_0 */
+ [21064] = 0x00FE, /* R21064 - VSS_XTD27_1 */
+ [21065] = 0x7E80, /* R21065 - VSS_XTD27_0 */
+ [21066] = 0x000E, /* R21066 - VSS_XTD28_1 */
+ [21067] = 0xAB40, /* R21067 - VSS_XTD28_0 */
+ [21068] = 0x00F9, /* R21068 - VSS_XTD29_1 */
+ [21069] = 0x9880, /* R21069 - VSS_XTD29_0 */
+ [21070] = 0x0009, /* R21070 - VSS_XTD30_1 */
+ [21071] = 0x87C0, /* R21071 - VSS_XTD30_0 */
+ [21072] = 0x00FD, /* R21072 - VSS_XTD31_1 */
+ [21073] = 0x2C40, /* R21073 - VSS_XTD31_0 */
+ [21074] = 0x0009, /* R21074 - VSS_XTD32_1 */
+ [21075] = 0x4800, /* R21075 - VSS_XTD32_0 */
+ [21076] = 0x0003, /* R21076 - VSS_XTS1_1 */
+ [21077] = 0x5F40, /* R21077 - VSS_XTS1_0 */
+ [21078] = 0x0000, /* R21078 - VSS_XTS2_1 */
+ [21079] = 0x8700, /* R21079 - VSS_XTS2_0 */
+ [21080] = 0x00FA, /* R21080 - VSS_XTS3_1 */
+ [21081] = 0xE4C0, /* R21081 - VSS_XTS3_0 */
+ [21082] = 0x0000, /* R21082 - VSS_XTS4_1 */
+ [21083] = 0x0B40, /* R21083 - VSS_XTS4_0 */
+ [21084] = 0x0004, /* R21084 - VSS_XTS5_1 */
+ [21085] = 0xE180, /* R21085 - VSS_XTS5_0 */
+ [21086] = 0x0001, /* R21086 - VSS_XTS6_1 */
+ [21087] = 0x1F40, /* R21087 - VSS_XTS6_0 */
+ [21088] = 0x00F8, /* R21088 - VSS_XTS7_1 */
+ [21089] = 0xB000, /* R21089 - VSS_XTS7_0 */
+ [21090] = 0x00FB, /* R21090 - VSS_XTS8_1 */
+ [21091] = 0xCBC0, /* R21091 - VSS_XTS8_0 */
+ [21092] = 0x0004, /* R21092 - VSS_XTS9_1 */
+ [21093] = 0xF380, /* R21093 - VSS_XTS9_0 */
+ [21094] = 0x0007, /* R21094 - VSS_XTS10_1 */
+ [21095] = 0xDF40, /* R21095 - VSS_XTS10_0 */
+ [21096] = 0x00FF, /* R21096 - VSS_XTS11_1 */
+ [21097] = 0x0700, /* R21097 - VSS_XTS11_0 */
+ [21098] = 0x00EF, /* R21098 - VSS_XTS12_1 */
+ [21099] = 0xD700, /* R21099 - VSS_XTS12_0 */
+ [21100] = 0x00FB, /* R21100 - VSS_XTS13_1 */
+ [21101] = 0xAF40, /* R21101 - VSS_XTS13_0 */
+ [21102] = 0x0010, /* R21102 - VSS_XTS14_1 */
+ [21103] = 0x8A80, /* R21103 - VSS_XTS14_0 */
+ [21104] = 0x0011, /* R21104 - VSS_XTS15_1 */
+ [21105] = 0x07C0, /* R21105 - VSS_XTS15_0 */
+ [21106] = 0x00E0, /* R21106 - VSS_XTS16_1 */
+ [21107] = 0x0800, /* R21107 - VSS_XTS16_0 */
+ [21108] = 0x00D2, /* R21108 - VSS_XTS17_1 */
+ [21109] = 0x7600, /* R21109 - VSS_XTS17_0 */
+ [21110] = 0x0020, /* R21110 - VSS_XTS18_1 */
+ [21111] = 0xCF40, /* R21111 - VSS_XTS18_0 */
+ [21112] = 0x0030, /* R21112 - VSS_XTS19_1 */
+ [21113] = 0x2340, /* R21113 - VSS_XTS19_0 */
+ [21114] = 0x00FD, /* R21114 - VSS_XTS20_1 */
+ [21115] = 0x69C0, /* R21115 - VSS_XTS20_0 */
+ [21116] = 0x0028, /* R21116 - VSS_XTS21_1 */
+ [21117] = 0x3500, /* R21117 - VSS_XTS21_0 */
+ [21118] = 0x0006, /* R21118 - VSS_XTS22_1 */
+ [21119] = 0x3300, /* R21119 - VSS_XTS22_0 */
+ [21120] = 0x00D9, /* R21120 - VSS_XTS23_1 */
+ [21121] = 0xF6C0, /* R21121 - VSS_XTS23_0 */
+ [21122] = 0x00F3, /* R21122 - VSS_XTS24_1 */
+ [21123] = 0x3340, /* R21123 - VSS_XTS24_0 */
+ [21124] = 0x000F, /* R21124 - VSS_XTS25_1 */
+ [21125] = 0x4200, /* R21125 - VSS_XTS25_0 */
+ [21126] = 0x0004, /* R21126 - VSS_XTS26_1 */
+ [21127] = 0x0C80, /* R21127 - VSS_XTS26_0 */
+ [21128] = 0x00FB, /* R21128 - VSS_XTS27_1 */
+ [21129] = 0x3F80, /* R21129 - VSS_XTS27_0 */
+ [21130] = 0x00F7, /* R21130 - VSS_XTS28_1 */
+ [21131] = 0x57C0, /* R21131 - VSS_XTS28_0 */
+ [21132] = 0x0003, /* R21132 - VSS_XTS29_1 */
+ [21133] = 0x5400, /* R21133 - VSS_XTS29_0 */
+ [21134] = 0x0000, /* R21134 - VSS_XTS30_1 */
+ [21135] = 0xC6C0, /* R21135 - VSS_XTS30_0 */
+ [21136] = 0x0003, /* R21136 - VSS_XTS31_1 */
+ [21137] = 0x12C0, /* R21137 - VSS_XTS31_0 */
+ [21138] = 0x00FD, /* R21138 - VSS_XTS32_1 */
+ [21139] = 0x8580, /* R21139 - VSS_XTS32_0 */
+};
+
+static const struct wm8962_reg_access {
+ u16 read;
+ u16 write;
+ u16 vol;
+} wm8962_reg_access[WM8962_MAX_REGISTER + 1] = {
+ [0] = { 0x00FF, 0x01FF, 0x0000 }, /* R0 - Left Input volume */
+ [1] = { 0xFEFF, 0x01FF, 0xFFFF }, /* R1 - Right Input volume */
+ [2] = { 0x00FF, 0x01FF, 0x0000 }, /* R2 - HPOUTL volume */
+ [3] = { 0x00FF, 0x01FF, 0x0000 }, /* R3 - HPOUTR volume */
+ [4] = { 0x07FE, 0x07FE, 0xFFFF }, /* R4 - Clocking1 */
+ [5] = { 0x007F, 0x007F, 0x0000 }, /* R5 - ADC & DAC Control 1 */
+ [6] = { 0x37ED, 0x37ED, 0x0000 }, /* R6 - ADC & DAC Control 2 */
+ [7] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R7 - Audio Interface 0 */
+ [8] = { 0x0FEF, 0x0FEF, 0xFFFF }, /* R8 - Clocking2 */
+ [9] = { 0x0B9F, 0x039F, 0x0000 }, /* R9 - Audio Interface 1 */
+ [10] = { 0x00FF, 0x01FF, 0x0000 }, /* R10 - Left DAC volume */
+ [11] = { 0x00FF, 0x01FF, 0x0000 }, /* R11 - Right DAC volume */
+ [14] = { 0x07FF, 0x07FF, 0x0000 }, /* R14 - Audio Interface 2 */
+ [15] = { 0xFFFF, 0xFFFF, 0xFFFF }, /* R15 - Software Reset */
+ [17] = { 0x07FF, 0x07FF, 0x0000 }, /* R17 - ALC1 */
+ [18] = { 0xF8FF, 0x00FF, 0xFFFF }, /* R18 - ALC2 */
+ [19] = { 0x1DFF, 0x1DFF, 0x0000 }, /* R19 - ALC3 */
+ [20] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20 - Noise Gate */
+ [21] = { 0x00FF, 0x01FF, 0x0000 }, /* R21 - Left ADC volume */
+ [22] = { 0x00FF, 0x01FF, 0x0000 }, /* R22 - Right ADC volume */
+ [23] = { 0x0161, 0x0161, 0x0000 }, /* R23 - Additional control(1) */
+ [24] = { 0x0008, 0x0008, 0x0000 }, /* R24 - Additional control(2) */
+ [25] = { 0x07FE, 0x07FE, 0x0000 }, /* R25 - Pwr Mgmt (1) */
+ [26] = { 0x01FB, 0x01FB, 0x0000 }, /* R26 - Pwr Mgmt (2) */
+ [27] = { 0x0017, 0x0017, 0x0000 }, /* R27 - Additional Control (3) */
+ [28] = { 0x001C, 0x001C, 0x0000 }, /* R28 - Anti-pop */
+
+ [30] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R30 - Clocking 3 */
+ [31] = { 0x000F, 0x000F, 0x0000 }, /* R31 - Input mixer control (1) */
+ [32] = { 0x01FF, 0x01FF, 0x0000 }, /* R32 - Left input mixer volume */
+ [33] = { 0x01FF, 0x01FF, 0x0000 }, /* R33 - Right input mixer volume */
+ [34] = { 0x003F, 0x003F, 0x0000 }, /* R34 - Input mixer control (2) */
+ [35] = { 0x003F, 0x003F, 0x0000 }, /* R35 - Input bias control */
+ [37] = { 0x001F, 0x001F, 0x0000 }, /* R37 - Left input PGA control */
+ [38] = { 0x001F, 0x001F, 0x0000 }, /* R38 - Right input PGA control */
+ [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */
+ [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */
+
+ [47] = { 0x000F, 0x0000, 0x0000 }, /* R47 - Thermal Shutdown Status */
+ [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */
+ [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */
+ [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */
+ [56] = { 0x001E, 0x001E, 0x0000 }, /* R56 - Clocking 4 */
+ [57] = { 0x02FC, 0x02FC, 0x0000 }, /* R57 - DAC DSP Mixing (1) */
+ [58] = { 0x00FC, 0x00FC, 0x0000 }, /* R58 - DAC DSP Mixing (2) */
+ [60] = { 0x00CC, 0x00CC, 0x0000 }, /* R60 - DC Servo 0 */
+ [61] = { 0x00DD, 0x00DD, 0x0000 }, /* R61 - DC Servo 1 */
+ [64] = { 0x3F80, 0x3F80, 0x0000 }, /* R64 - DC Servo 4 */
+ [66] = { 0x0780, 0x0000, 0xFFFF }, /* R66 - DC Servo 6 */
+ [68] = { 0x0007, 0x0007, 0x0000 }, /* R68 - Analogue PGA Bias */
+ [69] = { 0x00FF, 0x00FF, 0x0000 }, /* R69 - Analogue HP 0 */
+ [71] = { 0x01FF, 0x01FF, 0x0000 }, /* R71 - Analogue HP 2 */
+ [72] = { 0x0001, 0x0001, 0x0000 }, /* R72 - Charge Pump 1 */
+ [82] = { 0x0001, 0x0001, 0x0000 }, /* R82 - Charge Pump B */
+ [87] = { 0x00A0, 0x00A0, 0x0000 }, /* R87 - Write Sequencer Control 1 */
+ [90] = { 0x007F, 0x01FF, 0x0000 }, /* R90 - Write Sequencer Control 2 */
+ [93] = { 0x03F9, 0x0000, 0x0000 }, /* R93 - Write Sequencer Control 3 */
+ [94] = { 0x0070, 0x0070, 0x0000 }, /* R94 - Control Interface */
+ [99] = { 0x000F, 0x000F, 0x0000 }, /* R99 - Mixer Enables */
+ [100] = { 0x00BF, 0x00BF, 0x0000 }, /* R100 - Headphone Mixer (1) */
+ [101] = { 0x00BF, 0x00BF, 0x0000 }, /* R101 - Headphone Mixer (2) */
+ [102] = { 0x01FF, 0x01FF, 0x0000 }, /* R102 - Headphone Mixer (3) */
+ [103] = { 0x01FF, 0x01FF, 0x0000 }, /* R103 - Headphone Mixer (4) */
+ [105] = { 0x00BF, 0x00BF, 0x0000 }, /* R105 - Speaker Mixer (1) */
+ [106] = { 0x00BF, 0x00BF, 0x0000 }, /* R106 - Speaker Mixer (2) */
+ [107] = { 0x01FF, 0x01FF, 0x0000 }, /* R107 - Speaker Mixer (3) */
+ [108] = { 0x01FF, 0x01FF, 0x0000 }, /* R108 - Speaker Mixer (4) */
+ [109] = { 0x00F0, 0x00F0, 0x0000 }, /* R109 - Speaker Mixer (5) */
+ [110] = { 0x00F7, 0x00F7, 0x0000 }, /* R110 - Beep Generator (1) */
+ [115] = { 0x001F, 0x001F, 0x0000 }, /* R115 - Oscillator Trim (3) */
+ [116] = { 0x001F, 0x001F, 0x0000 }, /* R116 - Oscillator Trim (4) */
+ [119] = { 0x00FF, 0x00FF, 0x0000 }, /* R119 - Oscillator Trim (7) */
+ [124] = { 0x0079, 0x0079, 0x0000 }, /* R124 - Analogue Clocking1 */
+ [125] = { 0x00DF, 0x00DF, 0x0000 }, /* R125 - Analogue Clocking2 */
+ [126] = { 0x000D, 0x000D, 0x0000 }, /* R126 - Analogue Clocking3 */
+ [127] = { 0x0000, 0xFFFF, 0x0000 }, /* R127 - PLL Software Reset */
+ [129] = { 0x00B0, 0x00B0, 0x0000 }, /* R129 - PLL2 */
+ [131] = { 0x0003, 0x0003, 0x0000 }, /* R131 - PLL 4 */
+ [136] = { 0x005F, 0x005F, 0x0000 }, /* R136 - PLL 9 */
+ [137] = { 0x00FF, 0x00FF, 0x0000 }, /* R137 - PLL 10 */
+ [138] = { 0x00FF, 0x00FF, 0x0000 }, /* R138 - PLL 11 */
+ [139] = { 0x00FF, 0x00FF, 0x0000 }, /* R139 - PLL 12 */
+ [140] = { 0x005F, 0x005F, 0x0000 }, /* R140 - PLL 13 */
+ [141] = { 0x00FF, 0x00FF, 0x0000 }, /* R141 - PLL 14 */
+ [142] = { 0x00FF, 0x00FF, 0x0000 }, /* R142 - PLL 15 */
+ [143] = { 0x00FF, 0x00FF, 0x0000 }, /* R143 - PLL 16 */
+ [155] = { 0x0067, 0x0067, 0x0000 }, /* R155 - FLL Control (1) */
+ [156] = { 0x01FB, 0x01FB, 0x0000 }, /* R156 - FLL Control (2) */
+ [157] = { 0x0007, 0x0007, 0x0000 }, /* R157 - FLL Control (3) */
+ [159] = { 0x007F, 0x007F, 0x0000 }, /* R159 - FLL Control (5) */
+ [160] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R160 - FLL Control (6) */
+ [161] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R161 - FLL Control (7) */
+ [162] = { 0x03FF, 0x03FF, 0x0000 }, /* R162 - FLL Control (8) */
+ [252] = { 0x0005, 0x0005, 0x0000 }, /* R252 - General test 1 */
+ [256] = { 0x000F, 0x000F, 0x0000 }, /* R256 - DF1 */
+ [257] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R257 - DF2 */
+ [258] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R258 - DF3 */
+ [259] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R259 - DF4 */
+ [260] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R260 - DF5 */
+ [261] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R261 - DF6 */
+ [262] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R262 - DF7 */
+ [264] = { 0x0003, 0x0003, 0x0000 }, /* R264 - LHPF1 */
+ [265] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R265 - LHPF2 */
+ [268] = { 0x0077, 0x0077, 0x0000 }, /* R268 - THREED1 */
+ [269] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R269 - THREED2 */
+ [270] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R270 - THREED3 */
+ [271] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R271 - THREED4 */
+ [276] = { 0x7FFF, 0x7FFF, 0x0000 }, /* R276 - DRC 1 */
+ [277] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R277 - DRC 2 */
+ [278] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R278 - DRC 3 */
+ [279] = { 0x07FF, 0x07FF, 0x0000 }, /* R279 - DRC 4 */
+ [280] = { 0x03FF, 0x03FF, 0x0000 }, /* R280 - DRC 5 */
+ [285] = { 0x0003, 0x0003, 0x0000 }, /* R285 - Tloopback */
+ [335] = { 0x0007, 0x0007, 0x0000 }, /* R335 - EQ1 */
+ [336] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R336 - EQ2 */
+ [337] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R337 - EQ3 */
+ [338] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R338 - EQ4 */
+ [339] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R339 - EQ5 */
+ [340] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R340 - EQ6 */
+ [341] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R341 - EQ7 */
+ [342] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R342 - EQ8 */
+ [343] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R343 - EQ9 */
+ [344] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R344 - EQ10 */
+ [345] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R345 - EQ11 */
+ [346] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R346 - EQ12 */
+ [347] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R347 - EQ13 */
+ [348] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R348 - EQ14 */
+ [349] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R349 - EQ15 */
+ [350] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R350 - EQ16 */
+ [351] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R351 - EQ17 */
+ [352] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R352 - EQ18 */
+ [353] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R353 - EQ19 */
+ [354] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R354 - EQ20 */
+ [355] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R355 - EQ21 */
+ [356] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R356 - EQ22 */
+ [357] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R357 - EQ23 */
+ [358] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R358 - EQ24 */
+ [359] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R359 - EQ25 */
+ [360] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R360 - EQ26 */
+ [361] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R361 - EQ27 */
+ [362] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R362 - EQ28 */
+ [363] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R363 - EQ29 */
+ [364] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R364 - EQ30 */
+ [365] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R365 - EQ31 */
+ [366] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R366 - EQ32 */
+ [367] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R367 - EQ33 */
+ [368] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R368 - EQ34 */
+ [369] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R369 - EQ35 */
+ [370] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R370 - EQ36 */
+ [371] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R371 - EQ37 */
+ [372] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R372 - EQ38 */
+ [373] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R373 - EQ39 */
+ [374] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R374 - EQ40 */
+ [375] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R375 - EQ41 */
+ [513] = { 0x045F, 0x045F, 0x0000 }, /* R513 - GPIO 2 */
+ [514] = { 0x045F, 0x045F, 0x0000 }, /* R514 - GPIO 3 */
+ [516] = { 0xE75F, 0xE75F, 0x0000 }, /* R516 - GPIO 5 */
+ [517] = { 0xE75F, 0xE75F, 0x0000 }, /* R517 - GPIO 6 */
+ [560] = { 0x0030, 0x0030, 0xFFFF }, /* R560 - Interrupt Status 1 */
+ [561] = { 0xFFED, 0xFFED, 0xFFFF }, /* R561 - Interrupt Status 2 */
+ [568] = { 0x0030, 0x0030, 0x0000 }, /* R568 - Interrupt Status 1 Mask */
+ [569] = { 0xFFED, 0xFFED, 0x0000 }, /* R569 - Interrupt Status 2 Mask */
+ [576] = { 0x0001, 0x0001, 0x0000 }, /* R576 - Interrupt Control */
+ [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */
+ [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */
+ [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */
+ [1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */
+ [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */
+ [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */
+ [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */
+ [4099] = { 0x010F, 0x010F, 0x0000 }, /* R4099 - Write Sequencer 3 */
+ [4100] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4100 - Write Sequencer 4 */
+ [4101] = { 0x00FF, 0x00FF, 0x0000 }, /* R4101 - Write Sequencer 5 */
+ [4102] = { 0x070F, 0x070F, 0x0000 }, /* R4102 - Write Sequencer 6 */
+ [4103] = { 0x010F, 0x010F, 0x0000 }, /* R4103 - Write Sequencer 7 */
+ [4104] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4104 - Write Sequencer 8 */
+ [4105] = { 0x00FF, 0x00FF, 0x0000 }, /* R4105 - Write Sequencer 9 */
+ [4106] = { 0x070F, 0x070F, 0x0000 }, /* R4106 - Write Sequencer 10 */
+ [4107] = { 0x010F, 0x010F, 0x0000 }, /* R4107 - Write Sequencer 11 */
+ [4108] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4108 - Write Sequencer 12 */
+ [4109] = { 0x00FF, 0x00FF, 0x0000 }, /* R4109 - Write Sequencer 13 */
+ [4110] = { 0x070F, 0x070F, 0x0000 }, /* R4110 - Write Sequencer 14 */
+ [4111] = { 0x010F, 0x010F, 0x0000 }, /* R4111 - Write Sequencer 15 */
+ [4112] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4112 - Write Sequencer 16 */
+ [4113] = { 0x00FF, 0x00FF, 0x0000 }, /* R4113 - Write Sequencer 17 */
+ [4114] = { 0x070F, 0x070F, 0x0000 }, /* R4114 - Write Sequencer 18 */
+ [4115] = { 0x010F, 0x010F, 0x0000 }, /* R4115 - Write Sequencer 19 */
+ [4116] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4116 - Write Sequencer 20 */
+ [4117] = { 0x00FF, 0x00FF, 0x0000 }, /* R4117 - Write Sequencer 21 */
+ [4118] = { 0x070F, 0x070F, 0x0000 }, /* R4118 - Write Sequencer 22 */
+ [4119] = { 0x010F, 0x010F, 0x0000 }, /* R4119 - Write Sequencer 23 */
+ [4120] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4120 - Write Sequencer 24 */
+ [4121] = { 0x00FF, 0x00FF, 0x0000 }, /* R4121 - Write Sequencer 25 */
+ [4122] = { 0x070F, 0x070F, 0x0000 }, /* R4122 - Write Sequencer 26 */
+ [4123] = { 0x010F, 0x010F, 0x0000 }, /* R4123 - Write Sequencer 27 */
+ [4124] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4124 - Write Sequencer 28 */
+ [4125] = { 0x00FF, 0x00FF, 0x0000 }, /* R4125 - Write Sequencer 29 */
+ [4126] = { 0x070F, 0x070F, 0x0000 }, /* R4126 - Write Sequencer 30 */
+ [4127] = { 0x010F, 0x010F, 0x0000 }, /* R4127 - Write Sequencer 31 */
+ [4128] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4128 - Write Sequencer 32 */
+ [4129] = { 0x00FF, 0x00FF, 0x0000 }, /* R4129 - Write Sequencer 33 */
+ [4130] = { 0x070F, 0x070F, 0x0000 }, /* R4130 - Write Sequencer 34 */
+ [4131] = { 0x010F, 0x010F, 0x0000 }, /* R4131 - Write Sequencer 35 */
+ [4132] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4132 - Write Sequencer 36 */
+ [4133] = { 0x00FF, 0x00FF, 0x0000 }, /* R4133 - Write Sequencer 37 */
+ [4134] = { 0x070F, 0x070F, 0x0000 }, /* R4134 - Write Sequencer 38 */
+ [4135] = { 0x010F, 0x010F, 0x0000 }, /* R4135 - Write Sequencer 39 */
+ [4136] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4136 - Write Sequencer 40 */
+ [4137] = { 0x00FF, 0x00FF, 0x0000 }, /* R4137 - Write Sequencer 41 */
+ [4138] = { 0x070F, 0x070F, 0x0000 }, /* R4138 - Write Sequencer 42 */
+ [4139] = { 0x010F, 0x010F, 0x0000 }, /* R4139 - Write Sequencer 43 */
+ [4140] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4140 - Write Sequencer 44 */
+ [4141] = { 0x00FF, 0x00FF, 0x0000 }, /* R4141 - Write Sequencer 45 */
+ [4142] = { 0x070F, 0x070F, 0x0000 }, /* R4142 - Write Sequencer 46 */
+ [4143] = { 0x010F, 0x010F, 0x0000 }, /* R4143 - Write Sequencer 47 */
+ [4144] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4144 - Write Sequencer 48 */
+ [4145] = { 0x00FF, 0x00FF, 0x0000 }, /* R4145 - Write Sequencer 49 */
+ [4146] = { 0x070F, 0x070F, 0x0000 }, /* R4146 - Write Sequencer 50 */
+ [4147] = { 0x010F, 0x010F, 0x0000 }, /* R4147 - Write Sequencer 51 */
+ [4148] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4148 - Write Sequencer 52 */
+ [4149] = { 0x00FF, 0x00FF, 0x0000 }, /* R4149 - Write Sequencer 53 */
+ [4150] = { 0x070F, 0x070F, 0x0000 }, /* R4150 - Write Sequencer 54 */
+ [4151] = { 0x010F, 0x010F, 0x0000 }, /* R4151 - Write Sequencer 55 */
+ [4152] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4152 - Write Sequencer 56 */
+ [4153] = { 0x00FF, 0x00FF, 0x0000 }, /* R4153 - Write Sequencer 57 */
+ [4154] = { 0x070F, 0x070F, 0x0000 }, /* R4154 - Write Sequencer 58 */
+ [4155] = { 0x010F, 0x010F, 0x0000 }, /* R4155 - Write Sequencer 59 */
+ [4156] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4156 - Write Sequencer 60 */
+ [4157] = { 0x00FF, 0x00FF, 0x0000 }, /* R4157 - Write Sequencer 61 */
+ [4158] = { 0x070F, 0x070F, 0x0000 }, /* R4158 - Write Sequencer 62 */
+ [4159] = { 0x010F, 0x010F, 0x0000 }, /* R4159 - Write Sequencer 63 */
+ [4160] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4160 - Write Sequencer 64 */
+ [4161] = { 0x00FF, 0x00FF, 0x0000 }, /* R4161 - Write Sequencer 65 */
+ [4162] = { 0x070F, 0x070F, 0x0000 }, /* R4162 - Write Sequencer 66 */
+ [4163] = { 0x010F, 0x010F, 0x0000 }, /* R4163 - Write Sequencer 67 */
+ [4164] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4164 - Write Sequencer 68 */
+ [4165] = { 0x00FF, 0x00FF, 0x0000 }, /* R4165 - Write Sequencer 69 */
+ [4166] = { 0x070F, 0x070F, 0x0000 }, /* R4166 - Write Sequencer 70 */
+ [4167] = { 0x010F, 0x010F, 0x0000 }, /* R4167 - Write Sequencer 71 */
+ [4168] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4168 - Write Sequencer 72 */
+ [4169] = { 0x00FF, 0x00FF, 0x0000 }, /* R4169 - Write Sequencer 73 */
+ [4170] = { 0x070F, 0x070F, 0x0000 }, /* R4170 - Write Sequencer 74 */
+ [4171] = { 0x010F, 0x010F, 0x0000 }, /* R4171 - Write Sequencer 75 */
+ [4172] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4172 - Write Sequencer 76 */
+ [4173] = { 0x00FF, 0x00FF, 0x0000 }, /* R4173 - Write Sequencer 77 */
+ [4174] = { 0x070F, 0x070F, 0x0000 }, /* R4174 - Write Sequencer 78 */
+ [4175] = { 0x010F, 0x010F, 0x0000 }, /* R4175 - Write Sequencer 79 */
+ [4176] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4176 - Write Sequencer 80 */
+ [4177] = { 0x00FF, 0x00FF, 0x0000 }, /* R4177 - Write Sequencer 81 */
+ [4178] = { 0x070F, 0x070F, 0x0000 }, /* R4178 - Write Sequencer 82 */
+ [4179] = { 0x010F, 0x010F, 0x0000 }, /* R4179 - Write Sequencer 83 */
+ [4180] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4180 - Write Sequencer 84 */
+ [4181] = { 0x00FF, 0x00FF, 0x0000 }, /* R4181 - Write Sequencer 85 */
+ [4182] = { 0x070F, 0x070F, 0x0000 }, /* R4182 - Write Sequencer 86 */
+ [4183] = { 0x010F, 0x010F, 0x0000 }, /* R4183 - Write Sequencer 87 */
+ [4184] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4184 - Write Sequencer 88 */
+ [4185] = { 0x00FF, 0x00FF, 0x0000 }, /* R4185 - Write Sequencer 89 */
+ [4186] = { 0x070F, 0x070F, 0x0000 }, /* R4186 - Write Sequencer 90 */
+ [4187] = { 0x010F, 0x010F, 0x0000 }, /* R4187 - Write Sequencer 91 */
+ [4188] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4188 - Write Sequencer 92 */
+ [4189] = { 0x00FF, 0x00FF, 0x0000 }, /* R4189 - Write Sequencer 93 */
+ [4190] = { 0x070F, 0x070F, 0x0000 }, /* R4190 - Write Sequencer 94 */
+ [4191] = { 0x010F, 0x010F, 0x0000 }, /* R4191 - Write Sequencer 95 */
+ [4192] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4192 - Write Sequencer 96 */
+ [4193] = { 0x00FF, 0x00FF, 0x0000 }, /* R4193 - Write Sequencer 97 */
+ [4194] = { 0x070F, 0x070F, 0x0000 }, /* R4194 - Write Sequencer 98 */
+ [4195] = { 0x010F, 0x010F, 0x0000 }, /* R4195 - Write Sequencer 99 */
+ [4196] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4196 - Write Sequencer 100 */
+ [4197] = { 0x00FF, 0x00FF, 0x0000 }, /* R4197 - Write Sequencer 101 */
+ [4198] = { 0x070F, 0x070F, 0x0000 }, /* R4198 - Write Sequencer 102 */
+ [4199] = { 0x010F, 0x010F, 0x0000 }, /* R4199 - Write Sequencer 103 */
+ [4200] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4200 - Write Sequencer 104 */
+ [4201] = { 0x00FF, 0x00FF, 0x0000 }, /* R4201 - Write Sequencer 105 */
+ [4202] = { 0x070F, 0x070F, 0x0000 }, /* R4202 - Write Sequencer 106 */
+ [4203] = { 0x010F, 0x010F, 0x0000 }, /* R4203 - Write Sequencer 107 */
+ [4204] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4204 - Write Sequencer 108 */
+ [4205] = { 0x00FF, 0x00FF, 0x0000 }, /* R4205 - Write Sequencer 109 */
+ [4206] = { 0x070F, 0x070F, 0x0000 }, /* R4206 - Write Sequencer 110 */
+ [4207] = { 0x010F, 0x010F, 0x0000 }, /* R4207 - Write Sequencer 111 */
+ [4208] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4208 - Write Sequencer 112 */
+ [4209] = { 0x00FF, 0x00FF, 0x0000 }, /* R4209 - Write Sequencer 113 */
+ [4210] = { 0x070F, 0x070F, 0x0000 }, /* R4210 - Write Sequencer 114 */
+ [4211] = { 0x010F, 0x010F, 0x0000 }, /* R4211 - Write Sequencer 115 */
+ [4212] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4212 - Write Sequencer 116 */
+ [4213] = { 0x00FF, 0x00FF, 0x0000 }, /* R4213 - Write Sequencer 117 */
+ [4214] = { 0x070F, 0x070F, 0x0000 }, /* R4214 - Write Sequencer 118 */
+ [4215] = { 0x010F, 0x010F, 0x0000 }, /* R4215 - Write Sequencer 119 */
+ [4216] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4216 - Write Sequencer 120 */
+ [4217] = { 0x00FF, 0x00FF, 0x0000 }, /* R4217 - Write Sequencer 121 */
+ [4218] = { 0x070F, 0x070F, 0x0000 }, /* R4218 - Write Sequencer 122 */
+ [4219] = { 0x010F, 0x010F, 0x0000 }, /* R4219 - Write Sequencer 123 */
+ [4220] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4220 - Write Sequencer 124 */
+ [4221] = { 0x00FF, 0x00FF, 0x0000 }, /* R4221 - Write Sequencer 125 */
+ [4222] = { 0x070F, 0x070F, 0x0000 }, /* R4222 - Write Sequencer 126 */
+ [4223] = { 0x010F, 0x010F, 0x0000 }, /* R4223 - Write Sequencer 127 */
+ [4224] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4224 - Write Sequencer 128 */
+ [4225] = { 0x00FF, 0x00FF, 0x0000 }, /* R4225 - Write Sequencer 129 */
+ [4226] = { 0x070F, 0x070F, 0x0000 }, /* R4226 - Write Sequencer 130 */
+ [4227] = { 0x010F, 0x010F, 0x0000 }, /* R4227 - Write Sequencer 131 */
+ [4228] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4228 - Write Sequencer 132 */
+ [4229] = { 0x00FF, 0x00FF, 0x0000 }, /* R4229 - Write Sequencer 133 */
+ [4230] = { 0x070F, 0x070F, 0x0000 }, /* R4230 - Write Sequencer 134 */
+ [4231] = { 0x010F, 0x010F, 0x0000 }, /* R4231 - Write Sequencer 135 */
+ [4232] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4232 - Write Sequencer 136 */
+ [4233] = { 0x00FF, 0x00FF, 0x0000 }, /* R4233 - Write Sequencer 137 */
+ [4234] = { 0x070F, 0x070F, 0x0000 }, /* R4234 - Write Sequencer 138 */
+ [4235] = { 0x010F, 0x010F, 0x0000 }, /* R4235 - Write Sequencer 139 */
+ [4236] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4236 - Write Sequencer 140 */
+ [4237] = { 0x00FF, 0x00FF, 0x0000 }, /* R4237 - Write Sequencer 141 */
+ [4238] = { 0x070F, 0x070F, 0x0000 }, /* R4238 - Write Sequencer 142 */
+ [4239] = { 0x010F, 0x010F, 0x0000 }, /* R4239 - Write Sequencer 143 */
+ [4240] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4240 - Write Sequencer 144 */
+ [4241] = { 0x00FF, 0x00FF, 0x0000 }, /* R4241 - Write Sequencer 145 */
+ [4242] = { 0x070F, 0x070F, 0x0000 }, /* R4242 - Write Sequencer 146 */
+ [4243] = { 0x010F, 0x010F, 0x0000 }, /* R4243 - Write Sequencer 147 */
+ [4244] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4244 - Write Sequencer 148 */
+ [4245] = { 0x00FF, 0x00FF, 0x0000 }, /* R4245 - Write Sequencer 149 */
+ [4246] = { 0x070F, 0x070F, 0x0000 }, /* R4246 - Write Sequencer 150 */
+ [4247] = { 0x010F, 0x010F, 0x0000 }, /* R4247 - Write Sequencer 151 */
+ [4248] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4248 - Write Sequencer 152 */
+ [4249] = { 0x00FF, 0x00FF, 0x0000 }, /* R4249 - Write Sequencer 153 */
+ [4250] = { 0x070F, 0x070F, 0x0000 }, /* R4250 - Write Sequencer 154 */
+ [4251] = { 0x010F, 0x010F, 0x0000 }, /* R4251 - Write Sequencer 155 */
+ [4252] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4252 - Write Sequencer 156 */
+ [4253] = { 0x00FF, 0x00FF, 0x0000 }, /* R4253 - Write Sequencer 157 */
+ [4254] = { 0x070F, 0x070F, 0x0000 }, /* R4254 - Write Sequencer 158 */
+ [4255] = { 0x010F, 0x010F, 0x0000 }, /* R4255 - Write Sequencer 159 */
+ [4256] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4256 - Write Sequencer 160 */
+ [4257] = { 0x00FF, 0x00FF, 0x0000 }, /* R4257 - Write Sequencer 161 */
+ [4258] = { 0x070F, 0x070F, 0x0000 }, /* R4258 - Write Sequencer 162 */
+ [4259] = { 0x010F, 0x010F, 0x0000 }, /* R4259 - Write Sequencer 163 */
+ [4260] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4260 - Write Sequencer 164 */
+ [4261] = { 0x00FF, 0x00FF, 0x0000 }, /* R4261 - Write Sequencer 165 */
+ [4262] = { 0x070F, 0x070F, 0x0000 }, /* R4262 - Write Sequencer 166 */
+ [4263] = { 0x010F, 0x010F, 0x0000 }, /* R4263 - Write Sequencer 167 */
+ [4264] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4264 - Write Sequencer 168 */
+ [4265] = { 0x00FF, 0x00FF, 0x0000 }, /* R4265 - Write Sequencer 169 */
+ [4266] = { 0x070F, 0x070F, 0x0000 }, /* R4266 - Write Sequencer 170 */
+ [4267] = { 0x010F, 0x010F, 0x0000 }, /* R4267 - Write Sequencer 171 */
+ [4268] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4268 - Write Sequencer 172 */
+ [4269] = { 0x00FF, 0x00FF, 0x0000 }, /* R4269 - Write Sequencer 173 */
+ [4270] = { 0x070F, 0x070F, 0x0000 }, /* R4270 - Write Sequencer 174 */
+ [4271] = { 0x010F, 0x010F, 0x0000 }, /* R4271 - Write Sequencer 175 */
+ [4272] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4272 - Write Sequencer 176 */
+ [4273] = { 0x00FF, 0x00FF, 0x0000 }, /* R4273 - Write Sequencer 177 */
+ [4274] = { 0x070F, 0x070F, 0x0000 }, /* R4274 - Write Sequencer 178 */
+ [4275] = { 0x010F, 0x010F, 0x0000 }, /* R4275 - Write Sequencer 179 */
+ [4276] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4276 - Write Sequencer 180 */
+ [4277] = { 0x00FF, 0x00FF, 0x0000 }, /* R4277 - Write Sequencer 181 */
+ [4278] = { 0x070F, 0x070F, 0x0000 }, /* R4278 - Write Sequencer 182 */
+ [4279] = { 0x010F, 0x010F, 0x0000 }, /* R4279 - Write Sequencer 183 */
+ [4280] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4280 - Write Sequencer 184 */
+ [4281] = { 0x00FF, 0x00FF, 0x0000 }, /* R4281 - Write Sequencer 185 */
+ [4282] = { 0x070F, 0x070F, 0x0000 }, /* R4282 - Write Sequencer 186 */
+ [4283] = { 0x010F, 0x010F, 0x0000 }, /* R4283 - Write Sequencer 187 */
+ [4284] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4284 - Write Sequencer 188 */
+ [4285] = { 0x00FF, 0x00FF, 0x0000 }, /* R4285 - Write Sequencer 189 */
+ [4286] = { 0x070F, 0x070F, 0x0000 }, /* R4286 - Write Sequencer 190 */
+ [4287] = { 0x010F, 0x010F, 0x0000 }, /* R4287 - Write Sequencer 191 */
+ [4288] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4288 - Write Sequencer 192 */
+ [4289] = { 0x00FF, 0x00FF, 0x0000 }, /* R4289 - Write Sequencer 193 */
+ [4290] = { 0x070F, 0x070F, 0x0000 }, /* R4290 - Write Sequencer 194 */
+ [4291] = { 0x010F, 0x010F, 0x0000 }, /* R4291 - Write Sequencer 195 */
+ [4292] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4292 - Write Sequencer 196 */
+ [4293] = { 0x00FF, 0x00FF, 0x0000 }, /* R4293 - Write Sequencer 197 */
+ [4294] = { 0x070F, 0x070F, 0x0000 }, /* R4294 - Write Sequencer 198 */
+ [4295] = { 0x010F, 0x010F, 0x0000 }, /* R4295 - Write Sequencer 199 */
+ [4296] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4296 - Write Sequencer 200 */
+ [4297] = { 0x00FF, 0x00FF, 0x0000 }, /* R4297 - Write Sequencer 201 */
+ [4298] = { 0x070F, 0x070F, 0x0000 }, /* R4298 - Write Sequencer 202 */
+ [4299] = { 0x010F, 0x010F, 0x0000 }, /* R4299 - Write Sequencer 203 */
+ [4300] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4300 - Write Sequencer 204 */
+ [4301] = { 0x00FF, 0x00FF, 0x0000 }, /* R4301 - Write Sequencer 205 */
+ [4302] = { 0x070F, 0x070F, 0x0000 }, /* R4302 - Write Sequencer 206 */
+ [4303] = { 0x010F, 0x010F, 0x0000 }, /* R4303 - Write Sequencer 207 */
+ [4304] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4304 - Write Sequencer 208 */
+ [4305] = { 0x00FF, 0x00FF, 0x0000 }, /* R4305 - Write Sequencer 209 */
+ [4306] = { 0x070F, 0x070F, 0x0000 }, /* R4306 - Write Sequencer 210 */
+ [4307] = { 0x010F, 0x010F, 0x0000 }, /* R4307 - Write Sequencer 211 */
+ [4308] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4308 - Write Sequencer 212 */
+ [4309] = { 0x00FF, 0x00FF, 0x0000 }, /* R4309 - Write Sequencer 213 */
+ [4310] = { 0x070F, 0x070F, 0x0000 }, /* R4310 - Write Sequencer 214 */
+ [4311] = { 0x010F, 0x010F, 0x0000 }, /* R4311 - Write Sequencer 215 */
+ [4312] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4312 - Write Sequencer 216 */
+ [4313] = { 0x00FF, 0x00FF, 0x0000 }, /* R4313 - Write Sequencer 217 */
+ [4314] = { 0x070F, 0x070F, 0x0000 }, /* R4314 - Write Sequencer 218 */
+ [4315] = { 0x010F, 0x010F, 0x0000 }, /* R4315 - Write Sequencer 219 */
+ [4316] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4316 - Write Sequencer 220 */
+ [4317] = { 0x00FF, 0x00FF, 0x0000 }, /* R4317 - Write Sequencer 221 */
+ [4318] = { 0x070F, 0x070F, 0x0000 }, /* R4318 - Write Sequencer 222 */
+ [4319] = { 0x010F, 0x010F, 0x0000 }, /* R4319 - Write Sequencer 223 */
+ [4320] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4320 - Write Sequencer 224 */
+ [4321] = { 0x00FF, 0x00FF, 0x0000 }, /* R4321 - Write Sequencer 225 */
+ [4322] = { 0x070F, 0x070F, 0x0000 }, /* R4322 - Write Sequencer 226 */
+ [4323] = { 0x010F, 0x010F, 0x0000 }, /* R4323 - Write Sequencer 227 */
+ [4324] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4324 - Write Sequencer 228 */
+ [4325] = { 0x00FF, 0x00FF, 0x0000 }, /* R4325 - Write Sequencer 229 */
+ [4326] = { 0x070F, 0x070F, 0x0000 }, /* R4326 - Write Sequencer 230 */
+ [4327] = { 0x010F, 0x010F, 0x0000 }, /* R4327 - Write Sequencer 231 */
+ [4328] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4328 - Write Sequencer 232 */
+ [4329] = { 0x00FF, 0x00FF, 0x0000 }, /* R4329 - Write Sequencer 233 */
+ [4330] = { 0x070F, 0x070F, 0x0000 }, /* R4330 - Write Sequencer 234 */
+ [4331] = { 0x010F, 0x010F, 0x0000 }, /* R4331 - Write Sequencer 235 */
+ [4332] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4332 - Write Sequencer 236 */
+ [4333] = { 0x00FF, 0x00FF, 0x0000 }, /* R4333 - Write Sequencer 237 */
+ [4334] = { 0x070F, 0x070F, 0x0000 }, /* R4334 - Write Sequencer 238 */
+ [4335] = { 0x010F, 0x010F, 0x0000 }, /* R4335 - Write Sequencer 239 */
+ [4336] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4336 - Write Sequencer 240 */
+ [4337] = { 0x00FF, 0x00FF, 0x0000 }, /* R4337 - Write Sequencer 241 */
+ [4338] = { 0x070F, 0x070F, 0x0000 }, /* R4338 - Write Sequencer 242 */
+ [4339] = { 0x010F, 0x010F, 0x0000 }, /* R4339 - Write Sequencer 243 */
+ [4340] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4340 - Write Sequencer 244 */
+ [4341] = { 0x00FF, 0x00FF, 0x0000 }, /* R4341 - Write Sequencer 245 */
+ [4342] = { 0x070F, 0x070F, 0x0000 }, /* R4342 - Write Sequencer 246 */
+ [4343] = { 0x010F, 0x010F, 0x0000 }, /* R4343 - Write Sequencer 247 */
+ [4344] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4344 - Write Sequencer 248 */
+ [4345] = { 0x00FF, 0x00FF, 0x0000 }, /* R4345 - Write Sequencer 249 */
+ [4346] = { 0x070F, 0x070F, 0x0000 }, /* R4346 - Write Sequencer 250 */
+ [4347] = { 0x010F, 0x010F, 0x0000 }, /* R4347 - Write Sequencer 251 */
+ [4348] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4348 - Write Sequencer 252 */
+ [4349] = { 0x00FF, 0x00FF, 0x0000 }, /* R4349 - Write Sequencer 253 */
+ [4350] = { 0x070F, 0x070F, 0x0000 }, /* R4350 - Write Sequencer 254 */
+ [4351] = { 0x010F, 0x010F, 0x0000 }, /* R4351 - Write Sequencer 255 */
+ [4352] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4352 - Write Sequencer 256 */
+ [4353] = { 0x00FF, 0x00FF, 0x0000 }, /* R4353 - Write Sequencer 257 */
+ [4354] = { 0x070F, 0x070F, 0x0000 }, /* R4354 - Write Sequencer 258 */
+ [4355] = { 0x010F, 0x010F, 0x0000 }, /* R4355 - Write Sequencer 259 */
+ [4356] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4356 - Write Sequencer 260 */
+ [4357] = { 0x00FF, 0x00FF, 0x0000 }, /* R4357 - Write Sequencer 261 */
+ [4358] = { 0x070F, 0x070F, 0x0000 }, /* R4358 - Write Sequencer 262 */
+ [4359] = { 0x010F, 0x010F, 0x0000 }, /* R4359 - Write Sequencer 263 */
+ [4360] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4360 - Write Sequencer 264 */
+ [4361] = { 0x00FF, 0x00FF, 0x0000 }, /* R4361 - Write Sequencer 265 */
+ [4362] = { 0x070F, 0x070F, 0x0000 }, /* R4362 - Write Sequencer 266 */
+ [4363] = { 0x010F, 0x010F, 0x0000 }, /* R4363 - Write Sequencer 267 */
+ [4364] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4364 - Write Sequencer 268 */
+ [4365] = { 0x00FF, 0x00FF, 0x0000 }, /* R4365 - Write Sequencer 269 */
+ [4366] = { 0x070F, 0x070F, 0x0000 }, /* R4366 - Write Sequencer 270 */
+ [4367] = { 0x010F, 0x010F, 0x0000 }, /* R4367 - Write Sequencer 271 */
+ [4368] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4368 - Write Sequencer 272 */
+ [4369] = { 0x00FF, 0x00FF, 0x0000 }, /* R4369 - Write Sequencer 273 */
+ [4370] = { 0x070F, 0x070F, 0x0000 }, /* R4370 - Write Sequencer 274 */
+ [4371] = { 0x010F, 0x010F, 0x0000 }, /* R4371 - Write Sequencer 275 */
+ [4372] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4372 - Write Sequencer 276 */
+ [4373] = { 0x00FF, 0x00FF, 0x0000 }, /* R4373 - Write Sequencer 277 */
+ [4374] = { 0x070F, 0x070F, 0x0000 }, /* R4374 - Write Sequencer 278 */
+ [4375] = { 0x010F, 0x010F, 0x0000 }, /* R4375 - Write Sequencer 279 */
+ [4376] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4376 - Write Sequencer 280 */
+ [4377] = { 0x00FF, 0x00FF, 0x0000 }, /* R4377 - Write Sequencer 281 */
+ [4378] = { 0x070F, 0x070F, 0x0000 }, /* R4378 - Write Sequencer 282 */
+ [4379] = { 0x010F, 0x010F, 0x0000 }, /* R4379 - Write Sequencer 283 */
+ [4380] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4380 - Write Sequencer 284 */
+ [4381] = { 0x00FF, 0x00FF, 0x0000 }, /* R4381 - Write Sequencer 285 */
+ [4382] = { 0x070F, 0x070F, 0x0000 }, /* R4382 - Write Sequencer 286 */
+ [4383] = { 0x010F, 0x010F, 0x0000 }, /* R4383 - Write Sequencer 287 */
+ [4384] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4384 - Write Sequencer 288 */
+ [4385] = { 0x00FF, 0x00FF, 0x0000 }, /* R4385 - Write Sequencer 289 */
+ [4386] = { 0x070F, 0x070F, 0x0000 }, /* R4386 - Write Sequencer 290 */
+ [4387] = { 0x010F, 0x010F, 0x0000 }, /* R4387 - Write Sequencer 291 */
+ [4388] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4388 - Write Sequencer 292 */
+ [4389] = { 0x00FF, 0x00FF, 0x0000 }, /* R4389 - Write Sequencer 293 */
+ [4390] = { 0x070F, 0x070F, 0x0000 }, /* R4390 - Write Sequencer 294 */
+ [4391] = { 0x010F, 0x010F, 0x0000 }, /* R4391 - Write Sequencer 295 */
+ [4392] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4392 - Write Sequencer 296 */
+ [4393] = { 0x00FF, 0x00FF, 0x0000 }, /* R4393 - Write Sequencer 297 */
+ [4394] = { 0x070F, 0x070F, 0x0000 }, /* R4394 - Write Sequencer 298 */
+ [4395] = { 0x010F, 0x010F, 0x0000 }, /* R4395 - Write Sequencer 299 */
+ [4396] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4396 - Write Sequencer 300 */
+ [4397] = { 0x00FF, 0x00FF, 0x0000 }, /* R4397 - Write Sequencer 301 */
+ [4398] = { 0x070F, 0x070F, 0x0000 }, /* R4398 - Write Sequencer 302 */
+ [4399] = { 0x010F, 0x010F, 0x0000 }, /* R4399 - Write Sequencer 303 */
+ [4400] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4400 - Write Sequencer 304 */
+ [4401] = { 0x00FF, 0x00FF, 0x0000 }, /* R4401 - Write Sequencer 305 */
+ [4402] = { 0x070F, 0x070F, 0x0000 }, /* R4402 - Write Sequencer 306 */
+ [4403] = { 0x010F, 0x010F, 0x0000 }, /* R4403 - Write Sequencer 307 */
+ [4404] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4404 - Write Sequencer 308 */
+ [4405] = { 0x00FF, 0x00FF, 0x0000 }, /* R4405 - Write Sequencer 309 */
+ [4406] = { 0x070F, 0x070F, 0x0000 }, /* R4406 - Write Sequencer 310 */
+ [4407] = { 0x010F, 0x010F, 0x0000 }, /* R4407 - Write Sequencer 311 */
+ [4408] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4408 - Write Sequencer 312 */
+ [4409] = { 0x00FF, 0x00FF, 0x0000 }, /* R4409 - Write Sequencer 313 */
+ [4410] = { 0x070F, 0x070F, 0x0000 }, /* R4410 - Write Sequencer 314 */
+ [4411] = { 0x010F, 0x010F, 0x0000 }, /* R4411 - Write Sequencer 315 */
+ [4412] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4412 - Write Sequencer 316 */
+ [4413] = { 0x00FF, 0x00FF, 0x0000 }, /* R4413 - Write Sequencer 317 */
+ [4414] = { 0x070F, 0x070F, 0x0000 }, /* R4414 - Write Sequencer 318 */
+ [4415] = { 0x010F, 0x010F, 0x0000 }, /* R4415 - Write Sequencer 319 */
+ [4416] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4416 - Write Sequencer 320 */
+ [4417] = { 0x00FF, 0x00FF, 0x0000 }, /* R4417 - Write Sequencer 321 */
+ [4418] = { 0x070F, 0x070F, 0x0000 }, /* R4418 - Write Sequencer 322 */
+ [4419] = { 0x010F, 0x010F, 0x0000 }, /* R4419 - Write Sequencer 323 */
+ [4420] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4420 - Write Sequencer 324 */
+ [4421] = { 0x00FF, 0x00FF, 0x0000 }, /* R4421 - Write Sequencer 325 */
+ [4422] = { 0x070F, 0x070F, 0x0000 }, /* R4422 - Write Sequencer 326 */
+ [4423] = { 0x010F, 0x010F, 0x0000 }, /* R4423 - Write Sequencer 327 */
+ [4424] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4424 - Write Sequencer 328 */
+ [4425] = { 0x00FF, 0x00FF, 0x0000 }, /* R4425 - Write Sequencer 329 */
+ [4426] = { 0x070F, 0x070F, 0x0000 }, /* R4426 - Write Sequencer 330 */
+ [4427] = { 0x010F, 0x010F, 0x0000 }, /* R4427 - Write Sequencer 331 */
+ [4428] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4428 - Write Sequencer 332 */
+ [4429] = { 0x00FF, 0x00FF, 0x0000 }, /* R4429 - Write Sequencer 333 */
+ [4430] = { 0x070F, 0x070F, 0x0000 }, /* R4430 - Write Sequencer 334 */
+ [4431] = { 0x010F, 0x010F, 0x0000 }, /* R4431 - Write Sequencer 335 */
+ [4432] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4432 - Write Sequencer 336 */
+ [4433] = { 0x00FF, 0x00FF, 0x0000 }, /* R4433 - Write Sequencer 337 */
+ [4434] = { 0x070F, 0x070F, 0x0000 }, /* R4434 - Write Sequencer 338 */
+ [4435] = { 0x010F, 0x010F, 0x0000 }, /* R4435 - Write Sequencer 339 */
+ [4436] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4436 - Write Sequencer 340 */
+ [4437] = { 0x00FF, 0x00FF, 0x0000 }, /* R4437 - Write Sequencer 341 */
+ [4438] = { 0x070F, 0x070F, 0x0000 }, /* R4438 - Write Sequencer 342 */
+ [4439] = { 0x010F, 0x010F, 0x0000 }, /* R4439 - Write Sequencer 343 */
+ [4440] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4440 - Write Sequencer 344 */
+ [4441] = { 0x00FF, 0x00FF, 0x0000 }, /* R4441 - Write Sequencer 345 */
+ [4442] = { 0x070F, 0x070F, 0x0000 }, /* R4442 - Write Sequencer 346 */
+ [4443] = { 0x010F, 0x010F, 0x0000 }, /* R4443 - Write Sequencer 347 */
+ [4444] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4444 - Write Sequencer 348 */
+ [4445] = { 0x00FF, 0x00FF, 0x0000 }, /* R4445 - Write Sequencer 349 */
+ [4446] = { 0x070F, 0x070F, 0x0000 }, /* R4446 - Write Sequencer 350 */
+ [4447] = { 0x010F, 0x010F, 0x0000 }, /* R4447 - Write Sequencer 351 */
+ [4448] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4448 - Write Sequencer 352 */
+ [4449] = { 0x00FF, 0x00FF, 0x0000 }, /* R4449 - Write Sequencer 353 */
+ [4450] = { 0x070F, 0x070F, 0x0000 }, /* R4450 - Write Sequencer 354 */
+ [4451] = { 0x010F, 0x010F, 0x0000 }, /* R4451 - Write Sequencer 355 */
+ [4452] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4452 - Write Sequencer 356 */
+ [4453] = { 0x00FF, 0x00FF, 0x0000 }, /* R4453 - Write Sequencer 357 */
+ [4454] = { 0x070F, 0x070F, 0x0000 }, /* R4454 - Write Sequencer 358 */
+ [4455] = { 0x010F, 0x010F, 0x0000 }, /* R4455 - Write Sequencer 359 */
+ [4456] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4456 - Write Sequencer 360 */
+ [4457] = { 0x00FF, 0x00FF, 0x0000 }, /* R4457 - Write Sequencer 361 */
+ [4458] = { 0x070F, 0x070F, 0x0000 }, /* R4458 - Write Sequencer 362 */
+ [4459] = { 0x010F, 0x010F, 0x0000 }, /* R4459 - Write Sequencer 363 */
+ [4460] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4460 - Write Sequencer 364 */
+ [4461] = { 0x00FF, 0x00FF, 0x0000 }, /* R4461 - Write Sequencer 365 */
+ [4462] = { 0x070F, 0x070F, 0x0000 }, /* R4462 - Write Sequencer 366 */
+ [4463] = { 0x010F, 0x010F, 0x0000 }, /* R4463 - Write Sequencer 367 */
+ [4464] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4464 - Write Sequencer 368 */
+ [4465] = { 0x00FF, 0x00FF, 0x0000 }, /* R4465 - Write Sequencer 369 */
+ [4466] = { 0x070F, 0x070F, 0x0000 }, /* R4466 - Write Sequencer 370 */
+ [4467] = { 0x010F, 0x010F, 0x0000 }, /* R4467 - Write Sequencer 371 */
+ [4468] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4468 - Write Sequencer 372 */
+ [4469] = { 0x00FF, 0x00FF, 0x0000 }, /* R4469 - Write Sequencer 373 */
+ [4470] = { 0x070F, 0x070F, 0x0000 }, /* R4470 - Write Sequencer 374 */
+ [4471] = { 0x010F, 0x010F, 0x0000 }, /* R4471 - Write Sequencer 375 */
+ [4472] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4472 - Write Sequencer 376 */
+ [4473] = { 0x00FF, 0x00FF, 0x0000 }, /* R4473 - Write Sequencer 377 */
+ [4474] = { 0x070F, 0x070F, 0x0000 }, /* R4474 - Write Sequencer 378 */
+ [4475] = { 0x010F, 0x010F, 0x0000 }, /* R4475 - Write Sequencer 379 */
+ [4476] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4476 - Write Sequencer 380 */
+ [4477] = { 0x00FF, 0x00FF, 0x0000 }, /* R4477 - Write Sequencer 381 */
+ [4478] = { 0x070F, 0x070F, 0x0000 }, /* R4478 - Write Sequencer 382 */
+ [4479] = { 0x010F, 0x010F, 0x0000 }, /* R4479 - Write Sequencer 383 */
+ [4480] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4480 - Write Sequencer 384 */
+ [4481] = { 0x00FF, 0x00FF, 0x0000 }, /* R4481 - Write Sequencer 385 */
+ [4482] = { 0x070F, 0x070F, 0x0000 }, /* R4482 - Write Sequencer 386 */
+ [4483] = { 0x010F, 0x010F, 0x0000 }, /* R4483 - Write Sequencer 387 */
+ [4484] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4484 - Write Sequencer 388 */
+ [4485] = { 0x00FF, 0x00FF, 0x0000 }, /* R4485 - Write Sequencer 389 */
+ [4486] = { 0x070F, 0x070F, 0x0000 }, /* R4486 - Write Sequencer 390 */
+ [4487] = { 0x010F, 0x010F, 0x0000 }, /* R4487 - Write Sequencer 391 */
+ [4488] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4488 - Write Sequencer 392 */
+ [4489] = { 0x00FF, 0x00FF, 0x0000 }, /* R4489 - Write Sequencer 393 */
+ [4490] = { 0x070F, 0x070F, 0x0000 }, /* R4490 - Write Sequencer 394 */
+ [4491] = { 0x010F, 0x010F, 0x0000 }, /* R4491 - Write Sequencer 395 */
+ [4492] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4492 - Write Sequencer 396 */
+ [4493] = { 0x00FF, 0x00FF, 0x0000 }, /* R4493 - Write Sequencer 397 */
+ [4494] = { 0x070F, 0x070F, 0x0000 }, /* R4494 - Write Sequencer 398 */
+ [4495] = { 0x010F, 0x010F, 0x0000 }, /* R4495 - Write Sequencer 399 */
+ [4496] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4496 - Write Sequencer 400 */
+ [4497] = { 0x00FF, 0x00FF, 0x0000 }, /* R4497 - Write Sequencer 401 */
+ [4498] = { 0x070F, 0x070F, 0x0000 }, /* R4498 - Write Sequencer 402 */
+ [4499] = { 0x010F, 0x010F, 0x0000 }, /* R4499 - Write Sequencer 403 */
+ [4500] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4500 - Write Sequencer 404 */
+ [4501] = { 0x00FF, 0x00FF, 0x0000 }, /* R4501 - Write Sequencer 405 */
+ [4502] = { 0x070F, 0x070F, 0x0000 }, /* R4502 - Write Sequencer 406 */
+ [4503] = { 0x010F, 0x010F, 0x0000 }, /* R4503 - Write Sequencer 407 */
+ [4504] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4504 - Write Sequencer 408 */
+ [4505] = { 0x00FF, 0x00FF, 0x0000 }, /* R4505 - Write Sequencer 409 */
+ [4506] = { 0x070F, 0x070F, 0x0000 }, /* R4506 - Write Sequencer 410 */
+ [4507] = { 0x010F, 0x010F, 0x0000 }, /* R4507 - Write Sequencer 411 */
+ [4508] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4508 - Write Sequencer 412 */
+ [4509] = { 0x00FF, 0x00FF, 0x0000 }, /* R4509 - Write Sequencer 413 */
+ [4510] = { 0x070F, 0x070F, 0x0000 }, /* R4510 - Write Sequencer 414 */
+ [4511] = { 0x010F, 0x010F, 0x0000 }, /* R4511 - Write Sequencer 415 */
+ [4512] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4512 - Write Sequencer 416 */
+ [4513] = { 0x00FF, 0x00FF, 0x0000 }, /* R4513 - Write Sequencer 417 */
+ [4514] = { 0x070F, 0x070F, 0x0000 }, /* R4514 - Write Sequencer 418 */
+ [4515] = { 0x010F, 0x010F, 0x0000 }, /* R4515 - Write Sequencer 419 */
+ [4516] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4516 - Write Sequencer 420 */
+ [4517] = { 0x00FF, 0x00FF, 0x0000 }, /* R4517 - Write Sequencer 421 */
+ [4518] = { 0x070F, 0x070F, 0x0000 }, /* R4518 - Write Sequencer 422 */
+ [4519] = { 0x010F, 0x010F, 0x0000 }, /* R4519 - Write Sequencer 423 */
+ [4520] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4520 - Write Sequencer 424 */
+ [4521] = { 0x00FF, 0x00FF, 0x0000 }, /* R4521 - Write Sequencer 425 */
+ [4522] = { 0x070F, 0x070F, 0x0000 }, /* R4522 - Write Sequencer 426 */
+ [4523] = { 0x010F, 0x010F, 0x0000 }, /* R4523 - Write Sequencer 427 */
+ [4524] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4524 - Write Sequencer 428 */
+ [4525] = { 0x00FF, 0x00FF, 0x0000 }, /* R4525 - Write Sequencer 429 */
+ [4526] = { 0x070F, 0x070F, 0x0000 }, /* R4526 - Write Sequencer 430 */
+ [4527] = { 0x010F, 0x010F, 0x0000 }, /* R4527 - Write Sequencer 431 */
+ [4528] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4528 - Write Sequencer 432 */
+ [4529] = { 0x00FF, 0x00FF, 0x0000 }, /* R4529 - Write Sequencer 433 */
+ [4530] = { 0x070F, 0x070F, 0x0000 }, /* R4530 - Write Sequencer 434 */
+ [4531] = { 0x010F, 0x010F, 0x0000 }, /* R4531 - Write Sequencer 435 */
+ [4532] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4532 - Write Sequencer 436 */
+ [4533] = { 0x00FF, 0x00FF, 0x0000 }, /* R4533 - Write Sequencer 437 */
+ [4534] = { 0x070F, 0x070F, 0x0000 }, /* R4534 - Write Sequencer 438 */
+ [4535] = { 0x010F, 0x010F, 0x0000 }, /* R4535 - Write Sequencer 439 */
+ [4536] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4536 - Write Sequencer 440 */
+ [4537] = { 0x00FF, 0x00FF, 0x0000 }, /* R4537 - Write Sequencer 441 */
+ [4538] = { 0x070F, 0x070F, 0x0000 }, /* R4538 - Write Sequencer 442 */
+ [4539] = { 0x010F, 0x010F, 0x0000 }, /* R4539 - Write Sequencer 443 */
+ [4540] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4540 - Write Sequencer 444 */
+ [4541] = { 0x00FF, 0x00FF, 0x0000 }, /* R4541 - Write Sequencer 445 */
+ [4542] = { 0x070F, 0x070F, 0x0000 }, /* R4542 - Write Sequencer 446 */
+ [4543] = { 0x010F, 0x010F, 0x0000 }, /* R4543 - Write Sequencer 447 */
+ [4544] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4544 - Write Sequencer 448 */
+ [4545] = { 0x00FF, 0x00FF, 0x0000 }, /* R4545 - Write Sequencer 449 */
+ [4546] = { 0x070F, 0x070F, 0x0000 }, /* R4546 - Write Sequencer 450 */
+ [4547] = { 0x010F, 0x010F, 0x0000 }, /* R4547 - Write Sequencer 451 */
+ [4548] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4548 - Write Sequencer 452 */
+ [4549] = { 0x00FF, 0x00FF, 0x0000 }, /* R4549 - Write Sequencer 453 */
+ [4550] = { 0x070F, 0x070F, 0x0000 }, /* R4550 - Write Sequencer 454 */
+ [4551] = { 0x010F, 0x010F, 0x0000 }, /* R4551 - Write Sequencer 455 */
+ [4552] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4552 - Write Sequencer 456 */
+ [4553] = { 0x00FF, 0x00FF, 0x0000 }, /* R4553 - Write Sequencer 457 */
+ [4554] = { 0x070F, 0x070F, 0x0000 }, /* R4554 - Write Sequencer 458 */
+ [4555] = { 0x010F, 0x010F, 0x0000 }, /* R4555 - Write Sequencer 459 */
+ [4556] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4556 - Write Sequencer 460 */
+ [4557] = { 0x00FF, 0x00FF, 0x0000 }, /* R4557 - Write Sequencer 461 */
+ [4558] = { 0x070F, 0x070F, 0x0000 }, /* R4558 - Write Sequencer 462 */
+ [4559] = { 0x010F, 0x010F, 0x0000 }, /* R4559 - Write Sequencer 463 */
+ [4560] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4560 - Write Sequencer 464 */
+ [4561] = { 0x00FF, 0x00FF, 0x0000 }, /* R4561 - Write Sequencer 465 */
+ [4562] = { 0x070F, 0x070F, 0x0000 }, /* R4562 - Write Sequencer 466 */
+ [4563] = { 0x010F, 0x010F, 0x0000 }, /* R4563 - Write Sequencer 467 */
+ [4564] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4564 - Write Sequencer 468 */
+ [4565] = { 0x00FF, 0x00FF, 0x0000 }, /* R4565 - Write Sequencer 469 */
+ [4566] = { 0x070F, 0x070F, 0x0000 }, /* R4566 - Write Sequencer 470 */
+ [4567] = { 0x010F, 0x010F, 0x0000 }, /* R4567 - Write Sequencer 471 */
+ [4568] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4568 - Write Sequencer 472 */
+ [4569] = { 0x00FF, 0x00FF, 0x0000 }, /* R4569 - Write Sequencer 473 */
+ [4570] = { 0x070F, 0x070F, 0x0000 }, /* R4570 - Write Sequencer 474 */
+ [4571] = { 0x010F, 0x010F, 0x0000 }, /* R4571 - Write Sequencer 475 */
+ [4572] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4572 - Write Sequencer 476 */
+ [4573] = { 0x00FF, 0x00FF, 0x0000 }, /* R4573 - Write Sequencer 477 */
+ [4574] = { 0x070F, 0x070F, 0x0000 }, /* R4574 - Write Sequencer 478 */
+ [4575] = { 0x010F, 0x010F, 0x0000 }, /* R4575 - Write Sequencer 479 */
+ [4576] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4576 - Write Sequencer 480 */
+ [4577] = { 0x00FF, 0x00FF, 0x0000 }, /* R4577 - Write Sequencer 481 */
+ [4578] = { 0x070F, 0x070F, 0x0000 }, /* R4578 - Write Sequencer 482 */
+ [4579] = { 0x010F, 0x010F, 0x0000 }, /* R4579 - Write Sequencer 483 */
+ [4580] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4580 - Write Sequencer 484 */
+ [4581] = { 0x00FF, 0x00FF, 0x0000 }, /* R4581 - Write Sequencer 485 */
+ [4582] = { 0x070F, 0x070F, 0x0000 }, /* R4582 - Write Sequencer 486 */
+ [4583] = { 0x010F, 0x010F, 0x0000 }, /* R4583 - Write Sequencer 487 */
+ [4584] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4584 - Write Sequencer 488 */
+ [4585] = { 0x00FF, 0x00FF, 0x0000 }, /* R4585 - Write Sequencer 489 */
+ [4586] = { 0x070F, 0x070F, 0x0000 }, /* R4586 - Write Sequencer 490 */
+ [4587] = { 0x010F, 0x010F, 0x0000 }, /* R4587 - Write Sequencer 491 */
+ [4588] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4588 - Write Sequencer 492 */
+ [4589] = { 0x00FF, 0x00FF, 0x0000 }, /* R4589 - Write Sequencer 493 */
+ [4590] = { 0x070F, 0x070F, 0x0000 }, /* R4590 - Write Sequencer 494 */
+ [4591] = { 0x010F, 0x010F, 0x0000 }, /* R4591 - Write Sequencer 495 */
+ [4592] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4592 - Write Sequencer 496 */
+ [4593] = { 0x00FF, 0x00FF, 0x0000 }, /* R4593 - Write Sequencer 497 */
+ [4594] = { 0x070F, 0x070F, 0x0000 }, /* R4594 - Write Sequencer 498 */
+ [4595] = { 0x010F, 0x010F, 0x0000 }, /* R4595 - Write Sequencer 499 */
+ [4596] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4596 - Write Sequencer 500 */
+ [4597] = { 0x00FF, 0x00FF, 0x0000 }, /* R4597 - Write Sequencer 501 */
+ [4598] = { 0x070F, 0x070F, 0x0000 }, /* R4598 - Write Sequencer 502 */
+ [4599] = { 0x010F, 0x010F, 0x0000 }, /* R4599 - Write Sequencer 503 */
+ [4600] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4600 - Write Sequencer 504 */
+ [4601] = { 0x00FF, 0x00FF, 0x0000 }, /* R4601 - Write Sequencer 505 */
+ [4602] = { 0x070F, 0x070F, 0x0000 }, /* R4602 - Write Sequencer 506 */
+ [4603] = { 0x010F, 0x010F, 0x0000 }, /* R4603 - Write Sequencer 507 */
+ [4604] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4604 - Write Sequencer 508 */
+ [4605] = { 0x00FF, 0x00FF, 0x0000 }, /* R4605 - Write Sequencer 509 */
+ [4606] = { 0x070F, 0x070F, 0x0000 }, /* R4606 - Write Sequencer 510 */
+ [4607] = { 0x010F, 0x010F, 0x0000 }, /* R4607 - Write Sequencer 511 */
+ [8192] = { 0x03FF, 0x03FF, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */
+ [9216] = { 0x003F, 0x003F, 0x0000 }, /* R9216 - DSP2 Address RAM 2 */
+ [9217] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9217 - DSP2 Address RAM 1 */
+ [9218] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9218 - DSP2 Address RAM 0 */
+ [12288] = { 0x00FF, 0x00FF, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */
+ [12289] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */
+ [13312] = { 0x00FF, 0x00FF, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */
+ [13313] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */
+ [14336] = { 0x00FF, 0x00FF, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */
+ [14337] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */
+ [15360] = { 0x07FF, 0x07FF, 0x0000 }, /* R15360 - DSP2 Coeff RAM 0 */
+ [16384] = { 0x00FF, 0x00FF, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
+ [16385] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
+ [16386] = { 0x00FF, 0x00FF, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
+ [16387] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
+ [16388] = { 0x00FF, 0x00FF, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */
+ [16389] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */
+ [16896] = { 0x00FF, 0x00FF, 0x0000 }, /* R16896 - HDBASS_AI_1 */
+ [16897] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16897 - HDBASS_AI_0 */
+ [16898] = { 0x00FF, 0x00FF, 0x0000 }, /* R16898 - HDBASS_AR_1 */
+ [16899] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16899 - HDBASS_AR_0 */
+ [16900] = { 0x00FF, 0x00FF, 0x0000 }, /* R16900 - HDBASS_B_1 */
+ [16901] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16901 - HDBASS_B_0 */
+ [16902] = { 0x00FF, 0x00FF, 0x0000 }, /* R16902 - HDBASS_K_1 */
+ [16903] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16903 - HDBASS_K_0 */
+ [16904] = { 0x00FF, 0x00FF, 0x0000 }, /* R16904 - HDBASS_N1_1 */
+ [16905] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16905 - HDBASS_N1_0 */
+ [16906] = { 0x00FF, 0x00FF, 0x0000 }, /* R16906 - HDBASS_N2_1 */
+ [16907] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16907 - HDBASS_N2_0 */
+ [16908] = { 0x00FF, 0x00FF, 0x0000 }, /* R16908 - HDBASS_N3_1 */
+ [16909] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16909 - HDBASS_N3_0 */
+ [16910] = { 0x00FF, 0x00FF, 0x0000 }, /* R16910 - HDBASS_N4_1 */
+ [16911] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16911 - HDBASS_N4_0 */
+ [16912] = { 0x00FF, 0x00FF, 0x0000 }, /* R16912 - HDBASS_N5_1 */
+ [16913] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16913 - HDBASS_N5_0 */
+ [16914] = { 0x00FF, 0x00FF, 0x0000 }, /* R16914 - HDBASS_X1_1 */
+ [16915] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16915 - HDBASS_X1_0 */
+ [16916] = { 0x00FF, 0x00FF, 0x0000 }, /* R16916 - HDBASS_X2_1 */
+ [16917] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16917 - HDBASS_X2_0 */
+ [16918] = { 0x00FF, 0x00FF, 0x0000 }, /* R16918 - HDBASS_X3_1 */
+ [16919] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16919 - HDBASS_X3_0 */
+ [16920] = { 0x00FF, 0x00FF, 0x0000 }, /* R16920 - HDBASS_ATK_1 */
+ [16921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16921 - HDBASS_ATK_0 */
+ [16922] = { 0x00FF, 0x00FF, 0x0000 }, /* R16922 - HDBASS_DCY_1 */
+ [16923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16923 - HDBASS_DCY_0 */
+ [16924] = { 0x00FF, 0x00FF, 0x0000 }, /* R16924 - HDBASS_PG_1 */
+ [16925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16925 - HDBASS_PG_0 */
+ [17408] = { 0x00FF, 0x00FF, 0x0000 }, /* R17408 - HPF_C_1 */
+ [17409] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17409 - HPF_C_0 */
+ [17920] = { 0x00FF, 0x00FF, 0x0000 }, /* R17920 - ADCL_RETUNE_C1_1 */
+ [17921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17921 - ADCL_RETUNE_C1_0 */
+ [17922] = { 0x00FF, 0x00FF, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */
+ [17923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */
+ [17924] = { 0x00FF, 0x00FF, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */
+ [17925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */
+ [17926] = { 0x00FF, 0x00FF, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */
+ [17927] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */
+ [17928] = { 0x00FF, 0x00FF, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */
+ [17929] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */
+ [17930] = { 0x00FF, 0x00FF, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */
+ [17931] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */
+ [17932] = { 0x00FF, 0x00FF, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */
+ [17933] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */
+ [17934] = { 0x00FF, 0x00FF, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */
+ [17935] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */
+ [17936] = { 0x00FF, 0x00FF, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */
+ [17937] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */
+ [17938] = { 0x00FF, 0x00FF, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */
+ [17939] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */
+ [17940] = { 0x00FF, 0x00FF, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */
+ [17941] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */
+ [17942] = { 0x00FF, 0x00FF, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */
+ [17943] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */
+ [17944] = { 0x00FF, 0x00FF, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */
+ [17945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */
+ [17946] = { 0x00FF, 0x00FF, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */
+ [17947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */
+ [17948] = { 0x00FF, 0x00FF, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */
+ [17949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */
+ [17950] = { 0x00FF, 0x00FF, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */
+ [17951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */
+ [17952] = { 0x00FF, 0x00FF, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */
+ [17953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */
+ [17954] = { 0x00FF, 0x00FF, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */
+ [17955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */
+ [17956] = { 0x00FF, 0x00FF, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */
+ [17957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */
+ [17958] = { 0x00FF, 0x00FF, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */
+ [17959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */
+ [17960] = { 0x00FF, 0x00FF, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */
+ [17961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */
+ [17962] = { 0x00FF, 0x00FF, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */
+ [17963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */
+ [17964] = { 0x00FF, 0x00FF, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */
+ [17965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */
+ [17966] = { 0x00FF, 0x00FF, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */
+ [17967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */
+ [17968] = { 0x00FF, 0x00FF, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */
+ [17969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */
+ [17970] = { 0x00FF, 0x00FF, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */
+ [17971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */
+ [17972] = { 0x00FF, 0x00FF, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */
+ [17973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */
+ [17974] = { 0x00FF, 0x00FF, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */
+ [17975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */
+ [17976] = { 0x00FF, 0x00FF, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */
+ [17977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */
+ [17978] = { 0x00FF, 0x00FF, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */
+ [17979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */
+ [17980] = { 0x00FF, 0x00FF, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */
+ [17981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */
+ [17982] = { 0x00FF, 0x00FF, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */
+ [17983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */
+ [18432] = { 0x00FF, 0x00FF, 0x0000 }, /* R18432 - RETUNEADC_PG2_1 */
+ [18433] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */
+ [18434] = { 0x00FF, 0x00FF, 0x0000 }, /* R18434 - RETUNEADC_PG_1 */
+ [18435] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */
+ [18944] = { 0x00FF, 0x00FF, 0x0000 }, /* R18944 - ADCR_RETUNE_C1_1 */
+ [18945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18945 - ADCR_RETUNE_C1_0 */
+ [18946] = { 0x00FF, 0x00FF, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */
+ [18947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */
+ [18948] = { 0x00FF, 0x00FF, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */
+ [18949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */
+ [18950] = { 0x00FF, 0x00FF, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */
+ [18951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */
+ [18952] = { 0x00FF, 0x00FF, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */
+ [18953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */
+ [18954] = { 0x00FF, 0x00FF, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */
+ [18955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */
+ [18956] = { 0x00FF, 0x00FF, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */
+ [18957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */
+ [18958] = { 0x00FF, 0x00FF, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */
+ [18959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */
+ [18960] = { 0x00FF, 0x00FF, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */
+ [18961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */
+ [18962] = { 0x00FF, 0x00FF, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */
+ [18963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */
+ [18964] = { 0x00FF, 0x00FF, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */
+ [18965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */
+ [18966] = { 0x00FF, 0x00FF, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */
+ [18967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */
+ [18968] = { 0x00FF, 0x00FF, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */
+ [18969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */
+ [18970] = { 0x00FF, 0x00FF, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */
+ [18971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */
+ [18972] = { 0x00FF, 0x00FF, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */
+ [18973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */
+ [18974] = { 0x00FF, 0x00FF, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */
+ [18975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */
+ [18976] = { 0x00FF, 0x00FF, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */
+ [18977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */
+ [18978] = { 0x00FF, 0x00FF, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */
+ [18979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */
+ [18980] = { 0x00FF, 0x00FF, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */
+ [18981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */
+ [18982] = { 0x00FF, 0x00FF, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */
+ [18983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */
+ [18984] = { 0x00FF, 0x00FF, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */
+ [18985] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */
+ [18986] = { 0x00FF, 0x00FF, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */
+ [18987] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */
+ [18988] = { 0x00FF, 0x00FF, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */
+ [18989] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */
+ [18990] = { 0x00FF, 0x00FF, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */
+ [18991] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */
+ [18992] = { 0x00FF, 0x00FF, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */
+ [18993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */
+ [18994] = { 0x00FF, 0x00FF, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */
+ [18995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */
+ [18996] = { 0x00FF, 0x00FF, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */
+ [18997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */
+ [18998] = { 0x00FF, 0x00FF, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */
+ [18999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */
+ [19000] = { 0x00FF, 0x00FF, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */
+ [19001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */
+ [19002] = { 0x00FF, 0x00FF, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */
+ [19003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */
+ [19004] = { 0x00FF, 0x00FF, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */
+ [19005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */
+ [19006] = { 0x00FF, 0x00FF, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */
+ [19007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */
+ [19456] = { 0x00FF, 0x00FF, 0x0000 }, /* R19456 - DACL_RETUNE_C1_1 */
+ [19457] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19457 - DACL_RETUNE_C1_0 */
+ [19458] = { 0x00FF, 0x00FF, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */
+ [19459] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */
+ [19460] = { 0x00FF, 0x00FF, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */
+ [19461] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */
+ [19462] = { 0x00FF, 0x00FF, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */
+ [19463] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */
+ [19464] = { 0x00FF, 0x00FF, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */
+ [19465] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */
+ [19466] = { 0x00FF, 0x00FF, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */
+ [19467] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */
+ [19468] = { 0x00FF, 0x00FF, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */
+ [19469] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */
+ [19470] = { 0x00FF, 0x00FF, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */
+ [19471] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */
+ [19472] = { 0x00FF, 0x00FF, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */
+ [19473] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */
+ [19474] = { 0x00FF, 0x00FF, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */
+ [19475] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */
+ [19476] = { 0x00FF, 0x00FF, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */
+ [19477] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */
+ [19478] = { 0x00FF, 0x00FF, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */
+ [19479] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */
+ [19480] = { 0x00FF, 0x00FF, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */
+ [19481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */
+ [19482] = { 0x00FF, 0x00FF, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */
+ [19483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */
+ [19484] = { 0x00FF, 0x00FF, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */
+ [19485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */
+ [19486] = { 0x00FF, 0x00FF, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */
+ [19487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */
+ [19488] = { 0x00FF, 0x00FF, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */
+ [19489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */
+ [19490] = { 0x00FF, 0x00FF, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */
+ [19491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */
+ [19492] = { 0x00FF, 0x00FF, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */
+ [19493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */
+ [19494] = { 0x00FF, 0x00FF, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */
+ [19495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */
+ [19496] = { 0x00FF, 0x00FF, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */
+ [19497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */
+ [19498] = { 0x00FF, 0x00FF, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */
+ [19499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */
+ [19500] = { 0x00FF, 0x00FF, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */
+ [19501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */
+ [19502] = { 0x00FF, 0x00FF, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */
+ [19503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */
+ [19504] = { 0x00FF, 0x00FF, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */
+ [19505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */
+ [19506] = { 0x00FF, 0x00FF, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */
+ [19507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */
+ [19508] = { 0x00FF, 0x00FF, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */
+ [19509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */
+ [19510] = { 0x00FF, 0x00FF, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */
+ [19511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */
+ [19512] = { 0x00FF, 0x00FF, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */
+ [19513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */
+ [19514] = { 0x00FF, 0x00FF, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */
+ [19515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */
+ [19516] = { 0x00FF, 0x00FF, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */
+ [19517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */
+ [19518] = { 0x00FF, 0x00FF, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */
+ [19519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */
+ [19968] = { 0x00FF, 0x00FF, 0x0000 }, /* R19968 - RETUNEDAC_PG2_1 */
+ [19969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */
+ [19970] = { 0x00FF, 0x00FF, 0x0000 }, /* R19970 - RETUNEDAC_PG_1 */
+ [19971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */
+ [20480] = { 0x00FF, 0x00FF, 0x0000 }, /* R20480 - DACR_RETUNE_C1_1 */
+ [20481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20481 - DACR_RETUNE_C1_0 */
+ [20482] = { 0x00FF, 0x00FF, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */
+ [20483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */
+ [20484] = { 0x00FF, 0x00FF, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */
+ [20485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */
+ [20486] = { 0x00FF, 0x00FF, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */
+ [20487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */
+ [20488] = { 0x00FF, 0x00FF, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */
+ [20489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */
+ [20490] = { 0x00FF, 0x00FF, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */
+ [20491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */
+ [20492] = { 0x00FF, 0x00FF, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */
+ [20493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */
+ [20494] = { 0x00FF, 0x00FF, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */
+ [20495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */
+ [20496] = { 0x00FF, 0x00FF, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */
+ [20497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */
+ [20498] = { 0x00FF, 0x00FF, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */
+ [20499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */
+ [20500] = { 0x00FF, 0x00FF, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */
+ [20501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */
+ [20502] = { 0x00FF, 0x00FF, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */
+ [20503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */
+ [20504] = { 0x00FF, 0x00FF, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */
+ [20505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */
+ [20506] = { 0x00FF, 0x00FF, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */
+ [20507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */
+ [20508] = { 0x00FF, 0x00FF, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */
+ [20509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */
+ [20510] = { 0x00FF, 0x00FF, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */
+ [20511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */
+ [20512] = { 0x00FF, 0x00FF, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */
+ [20513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */
+ [20514] = { 0x00FF, 0x00FF, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */
+ [20515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */
+ [20516] = { 0x00FF, 0x00FF, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */
+ [20517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */
+ [20518] = { 0x00FF, 0x00FF, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */
+ [20519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */
+ [20520] = { 0x00FF, 0x00FF, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */
+ [20521] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */
+ [20522] = { 0x00FF, 0x00FF, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */
+ [20523] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */
+ [20524] = { 0x00FF, 0x00FF, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */
+ [20525] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */
+ [20526] = { 0x00FF, 0x00FF, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */
+ [20527] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */
+ [20528] = { 0x00FF, 0x00FF, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */
+ [20529] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */
+ [20530] = { 0x00FF, 0x00FF, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */
+ [20531] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */
+ [20532] = { 0x00FF, 0x00FF, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */
+ [20533] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */
+ [20534] = { 0x00FF, 0x00FF, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */
+ [20535] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */
+ [20536] = { 0x00FF, 0x00FF, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */
+ [20537] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */
+ [20538] = { 0x00FF, 0x00FF, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */
+ [20539] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */
+ [20540] = { 0x00FF, 0x00FF, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */
+ [20541] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */
+ [20542] = { 0x00FF, 0x00FF, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */
+ [20543] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */
+ [20992] = { 0x00FF, 0x00FF, 0x0000 }, /* R20992 - VSS_XHD2_1 */
+ [20993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20993 - VSS_XHD2_0 */
+ [20994] = { 0x00FF, 0x00FF, 0x0000 }, /* R20994 - VSS_XHD3_1 */
+ [20995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20995 - VSS_XHD3_0 */
+ [20996] = { 0x00FF, 0x00FF, 0x0000 }, /* R20996 - VSS_XHN1_1 */
+ [20997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20997 - VSS_XHN1_0 */
+ [20998] = { 0x00FF, 0x00FF, 0x0000 }, /* R20998 - VSS_XHN2_1 */
+ [20999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20999 - VSS_XHN2_0 */
+ [21000] = { 0x00FF, 0x00FF, 0x0000 }, /* R21000 - VSS_XHN3_1 */
+ [21001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21001 - VSS_XHN3_0 */
+ [21002] = { 0x00FF, 0x00FF, 0x0000 }, /* R21002 - VSS_XLA_1 */
+ [21003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21003 - VSS_XLA_0 */
+ [21004] = { 0x00FF, 0x00FF, 0x0000 }, /* R21004 - VSS_XLB_1 */
+ [21005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21005 - VSS_XLB_0 */
+ [21006] = { 0x00FF, 0x00FF, 0x0000 }, /* R21006 - VSS_XLG_1 */
+ [21007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21007 - VSS_XLG_0 */
+ [21008] = { 0x00FF, 0x00FF, 0x0000 }, /* R21008 - VSS_PG2_1 */
+ [21009] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21009 - VSS_PG2_0 */
+ [21010] = { 0x00FF, 0x00FF, 0x0000 }, /* R21010 - VSS_PG_1 */
+ [21011] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21011 - VSS_PG_0 */
+ [21012] = { 0x00FF, 0x00FF, 0x0000 }, /* R21012 - VSS_XTD1_1 */
+ [21013] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21013 - VSS_XTD1_0 */
+ [21014] = { 0x00FF, 0x00FF, 0x0000 }, /* R21014 - VSS_XTD2_1 */
+ [21015] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21015 - VSS_XTD2_0 */
+ [21016] = { 0x00FF, 0x00FF, 0x0000 }, /* R21016 - VSS_XTD3_1 */
+ [21017] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21017 - VSS_XTD3_0 */
+ [21018] = { 0x00FF, 0x00FF, 0x0000 }, /* R21018 - VSS_XTD4_1 */
+ [21019] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21019 - VSS_XTD4_0 */
+ [21020] = { 0x00FF, 0x00FF, 0x0000 }, /* R21020 - VSS_XTD5_1 */
+ [21021] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21021 - VSS_XTD5_0 */
+ [21022] = { 0x00FF, 0x00FF, 0x0000 }, /* R21022 - VSS_XTD6_1 */
+ [21023] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21023 - VSS_XTD6_0 */
+ [21024] = { 0x00FF, 0x00FF, 0x0000 }, /* R21024 - VSS_XTD7_1 */
+ [21025] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21025 - VSS_XTD7_0 */
+ [21026] = { 0x00FF, 0x00FF, 0x0000 }, /* R21026 - VSS_XTD8_1 */
+ [21027] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21027 - VSS_XTD8_0 */
+ [21028] = { 0x00FF, 0x00FF, 0x0000 }, /* R21028 - VSS_XTD9_1 */
+ [21029] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21029 - VSS_XTD9_0 */
+ [21030] = { 0x00FF, 0x00FF, 0x0000 }, /* R21030 - VSS_XTD10_1 */
+ [21031] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21031 - VSS_XTD10_0 */
+ [21032] = { 0x00FF, 0x00FF, 0x0000 }, /* R21032 - VSS_XTD11_1 */
+ [21033] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21033 - VSS_XTD11_0 */
+ [21034] = { 0x00FF, 0x00FF, 0x0000 }, /* R21034 - VSS_XTD12_1 */
+ [21035] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21035 - VSS_XTD12_0 */
+ [21036] = { 0x00FF, 0x00FF, 0x0000 }, /* R21036 - VSS_XTD13_1 */
+ [21037] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21037 - VSS_XTD13_0 */
+ [21038] = { 0x00FF, 0x00FF, 0x0000 }, /* R21038 - VSS_XTD14_1 */
+ [21039] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21039 - VSS_XTD14_0 */
+ [21040] = { 0x00FF, 0x00FF, 0x0000 }, /* R21040 - VSS_XTD15_1 */
+ [21041] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21041 - VSS_XTD15_0 */
+ [21042] = { 0x00FF, 0x00FF, 0x0000 }, /* R21042 - VSS_XTD16_1 */
+ [21043] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21043 - VSS_XTD16_0 */
+ [21044] = { 0x00FF, 0x00FF, 0x0000 }, /* R21044 - VSS_XTD17_1 */
+ [21045] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21045 - VSS_XTD17_0 */
+ [21046] = { 0x00FF, 0x00FF, 0x0000 }, /* R21046 - VSS_XTD18_1 */
+ [21047] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21047 - VSS_XTD18_0 */
+ [21048] = { 0x00FF, 0x00FF, 0x0000 }, /* R21048 - VSS_XTD19_1 */
+ [21049] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21049 - VSS_XTD19_0 */
+ [21050] = { 0x00FF, 0x00FF, 0x0000 }, /* R21050 - VSS_XTD20_1 */
+ [21051] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21051 - VSS_XTD20_0 */
+ [21052] = { 0x00FF, 0x00FF, 0x0000 }, /* R21052 - VSS_XTD21_1 */
+ [21053] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21053 - VSS_XTD21_0 */
+ [21054] = { 0x00FF, 0x00FF, 0x0000 }, /* R21054 - VSS_XTD22_1 */
+ [21055] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21055 - VSS_XTD22_0 */
+ [21056] = { 0x00FF, 0x00FF, 0x0000 }, /* R21056 - VSS_XTD23_1 */
+ [21057] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21057 - VSS_XTD23_0 */
+ [21058] = { 0x00FF, 0x00FF, 0x0000 }, /* R21058 - VSS_XTD24_1 */
+ [21059] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21059 - VSS_XTD24_0 */
+ [21060] = { 0x00FF, 0x00FF, 0x0000 }, /* R21060 - VSS_XTD25_1 */
+ [21061] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21061 - VSS_XTD25_0 */
+ [21062] = { 0x00FF, 0x00FF, 0x0000 }, /* R21062 - VSS_XTD26_1 */
+ [21063] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21063 - VSS_XTD26_0 */
+ [21064] = { 0x00FF, 0x00FF, 0x0000 }, /* R21064 - VSS_XTD27_1 */
+ [21065] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21065 - VSS_XTD27_0 */
+ [21066] = { 0x00FF, 0x00FF, 0x0000 }, /* R21066 - VSS_XTD28_1 */
+ [21067] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21067 - VSS_XTD28_0 */
+ [21068] = { 0x00FF, 0x00FF, 0x0000 }, /* R21068 - VSS_XTD29_1 */
+ [21069] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21069 - VSS_XTD29_0 */
+ [21070] = { 0x00FF, 0x00FF, 0x0000 }, /* R21070 - VSS_XTD30_1 */
+ [21071] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21071 - VSS_XTD30_0 */
+ [21072] = { 0x00FF, 0x00FF, 0x0000 }, /* R21072 - VSS_XTD31_1 */
+ [21073] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21073 - VSS_XTD31_0 */
+ [21074] = { 0x00FF, 0x00FF, 0x0000 }, /* R21074 - VSS_XTD32_1 */
+ [21075] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21075 - VSS_XTD32_0 */
+ [21076] = { 0x00FF, 0x00FF, 0x0000 }, /* R21076 - VSS_XTS1_1 */
+ [21077] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21077 - VSS_XTS1_0 */
+ [21078] = { 0x00FF, 0x00FF, 0x0000 }, /* R21078 - VSS_XTS2_1 */
+ [21079] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21079 - VSS_XTS2_0 */
+ [21080] = { 0x00FF, 0x00FF, 0x0000 }, /* R21080 - VSS_XTS3_1 */
+ [21081] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21081 - VSS_XTS3_0 */
+ [21082] = { 0x00FF, 0x00FF, 0x0000 }, /* R21082 - VSS_XTS4_1 */
+ [21083] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21083 - VSS_XTS4_0 */
+ [21084] = { 0x00FF, 0x00FF, 0x0000 }, /* R21084 - VSS_XTS5_1 */
+ [21085] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21085 - VSS_XTS5_0 */
+ [21086] = { 0x00FF, 0x00FF, 0x0000 }, /* R21086 - VSS_XTS6_1 */
+ [21087] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21087 - VSS_XTS6_0 */
+ [21088] = { 0x00FF, 0x00FF, 0x0000 }, /* R21088 - VSS_XTS7_1 */
+ [21089] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21089 - VSS_XTS7_0 */
+ [21090] = { 0x00FF, 0x00FF, 0x0000 }, /* R21090 - VSS_XTS8_1 */
+ [21091] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21091 - VSS_XTS8_0 */
+ [21092] = { 0x00FF, 0x00FF, 0x0000 }, /* R21092 - VSS_XTS9_1 */
+ [21093] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21093 - VSS_XTS9_0 */
+ [21094] = { 0x00FF, 0x00FF, 0x0000 }, /* R21094 - VSS_XTS10_1 */
+ [21095] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21095 - VSS_XTS10_0 */
+ [21096] = { 0x00FF, 0x00FF, 0x0000 }, /* R21096 - VSS_XTS11_1 */
+ [21097] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21097 - VSS_XTS11_0 */
+ [21098] = { 0x00FF, 0x00FF, 0x0000 }, /* R21098 - VSS_XTS12_1 */
+ [21099] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21099 - VSS_XTS12_0 */
+ [21100] = { 0x00FF, 0x00FF, 0x0000 }, /* R21100 - VSS_XTS13_1 */
+ [21101] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21101 - VSS_XTS13_0 */
+ [21102] = { 0x00FF, 0x00FF, 0x0000 }, /* R21102 - VSS_XTS14_1 */
+ [21103] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21103 - VSS_XTS14_0 */
+ [21104] = { 0x00FF, 0x00FF, 0x0000 }, /* R21104 - VSS_XTS15_1 */
+ [21105] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21105 - VSS_XTS15_0 */
+ [21106] = { 0x00FF, 0x00FF, 0x0000 }, /* R21106 - VSS_XTS16_1 */
+ [21107] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21107 - VSS_XTS16_0 */
+ [21108] = { 0x00FF, 0x00FF, 0x0000 }, /* R21108 - VSS_XTS17_1 */
+ [21109] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21109 - VSS_XTS17_0 */
+ [21110] = { 0x00FF, 0x00FF, 0x0000 }, /* R21110 - VSS_XTS18_1 */
+ [21111] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21111 - VSS_XTS18_0 */
+ [21112] = { 0x00FF, 0x00FF, 0x0000 }, /* R21112 - VSS_XTS19_1 */
+ [21113] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21113 - VSS_XTS19_0 */
+ [21114] = { 0x00FF, 0x00FF, 0x0000 }, /* R21114 - VSS_XTS20_1 */
+ [21115] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21115 - VSS_XTS20_0 */
+ [21116] = { 0x00FF, 0x00FF, 0x0000 }, /* R21116 - VSS_XTS21_1 */
+ [21117] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21117 - VSS_XTS21_0 */
+ [21118] = { 0x00FF, 0x00FF, 0x0000 }, /* R21118 - VSS_XTS22_1 */
+ [21119] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21119 - VSS_XTS22_0 */
+ [21120] = { 0x00FF, 0x00FF, 0x0000 }, /* R21120 - VSS_XTS23_1 */
+ [21121] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21121 - VSS_XTS23_0 */
+ [21122] = { 0x00FF, 0x00FF, 0x0000 }, /* R21122 - VSS_XTS24_1 */
+ [21123] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21123 - VSS_XTS24_0 */
+ [21124] = { 0x00FF, 0x00FF, 0x0000 }, /* R21124 - VSS_XTS25_1 */
+ [21125] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21125 - VSS_XTS25_0 */
+ [21126] = { 0x00FF, 0x00FF, 0x0000 }, /* R21126 - VSS_XTS26_1 */
+ [21127] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21127 - VSS_XTS26_0 */
+ [21128] = { 0x00FF, 0x00FF, 0x0000 }, /* R21128 - VSS_XTS27_1 */
+ [21129] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21129 - VSS_XTS27_0 */
+ [21130] = { 0x00FF, 0x00FF, 0x0000 }, /* R21130 - VSS_XTS28_1 */
+ [21131] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21131 - VSS_XTS28_0 */
+ [21132] = { 0x00FF, 0x00FF, 0x0000 }, /* R21132 - VSS_XTS29_1 */
+ [21133] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21133 - VSS_XTS29_0 */
+ [21134] = { 0x00FF, 0x00FF, 0x0000 }, /* R21134 - VSS_XTS30_1 */
+ [21135] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21135 - VSS_XTS30_0 */
+ [21136] = { 0x00FF, 0x00FF, 0x0000 }, /* R21136 - VSS_XTS31_1 */
+ [21137] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21137 - VSS_XTS31_0 */
+ [21138] = { 0x00FF, 0x00FF, 0x0000 }, /* R21138 - VSS_XTS32_1 */
+ [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
+};
+
+static int wm8962_volatile_register(unsigned int reg)
+{
+ if (wm8962_reg_access[reg].vol)
+ return 1;
+ else
+ return 0;
+}
+
+static int wm8962_readable_register(unsigned int reg)
+{
+ if (wm8962_reg_access[reg].read)
+ return 1;
+ else
+ return 0;
+}
+
+static int wm8962_reset(struct snd_soc_codec *codec)
+{
+ return snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0);
+}
+
+static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
+static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0);
+static const unsigned int mixinpga_tlv[] = {
+ TLV_DB_RANGE_HEAD(7),
+ 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0),
+ 3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0),
+ 5, 5, TLV_DB_SCALE_ITEM(2400, 0, 0),
+ 6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0),
+};
+static const DECLARE_TLV_DB_SCALE(beep_tlv, -9600, 600, 1);
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
+static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
+static const DECLARE_TLV_DB_SCALE(inmix_tlv, -600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
+static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0);
+static const unsigned int classd_tlv[] = {
+ TLV_DB_RANGE_HEAD(7),
+ 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
+};
+
+/* The VU bits for the headphones are in a different register to the mute
+ * bits and only take effect on the PGA if it is actually powered.
+ */
+static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = wm8962->reg_cache;
+ int ret;
+
+ /* Apply the update (if any) */
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+ if (ret == 0)
+ return 0;
+
+ /* If the left PGA is enabled hit that VU bit... */
+ if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA)
+ return snd_soc_write(codec, WM8962_HPOUTL_VOLUME,
+ reg_cache[WM8962_HPOUTL_VOLUME]);
+
+ /* ...otherwise the right. The VU is stereo. */
+ if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA)
+ return snd_soc_write(codec, WM8962_HPOUTR_VOLUME,
+ reg_cache[WM8962_HPOUTR_VOLUME]);
+
+ return 0;
+}
+
+/* The VU bits for the speakers are in a different register to the mute
+ * bits and only take effect on the PGA if it is actually powered.
+ */
+static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = wm8962->reg_cache;
+ int ret;
+
+ /* Apply the update (if any) */
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+ if (ret == 0)
+ return 0;
+
+ /* If the left PGA is enabled hit that VU bit... */
+ if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
+ return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
+ reg_cache[WM8962_SPKOUTL_VOLUME]);
+
+ /* ...otherwise the right. The VU is stereo. */
+ if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
+ return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
+ reg_cache[WM8962_SPKOUTR_VOLUME]);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new wm8962_snd_controls[] = {
+SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1),
+
+SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 6, 7, 0,
+ mixin_tlv),
+SOC_SINGLE_TLV("MIXINL PGA Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 3, 7, 0,
+ mixinpga_tlv),
+SOC_SINGLE_TLV("MIXINL IN3L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 0, 7, 0,
+ mixin_tlv),
+
+SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 6, 7, 0,
+ mixin_tlv),
+SOC_SINGLE_TLV("MIXINR PGA Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 3, 7, 0,
+ mixinpga_tlv),
+SOC_SINGLE_TLV("MIXINR IN3R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 0, 7, 0,
+ mixin_tlv),
+
+SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8962_LEFT_ADC_VOLUME,
+ WM8962_RIGHT_ADC_VOLUME, 1, 127, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("Capture Volume", WM8962_LEFT_INPUT_VOLUME,
+ WM8962_RIGHT_INPUT_VOLUME, 0, 63, 0, inpga_tlv),
+SOC_DOUBLE_R("Capture Switch", WM8962_LEFT_INPUT_VOLUME,
+ WM8962_RIGHT_INPUT_VOLUME, 7, 1, 1),
+SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME,
+ WM8962_RIGHT_INPUT_VOLUME, 6, 1, 1),
+
+SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
+ WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv),
+
+SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME,
+ WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv),
+SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0),
+
+SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1,
+ 5, 1, 0),
+
+SOC_SINGLE_TLV("Beep Volume", WM8962_BEEP_GENERATOR_1, 4, 15, 0, beep_tlv),
+
+SOC_DOUBLE_R_TLV("Headphone Volume", WM8962_HPOUTL_VOLUME,
+ WM8962_HPOUTR_VOLUME, 0, 127, 0, out_tlv),
+SOC_DOUBLE_EXT("Headphone Switch", WM8962_PWR_MGMT_2, 1, 0, 1, 1,
+ snd_soc_get_volsw, wm8962_put_hp_sw),
+SOC_DOUBLE_R("Headphone ZC Switch", WM8962_HPOUTL_VOLUME, WM8962_HPOUTR_VOLUME,
+ 7, 1, 0),
+SOC_DOUBLE_TLV("Headphone Aux Volume", WM8962_ANALOGUE_HP_2, 3, 6, 7, 0,
+ hp_tlv),
+
+SOC_DOUBLE_R("Headphone Mixer Switch", WM8962_HEADPHONE_MIXER_3,
+ WM8962_HEADPHONE_MIXER_4, 8, 1, 1),
+
+SOC_SINGLE_TLV("HPMIXL IN4L Volume", WM8962_HEADPHONE_MIXER_3,
+ 3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("HPMIXL IN4R Volume", WM8962_HEADPHONE_MIXER_3,
+ 0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("HPMIXL MIXINL Volume", WM8962_HEADPHONE_MIXER_3,
+ 7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("HPMIXL MIXINR Volume", WM8962_HEADPHONE_MIXER_3,
+ 6, 1, 1, inmix_tlv),
+
+SOC_SINGLE_TLV("HPMIXR IN4L Volume", WM8962_HEADPHONE_MIXER_4,
+ 3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("HPMIXR IN4R Volume", WM8962_HEADPHONE_MIXER_4,
+ 0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("HPMIXR MIXINL Volume", WM8962_HEADPHONE_MIXER_4,
+ 7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4,
+ 6, 1, 1, inmix_tlv),
+
+SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0,
+ classd_tlv),
+};
+
+static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
+SOC_SINGLE_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME, 0, 127, 0, out_tlv),
+SOC_SINGLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 1, 1,
+ snd_soc_get_volsw, wm8962_put_spk_sw),
+SOC_SINGLE("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, 7, 1, 0),
+
+SOC_SINGLE("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3, 8, 1, 1),
+SOC_SINGLE_TLV("Speaker Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3,
+ 3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("Speaker Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3,
+ 0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("Speaker Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3,
+ 7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("Speaker Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3,
+ 6, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("Speaker Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
+ 7, 1, 0, inmix_tlv),
+SOC_SINGLE_TLV("Speaker Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
+ 6, 1, 0, inmix_tlv),
+};
+
+static const struct snd_kcontrol_new wm8962_spk_stereo_controls[] = {
+SOC_DOUBLE_R_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME,
+ WM8962_SPKOUTR_VOLUME, 0, 127, 0, out_tlv),
+SOC_DOUBLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 0, 1, 1,
+ snd_soc_get_volsw, wm8962_put_spk_sw),
+SOC_DOUBLE_R("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, WM8962_SPKOUTR_VOLUME,
+ 7, 1, 0),
+
+SOC_DOUBLE_R("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3,
+ WM8962_SPEAKER_MIXER_4, 8, 1, 1),
+
+SOC_SINGLE_TLV("SPKOUTL Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3,
+ 3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3,
+ 0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3,
+ 7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3,
+ 6, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
+ 7, 1, 0, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
+ 6, 1, 0, inmix_tlv),
+
+SOC_SINGLE_TLV("SPKOUTR Mixer IN4L Volume", WM8962_SPEAKER_MIXER_4,
+ 3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer IN4R Volume", WM8962_SPEAKER_MIXER_4,
+ 0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_4,
+ 7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_4,
+ 6, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
+ 5, 1, 0, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
+ 4, 1, 0, inmix_tlv),
+};
+
+static int sysclk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int src;
+ int fll;
+
+ src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK;
+
+ switch (src) {
+ case 0: /* MCLK */
+ fll = 0;
+ break;
+ case 0x200: /* FLL */
+ fll = 1;
+ break;
+ default:
+ dev_err(codec->dev, "Unknown SYSCLK source %x\n", src);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (fll)
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+ WM8962_FLL_ENA, WM8962_FLL_ENA);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ if (fll)
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+ WM8962_FLL_ENA, 0);
+ break;
+
+ default:
+ BUG();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ msleep(5);
+ break;
+
+ default:
+ BUG();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int timeout;
+ int reg;
+ int expected = (WM8962_DCS_STARTUP_DONE_HP1L |
+ WM8962_DCS_STARTUP_DONE_HP1R);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+ WM8962_HP1L_ENA | WM8962_HP1R_ENA,
+ WM8962_HP1L_ENA | WM8962_HP1R_ENA);
+ udelay(20);
+
+ snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+ WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY,
+ WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY);
+
+ /* Start the DC servo */
+ snd_soc_update_bits(codec, WM8962_DC_SERVO_1,
+ WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
+ WM8962_HP1L_DCS_STARTUP |
+ WM8962_HP1R_DCS_STARTUP,
+ WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
+ WM8962_HP1L_DCS_STARTUP |
+ WM8962_HP1R_DCS_STARTUP);
+
+ /* Wait for it to complete, should be well under 100ms */
+ timeout = 0;
+ do {
+ msleep(1);
+ reg = snd_soc_read(codec, WM8962_DC_SERVO_6);
+ if (reg < 0) {
+ dev_err(codec->dev,
+ "Failed to read DCS status: %d\n",
+ reg);
+ continue;
+ }
+ dev_dbg(codec->dev, "DCS status: %x\n", reg);
+ } while (++timeout < 200 && (reg & expected) != expected);
+
+ if ((reg & expected) != expected)
+ dev_err(codec->dev, "DC servo timed out\n");
+ else
+ dev_dbg(codec->dev, "DC servo complete after %dms\n",
+ timeout);
+
+ snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+ WM8962_HP1L_ENA_OUTP |
+ WM8962_HP1R_ENA_OUTP,
+ WM8962_HP1L_ENA_OUTP |
+ WM8962_HP1R_ENA_OUTP);
+ udelay(20);
+
+ snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+ WM8962_HP1L_RMV_SHORT |
+ WM8962_HP1R_RMV_SHORT,
+ WM8962_HP1L_RMV_SHORT |
+ WM8962_HP1R_RMV_SHORT);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+ WM8962_HP1L_RMV_SHORT |
+ WM8962_HP1R_RMV_SHORT, 0);
+
+ udelay(20);
+
+ snd_soc_update_bits(codec, WM8962_DC_SERVO_1,
+ WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
+ WM8962_HP1L_DCS_STARTUP |
+ WM8962_HP1R_DCS_STARTUP,
+ 0);
+
+ snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+ WM8962_HP1L_ENA | WM8962_HP1R_ENA |
+ WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY |
+ WM8962_HP1L_ENA_OUTP |
+ WM8962_HP1R_ENA_OUTP, 0);
+
+ break;
+
+ default:
+ BUG();
+ return -EINVAL;
+
+ }
+
+ return 0;
+}
+
+/* VU bits for the output PGAs only take effect while the PGA is powered */
+static int out_pga_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = wm8962->reg_cache;
+ int reg;
+
+ switch (w->shift) {
+ case WM8962_HPOUTR_PGA_ENA_SHIFT:
+ reg = WM8962_HPOUTR_VOLUME;
+ break;
+ case WM8962_HPOUTL_PGA_ENA_SHIFT:
+ reg = WM8962_HPOUTL_VOLUME;
+ break;
+ case WM8962_SPKOUTR_PGA_ENA_SHIFT:
+ reg = WM8962_SPKOUTR_VOLUME;
+ break;
+ case WM8962_SPKOUTL_PGA_ENA_SHIFT:
+ reg = WM8962_SPKOUTL_VOLUME;
+ break;
+ default:
+ BUG();
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ return snd_soc_write(codec, reg, reg_cache[reg]);
+ default:
+ BUG();
+ return -EINVAL;
+ }
+}
+
+static const char *st_text[] = { "None", "Right", "Left" };
+
+static const struct soc_enum str_enum =
+ SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text);
+
+static const struct snd_kcontrol_new str_mux =
+ SOC_DAPM_ENUM("Right Sidetone", str_enum);
+
+static const struct soc_enum stl_enum =
+ SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text);
+
+static const struct snd_kcontrol_new stl_mux =
+ SOC_DAPM_ENUM("Left Sidetone", stl_enum);
+
+static const char *outmux_text[] = { "DAC", "Mixer" };
+
+static const struct soc_enum spkoutr_enum =
+ SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text);
+
+static const struct snd_kcontrol_new spkoutr_mux =
+ SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum);
+
+static const struct soc_enum spkoutl_enum =
+ SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text);
+
+static const struct snd_kcontrol_new spkoutl_mux =
+ SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum);
+
+static const struct soc_enum hpoutr_enum =
+ SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text);
+
+static const struct snd_kcontrol_new hpoutr_mux =
+ SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum);
+
+static const struct soc_enum hpoutl_enum =
+ SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text);
+
+static const struct snd_kcontrol_new hpoutl_mux =
+ SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum);
+
+static const struct snd_kcontrol_new inpgal[] = {
+SOC_DAPM_SINGLE("IN1L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 3, 1, 0),
+SOC_DAPM_SINGLE("IN2L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 2, 1, 0),
+SOC_DAPM_SINGLE("IN3L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new inpgar[] = {
+SOC_DAPM_SINGLE("IN1R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 3, 1, 0),
+SOC_DAPM_SINGLE("IN2R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 2, 1, 0),
+SOC_DAPM_SINGLE("IN3R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mixinl[] = {
+SOC_DAPM_SINGLE("IN2L Switch", WM8962_INPUT_MIXER_CONTROL_2, 5, 1, 0),
+SOC_DAPM_SINGLE("IN3L Switch", WM8962_INPUT_MIXER_CONTROL_2, 4, 1, 0),
+SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new mixinr[] = {
+SOC_DAPM_SINGLE("IN2R Switch", WM8962_INPUT_MIXER_CONTROL_2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN3R Switch", WM8962_INPUT_MIXER_CONTROL_2, 1, 1, 0),
+SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new hpmixl[] = {
+SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_1, 5, 1, 0),
+SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_1, 4, 1, 0),
+SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_1, 3, 1, 0),
+SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_1, 2, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_1, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new hpmixr[] = {
+SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_2, 5, 1, 0),
+SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_2, 4, 1, 0),
+SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_2, 3, 1, 0),
+SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new spkmixl[] = {
+SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_1, 5, 1, 0),
+SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_1, 4, 1, 0),
+SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_1, 3, 1, 0),
+SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_1, 2, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_1, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new spkmixr[] = {
+SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_2, 5, 1, 0),
+SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_2, 4, 1, 0),
+SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_2, 3, 1, 0),
+SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_2, 0, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8962_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+SND_SOC_DAPM_INPUT("IN4L"),
+SND_SOC_DAPM_INPUT("IN4R"),
+SND_SOC_DAPM_INPUT("Beep"),
+
+SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0),
+
+SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event,
+ SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
+ inpgal, ARRAY_SIZE(inpgal)),
+SND_SOC_DAPM_MIXER("INPGAR", WM8962_RIGHT_INPUT_PGA_CONTROL, 4, 0,
+ inpgar, ARRAY_SIZE(inpgar)),
+SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0,
+ mixinl, ARRAY_SIZE(mixinl)),
+SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0,
+ mixinr, ARRAY_SIZE(mixinr)),
+
+SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0),
+SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0),
+
+SND_SOC_DAPM_MUX("STL", SND_SOC_NOPM, 0, 0, &stl_mux),
+SND_SOC_DAPM_MUX("STR", SND_SOC_NOPM, 0, 0, &str_mux),
+
+SND_SOC_DAPM_DAC("DACL", "Playback", WM8962_PWR_MGMT_2, 8, 0),
+SND_SOC_DAPM_DAC("DACR", "Playback", WM8962_PWR_MGMT_2, 7, 0),
+
+SND_SOC_DAPM_PGA("Left Bypass", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Bypass", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_MIXER("HPMIXL", WM8962_MIXER_ENABLES, 3, 0,
+ hpmixl, ARRAY_SIZE(hpmixl)),
+SND_SOC_DAPM_MIXER("HPMIXR", WM8962_MIXER_ENABLES, 2, 0,
+ hpmixr, ARRAY_SIZE(hpmixr)),
+
+SND_SOC_DAPM_MUX_E("HPOUTL PGA", WM8962_PWR_MGMT_2, 6, 0, &hpoutl_mux,
+ out_pga_event, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_MUX_E("HPOUTR PGA", WM8962_PWR_MGMT_2, 5, 0, &hpoutr_mux,
+ out_pga_event, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA_E("HPOUT", SND_SOC_NOPM, 0, 0, NULL, 0, hp_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_OUTPUT("HPOUTL"),
+SND_SOC_DAPM_OUTPUT("HPOUTR"),
+};
+
+static const struct snd_soc_dapm_widget wm8962_dapm_spk_mono_widgets[] = {
+SND_SOC_DAPM_MIXER("Speaker Mixer", WM8962_MIXER_ENABLES, 1, 0,
+ spkmixl, ARRAY_SIZE(spkmixl)),
+SND_SOC_DAPM_MUX_E("Speaker PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
+ out_pga_event, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA("Speaker Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
+SND_SOC_DAPM_OUTPUT("SPKOUT"),
+};
+
+static const struct snd_soc_dapm_widget wm8962_dapm_spk_stereo_widgets[] = {
+SND_SOC_DAPM_MIXER("SPKOUTL Mixer", WM8962_MIXER_ENABLES, 1, 0,
+ spkmixl, ARRAY_SIZE(spkmixl)),
+SND_SOC_DAPM_MIXER("SPKOUTR Mixer", WM8962_MIXER_ENABLES, 0, 0,
+ spkmixr, ARRAY_SIZE(spkmixr)),
+
+SND_SOC_DAPM_MUX_E("SPKOUTL PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
+ out_pga_event, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_MUX_E("SPKOUTR PGA", WM8962_PWR_MGMT_2, 3, 0, &spkoutr_mux,
+ out_pga_event, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("SPKOUTL"),
+SND_SOC_DAPM_OUTPUT("SPKOUTR"),
+};
+
+static const struct snd_soc_dapm_route wm8962_intercon[] = {
+ { "INPGAL", "IN1L Switch", "IN1L" },
+ { "INPGAL", "IN2L Switch", "IN2L" },
+ { "INPGAL", "IN3L Switch", "IN3L" },
+ { "INPGAL", "IN4L Switch", "IN4L" },
+
+ { "INPGAR", "IN1R Switch", "IN1R" },
+ { "INPGAR", "IN2R Switch", "IN2R" },
+ { "INPGAR", "IN3R Switch", "IN3R" },
+ { "INPGAR", "IN4R Switch", "IN4R" },
+
+ { "MIXINL", "IN2L Switch", "IN2L" },
+ { "MIXINL", "IN3L Switch", "IN3L" },
+ { "MIXINL", "PGA Switch", "INPGAL" },
+
+ { "MIXINR", "IN2R Switch", "IN2R" },
+ { "MIXINR", "IN3R Switch", "IN3R" },
+ { "MIXINR", "PGA Switch", "INPGAR" },
+
+ { "MICBIAS", NULL, "SYSCLK" },
+
+ { "ADCL", NULL, "SYSCLK" },
+ { "ADCL", NULL, "TOCLK" },
+ { "ADCL", NULL, "MIXINL" },
+
+ { "ADCR", NULL, "SYSCLK" },
+ { "ADCR", NULL, "TOCLK" },
+ { "ADCR", NULL, "MIXINR" },
+
+ { "STL", "Left", "ADCL" },
+ { "STL", "Right", "ADCR" },
+
+ { "STR", "Left", "ADCL" },
+ { "STR", "Right", "ADCR" },
+
+ { "DACL", NULL, "SYSCLK" },
+ { "DACL", NULL, "TOCLK" },
+ { "DACL", NULL, "Beep" },
+ { "DACL", NULL, "STL" },
+
+ { "DACR", NULL, "SYSCLK" },
+ { "DACR", NULL, "TOCLK" },
+ { "DACR", NULL, "Beep" },
+ { "DACR", NULL, "STR" },
+
+ { "HPMIXL", "IN4L Switch", "IN4L" },
+ { "HPMIXL", "IN4R Switch", "IN4R" },
+ { "HPMIXL", "DACL Switch", "DACL" },
+ { "HPMIXL", "DACR Switch", "DACR" },
+ { "HPMIXL", "MIXINL Switch", "MIXINL" },
+ { "HPMIXL", "MIXINR Switch", "MIXINR" },
+
+ { "HPMIXR", "IN4L Switch", "IN4L" },
+ { "HPMIXR", "IN4R Switch", "IN4R" },
+ { "HPMIXR", "DACL Switch", "DACL" },
+ { "HPMIXR", "DACR Switch", "DACR" },
+ { "HPMIXR", "MIXINL Switch", "MIXINL" },
+ { "HPMIXR", "MIXINR Switch", "MIXINR" },
+
+ { "Left Bypass", NULL, "HPMIXL" },
+ { "Left Bypass", NULL, "Class G" },
+
+ { "Right Bypass", NULL, "HPMIXR" },
+ { "Right Bypass", NULL, "Class G" },
+
+ { "HPOUTL PGA", "Mixer", "Left Bypass" },
+ { "HPOUTL PGA", "DAC", "DACL" },
+
+ { "HPOUTR PGA", "Mixer", "Right Bypass" },
+ { "HPOUTR PGA", "DAC", "DACR" },
+
+ { "HPOUT", NULL, "HPOUTL PGA" },
+ { "HPOUT", NULL, "HPOUTR PGA" },
+ { "HPOUT", NULL, "Charge Pump" },
+ { "HPOUT", NULL, "SYSCLK" },
+ { "HPOUT", NULL, "TOCLK" },
+
+ { "HPOUTL", NULL, "HPOUT" },
+ { "HPOUTR", NULL, "HPOUT" },
+};
+
+static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
+ { "Speaker Mixer", "IN4L Switch", "IN4L" },
+ { "Speaker Mixer", "IN4R Switch", "IN4R" },
+ { "Speaker Mixer", "DACL Switch", "DACL" },
+ { "Speaker Mixer", "DACR Switch", "DACR" },
+ { "Speaker Mixer", "MIXINL Switch", "MIXINL" },
+ { "Speaker Mixer", "MIXINR Switch", "MIXINR" },
+
+ { "Speaker PGA", "Mixer", "Speaker Mixer" },
+ { "Speaker PGA", "DAC", "DACL" },
+
+ { "Speaker Output", NULL, "Speaker PGA" },
+ { "Speaker Output", NULL, "SYSCLK" },
+ { "Speaker Output", NULL, "TOCLK" },
+
+ { "SPKOUT", NULL, "Speaker Output" },
+};
+
+static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = {
+ { "SPKOUTL Mixer", "IN4L Switch", "IN4L" },
+ { "SPKOUTL Mixer", "IN4R Switch", "IN4R" },
+ { "SPKOUTL Mixer", "DACL Switch", "DACL" },
+ { "SPKOUTL Mixer", "DACR Switch", "DACR" },
+ { "SPKOUTL Mixer", "MIXINL Switch", "MIXINL" },
+ { "SPKOUTL Mixer", "MIXINR Switch", "MIXINR" },
+
+ { "SPKOUTR Mixer", "IN4L Switch", "IN4L" },
+ { "SPKOUTR Mixer", "IN4R Switch", "IN4R" },
+ { "SPKOUTR Mixer", "DACL Switch", "DACL" },
+ { "SPKOUTR Mixer", "DACR Switch", "DACR" },
+ { "SPKOUTR Mixer", "MIXINL Switch", "MIXINL" },
+ { "SPKOUTR Mixer", "MIXINR Switch", "MIXINR" },
+
+ { "SPKOUTL PGA", "Mixer", "SPKOUTL Mixer" },
+ { "SPKOUTL PGA", "DAC", "DACL" },
+
+ { "SPKOUTR PGA", "Mixer", "SPKOUTR Mixer" },
+ { "SPKOUTR PGA", "DAC", "DACR" },
+
+ { "SPKOUTL Output", NULL, "SPKOUTL PGA" },
+ { "SPKOUTL Output", NULL, "SYSCLK" },
+ { "SPKOUTL Output", NULL, "TOCLK" },
+
+ { "SPKOUTR Output", NULL, "SPKOUTR PGA" },
+ { "SPKOUTR Output", NULL, "SYSCLK" },
+ { "SPKOUTR Output", NULL, "TOCLK" },
+
+ { "SPKOUTL", NULL, "SPKOUTL Output" },
+ { "SPKOUTR", NULL, "SPKOUTR Output" },
+};
+
+static int wm8962_add_widgets(struct snd_soc_codec *codec)
+{
+ struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
+
+ snd_soc_add_controls(codec, wm8962_snd_controls,
+ ARRAY_SIZE(wm8962_snd_controls));
+ if (pdata && pdata->spk_mono)
+ snd_soc_add_controls(codec, wm8962_spk_mono_controls,
+ ARRAY_SIZE(wm8962_spk_mono_controls));
+ else
+ snd_soc_add_controls(codec, wm8962_spk_stereo_controls,
+ ARRAY_SIZE(wm8962_spk_stereo_controls));
+
+
+ snd_soc_dapm_new_controls(codec, wm8962_dapm_widgets,
+ ARRAY_SIZE(wm8962_dapm_widgets));
+ if (pdata && pdata->spk_mono)
+ snd_soc_dapm_new_controls(codec, wm8962_dapm_spk_mono_widgets,
+ ARRAY_SIZE(wm8962_dapm_spk_mono_widgets));
+ else
+ snd_soc_dapm_new_controls(codec, wm8962_dapm_spk_stereo_widgets,
+ ARRAY_SIZE(wm8962_dapm_spk_stereo_widgets));
+
+ snd_soc_dapm_add_routes(codec, wm8962_intercon,
+ ARRAY_SIZE(wm8962_intercon));
+ if (pdata && pdata->spk_mono)
+ snd_soc_dapm_add_routes(codec, wm8962_spk_mono_intercon,
+ ARRAY_SIZE(wm8962_spk_mono_intercon));
+ else
+ snd_soc_dapm_add_routes(codec, wm8962_spk_stereo_intercon,
+ ARRAY_SIZE(wm8962_spk_stereo_intercon));
+
+
+ snd_soc_dapm_disable_pin(codec, "Beep");
+
+ return 0;
+}
+
+static void wm8962_sync_cache(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ if (!codec->cache_sync)
+ return;
+
+ dev_dbg(codec->dev, "Syncing cache\n");
+
+ codec->cache_only = 0;
+
+ /* Sync back cached values if they're different from the
+ * hardware default.
+ */
+ for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+ if (i == WM8962_SOFTWARE_RESET)
+ continue;
+ if (wm8962->reg_cache[i] == wm8962_reg[i])
+ continue;
+
+ snd_soc_write(codec, i, wm8962->reg_cache[i]);
+ }
+
+ codec->cache_sync = 0;
+}
+
+/* -1 for reserved values */
+static const int bclk_divs[] = {
+ 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
+};
+
+static void wm8962_configure_bclk(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int dspclk, i;
+ int clocking2 = 0;
+ int aif2 = 0;
+
+ if (!wm8962->bclk) {
+ dev_dbg(codec->dev, "No BCLK rate configured\n");
+ return;
+ }
+
+ dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
+ if (dspclk < 0) {
+ dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
+ return;
+ }
+
+ dspclk = (dspclk & WM8962_DSPCLK_DIV_MASK) >> WM8962_DSPCLK_DIV_SHIFT;
+ switch (dspclk) {
+ case 0:
+ dspclk = wm8962->sysclk_rate;
+ break;
+ case 1:
+ dspclk = wm8962->sysclk_rate / 2;
+ break;
+ case 2:
+ dspclk = wm8962->sysclk_rate / 4;
+ break;
+ default:
+ dev_warn(codec->dev, "Unknown DSPCLK divisor read back\n");
+ dspclk = wm8962->sysclk;
+ }
+
+ dev_dbg(codec->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk);
+
+ /* We're expecting an exact match */
+ for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
+ if (bclk_divs[i] < 0)
+ continue;
+
+ if (dspclk / bclk_divs[i] == wm8962->bclk) {
+ dev_dbg(codec->dev, "Selected BCLK_DIV %d for %dHz\n",
+ bclk_divs[i], wm8962->bclk);
+ clocking2 |= i;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(bclk_divs)) {
+ dev_err(codec->dev, "Unsupported BCLK ratio %d\n",
+ dspclk / wm8962->bclk);
+ return;
+ }
+
+ aif2 |= wm8962->bclk / wm8962->lrclk;
+ dev_dbg(codec->dev, "Selected LRCLK divisor %d for %dHz\n",
+ wm8962->bclk / wm8962->lrclk, wm8962->lrclk);
+
+ snd_soc_update_bits(codec, WM8962_CLOCKING2,
+ WM8962_BCLK_DIV_MASK, clocking2);
+ snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_2,
+ WM8962_AIF_RATE_MASK, aif2);
+}
+
+static int wm8962_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ if (level == codec->bias_level)
+ return 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ /* VMID 2*50k */
+ snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK, 0x80);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ if (ret != 0) {
+ dev_err(codec->dev,
+ "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+
+ wm8962_sync_cache(codec);
+
+ snd_soc_update_bits(codec, WM8962_ANTI_POP,
+ WM8962_STARTUP_BIAS_ENA |
+ WM8962_VMID_BUF_ENA,
+ WM8962_STARTUP_BIAS_ENA |
+ WM8962_VMID_BUF_ENA);
+
+ /* Bias enable at 2*50k for ramp */
+ snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK |
+ WM8962_BIAS_ENA,
+ WM8962_BIAS_ENA | 0x180);
+
+ msleep(5);
+
+ snd_soc_update_bits(codec, WM8962_CLOCKING2,
+ WM8962_CLKREG_OVD,
+ WM8962_CLKREG_OVD);
+
+ wm8962_configure_bclk(codec);
+ }
+
+ /* VMID 2*250k */
+ snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK, 0x100);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
+
+ snd_soc_update_bits(codec, WM8962_ANTI_POP,
+ WM8962_STARTUP_BIAS_ENA |
+ WM8962_VMID_BUF_ENA, 0);
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ break;
+ }
+ codec->bias_level = level;
+ return 0;
+}
+
+static const struct {
+ int rate;
+ int reg;
+} sr_vals[] = {
+ { 48000, 0 },
+ { 44100, 0 },
+ { 32000, 1 },
+ { 22050, 2 },
+ { 24000, 2 },
+ { 16000, 3 },
+ { 11025, 4 },
+ { 12000, 4 },
+ { 8000, 5 },
+ { 88200, 6 },
+ { 96000, 6 },
+};
+
+static const int sysclk_rates[] = {
+ 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+};
+
+static int wm8962_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int rate = params_rate(params);
+ int i;
+ int aif0 = 0;
+ int adctl3 = 0;
+ int clocking4 = 0;
+
+ wm8962->bclk = snd_soc_params_to_bclk(params);
+ wm8962->lrclk = params_rate(params);
+
+ for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
+ if (sr_vals[i].rate == rate) {
+ adctl3 |= sr_vals[i].reg;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(sr_vals)) {
+ dev_err(codec->dev, "Unsupported rate %dHz\n", rate);
+ return -EINVAL;
+ }
+
+ if (rate % 8000 == 0)
+ adctl3 |= WM8962_SAMPLE_RATE_INT_MODE;
+
+ for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
+ if (sysclk_rates[i] == wm8962->sysclk_rate / rate) {
+ clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(sysclk_rates)) {
+ dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
+ wm8962->sysclk_rate / rate);
+ return -EINVAL;
+ }
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ aif0 |= 0x40;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ aif0 |= 0x80;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ aif0 |= 0xc0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0,
+ WM8962_WL_MASK, aif0);
+ snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3,
+ WM8962_SAMPLE_RATE_INT_MODE |
+ WM8962_SAMPLE_RATE_MASK, adctl3);
+ snd_soc_update_bits(codec, WM8962_CLOCKING_4,
+ WM8962_SYSCLK_RATE_MASK, clocking4);
+
+ wm8962_configure_bclk(codec);
+
+ return 0;
+}
+
+static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int src;
+
+ switch (clk_id) {
+ case WM8962_SYSCLK_MCLK:
+ wm8962->sysclk = WM8962_SYSCLK_MCLK;
+ src = 0;
+ break;
+ case WM8962_SYSCLK_FLL:
+ wm8962->sysclk = WM8962_SYSCLK_FLL;
+ src = 1 << WM8962_SYSCLK_SRC_SHIFT;
+ WARN_ON(freq != wm8962->fll_fout);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_SRC_MASK,
+ src);
+
+ wm8962->sysclk_rate = freq;
+
+ return 0;
+}
+
+static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int aif0 = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ aif0 |= WM8962_LRCLK_INV;
+ case SND_SOC_DAIFMT_DSP_B:
+ aif0 |= 3;
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ case SND_SOC_DAIFMT_IB_NF:
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ case SND_SOC_DAIFMT_RIGHT_J:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ aif0 |= 1;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ aif0 |= 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ aif0 |= WM8962_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ aif0 |= WM8962_LRCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ aif0 |= WM8962_BCLK_INV | WM8962_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ aif0 |= WM8962_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0,
+ WM8962_FMT_MASK | WM8962_BCLK_INV | WM8962_MSTR |
+ WM8962_LRCLK_INV, aif0);
+
+ return 0;
+}
+
+struct _fll_div {
+ u16 fll_fratio;
+ u16 fll_outdiv;
+ u16 fll_refclk_div;
+ u16 n;
+ u16 theta;
+ u16 lambda;
+};
+
+/* The size in bits of the FLL divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_FLL_SIZE ((1 << 16) * 10)
+
+static struct {
+ unsigned int min;
+ unsigned int max;
+ u16 fll_fratio;
+ int ratio;
+} fll_fratios[] = {
+ { 0, 64000, 4, 16 },
+ { 64000, 128000, 3, 8 },
+ { 128000, 256000, 2, 4 },
+ { 256000, 1000000, 1, 2 },
+ { 1000000, 13500000, 0, 1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+ unsigned int Fout)
+{
+ unsigned int target;
+ unsigned int div;
+ unsigned int fratio, gcd_fll;
+ int i;
+
+ /* Fref must be <=13.5MHz */
+ div = 1;
+ fll_div->fll_refclk_div = 0;
+ while ((Fref / div) > 13500000) {
+ div *= 2;
+ fll_div->fll_refclk_div++;
+
+ if (div > 4) {
+ pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+ Fref);
+ return -EINVAL;
+ }
+ }
+
+ pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+ /* Apply the division for our remaining calculations */
+ Fref /= div;
+
+ /* Fvco should be 90-100MHz; don't check the upper bound */
+ div = 2;
+ while (Fout * div < 90000000) {
+ div++;
+ if (div > 64) {
+ pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+ Fout);
+ return -EINVAL;
+ }
+ }
+ target = Fout * div;
+ fll_div->fll_outdiv = div - 1;
+
+ pr_debug("FLL Fvco=%dHz\n", target);
+
+ /* Find an appropraite FLL_FRATIO and factor it out of the target */
+ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+ if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+ fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+ fratio = fll_fratios[i].ratio;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(fll_fratios)) {
+ pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+ return -EINVAL;
+ }
+
+ fll_div->n = target / (fratio * Fref);
+
+ if (target % Fref == 0) {
+ fll_div->theta = 0;
+ fll_div->lambda = 0;
+ } else {
+ gcd_fll = gcd(target, fratio * Fref);
+
+ fll_div->theta = (target - (fll_div->n * fratio * Fref))
+ / gcd_fll;
+ fll_div->lambda = (fratio * Fref) / gcd_fll;
+ }
+
+ pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+ fll_div->n, fll_div->theta, fll_div->lambda);
+ pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+ fll_div->fll_fratio, fll_div->fll_outdiv,
+ fll_div->fll_refclk_div);
+
+ return 0;
+}
+
+static int wm8962_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
+ unsigned int Fref, unsigned int Fout)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ struct _fll_div fll_div;
+ int ret;
+ int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
+
+ /* Any change? */
+ if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
+ Fout == wm8962->fll_fout)
+ return 0;
+
+ if (Fout == 0) {
+ dev_dbg(codec->dev, "FLL disabled\n");
+
+ wm8962->fll_fref = 0;
+ wm8962->fll_fout = 0;
+
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+ WM8962_FLL_ENA, 0);
+
+ return 0;
+ }
+
+ ret = fll_factors(&fll_div, Fref, Fout);
+ if (ret != 0)
+ return ret;
+
+ switch (fll_id) {
+ case WM8962_FLL_MCLK:
+ case WM8962_FLL_BCLK:
+ case WM8962_FLL_OSC:
+ fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT;
+ break;
+ case WM8962_FLL_INT:
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+ WM8962_FLL_OSC_ENA, WM8962_FLL_OSC_ENA);
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_5,
+ WM8962_FLL_FRC_NCO, WM8962_FLL_FRC_NCO);
+ break;
+ default:
+ dev_err(codec->dev, "Unknown FLL source %d\n", ret);
+ return -EINVAL;
+ }
+
+ if (fll_div.theta || fll_div.lambda)
+ fll1 |= WM8962_FLL_FRAC;
+
+ /* Stop the FLL while we reconfigure */
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
+
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_2,
+ WM8962_FLL_OUTDIV_MASK |
+ WM8962_FLL_REFCLK_DIV_MASK,
+ (fll_div.fll_outdiv << WM8962_FLL_OUTDIV_SHIFT) |
+ (fll_div.fll_refclk_div));
+
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_3,
+ WM8962_FLL_FRATIO_MASK, fll_div.fll_fratio);
+
+ snd_soc_write(codec, WM8962_FLL_CONTROL_6, fll_div.theta);
+ snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda);
+ snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n);
+
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+ WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
+ WM8962_FLL_ENA, fll1);
+
+ dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
+
+ wm8962->fll_fref = Fref;
+ wm8962->fll_fout = Fout;
+ wm8962->fll_src = source;
+
+ return 0;
+}
+
+static int wm8962_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int val;
+
+ if (mute)
+ val = WM8962_DAC_MUTE;
+ else
+ val = 0;
+
+ return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
+ WM8962_DAC_MUTE, val);
+}
+
+#define WM8962_RATES SNDRV_PCM_RATE_8000_96000
+
+#define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops wm8962_dai_ops = {
+ .hw_params = wm8962_hw_params,
+ .set_sysclk = wm8962_set_dai_sysclk,
+ .set_fmt = wm8962_set_dai_fmt,
+ .set_pll = wm8962_set_fll,
+ .digital_mute = wm8962_mute,
+};
+
+static struct snd_soc_dai_driver wm8962_dai = {
+ .name = "wm8962",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM8962_RATES,
+ .formats = WM8962_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM8962_RATES,
+ .formats = WM8962_FORMATS,
+ },
+ .ops = &wm8962_dai_ops,
+ .symmetric_rates = 1,
+};
+
+static void wm8962_mic_work(struct work_struct *work)
+{
+ struct wm8962_priv *wm8962 = container_of(work,
+ struct wm8962_priv,
+ mic_work.work);
+ struct snd_soc_codec *codec = wm8962->codec;
+ int status = 0;
+ int irq_pol = 0;
+ int reg;
+
+ reg = snd_soc_read(codec, WM8962_ADDITIONAL_CONTROL_4);
+
+ if (reg & WM8962_MICDET_STS) {
+ status |= SND_JACK_MICROPHONE;
+ irq_pol |= WM8962_MICD_IRQ_POL;
+ }
+
+ if (reg & WM8962_MICSHORT_STS) {
+ status |= SND_JACK_BTN_0;
+ irq_pol |= WM8962_MICSCD_IRQ_POL;
+ }
+
+ snd_soc_jack_report(wm8962->jack, status,
+ SND_JACK_MICROPHONE | SND_JACK_BTN_0);
+
+ snd_soc_update_bits(codec, WM8962_MICINT_SOURCE_POL,
+ WM8962_MICSCD_IRQ_POL |
+ WM8962_MICD_IRQ_POL, irq_pol);
+}
+
+static irqreturn_t wm8962_irq(int irq, void *data)
+{
+ struct snd_soc_codec *codec = data;
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int mask;
+ int active;
+
+ mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
+
+ active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
+ active &= ~mask;
+
+ if (active & WM8962_FIFOS_ERR_EINT)
+ dev_err(codec->dev, "FIFO error\n");
+
+ if (active & WM8962_TEMP_SHUT_EINT)
+ dev_crit(codec->dev, "Thermal shutdown\n");
+
+ if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
+ dev_dbg(codec->dev, "Microphone event detected\n");
+
+ schedule_delayed_work(&wm8962->mic_work,
+ msecs_to_jiffies(250));
+ }
+
+ /* Acknowledge the interrupts */
+ snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * wm8962_mic_detect - Enable microphone detection via the WM8962 IRQ
+ *
+ * @codec: WM8962 codec
+ * @jack: jack to report detection events on
+ *
+ * Enable microphone detection via IRQ on the WM8962. If GPIOs are
+ * being used to bring out signals to the processor then only platform
+ * data configuration is needed for WM8962 and processor GPIOs should
+ * be configured using snd_soc_jack_add_gpios() instead.
+ *
+ * If no jack is supplied detection will be disabled.
+ */
+int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int irq_mask, enable;
+
+ wm8962->jack = jack;
+ if (jack) {
+ irq_mask = 0;
+ enable = WM8962_MICDET_ENA;
+ } else {
+ irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
+ enable = 0;
+ }
+
+ snd_soc_update_bits(codec, WM8962_INTERRUPT_STATUS_2_MASK,
+ WM8962_MICD_EINT | WM8962_MICSCD_EINT, irq_mask);
+ snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
+ WM8962_MICDET_ENA, enable);
+
+ /* Send an initial empty report */
+ snd_soc_jack_report(wm8962->jack, 0,
+ SND_JACK_MICROPHONE | SND_JACK_BTN_0);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8962_mic_detect);
+
+#ifdef CONFIG_PM
+static int wm8962_resume(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ u16 *reg_cache = codec->reg_cache;
+ int i;
+
+ /* Restore the registers */
+ for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+ switch (i) {
+ case WM8962_SOFTWARE_RESET:
+ continue;
+ default:
+ break;
+ }
+
+ if (reg_cache[i] != wm8962_reg[i])
+ snd_soc_write(codec, i, reg_cache[i]);
+ }
+
+ return 0;
+}
+#else
+#define wm8962_resume NULL
+#endif
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int beep_rates[] = {
+ 500, 1000, 2000, 4000,
+};
+
+static void wm8962_beep_work(struct work_struct *work)
+{
+ struct wm8962_priv *wm8962 =
+ container_of(work, struct wm8962_priv, beep_work);
+ struct snd_soc_codec *codec = wm8962->codec;
+ int i;
+ int reg = 0;
+ int best = 0;
+
+ if (wm8962->beep_rate) {
+ for (i = 0; i < ARRAY_SIZE(beep_rates); i++) {
+ if (abs(wm8962->beep_rate - beep_rates[i]) <
+ abs(wm8962->beep_rate - beep_rates[best]))
+ best = i;
+ }
+
+ dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n",
+ beep_rates[best], wm8962->beep_rate);
+
+ reg = WM8962_BEEP_ENA | (best << WM8962_BEEP_RATE_SHIFT);
+
+ snd_soc_dapm_enable_pin(codec, "Beep");
+ } else {
+ dev_dbg(codec->dev, "Disabling beep\n");
+ snd_soc_dapm_disable_pin(codec, "Beep");
+ }
+
+ snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1,
+ WM8962_BEEP_ENA | WM8962_BEEP_RATE_MASK, reg);
+
+ snd_soc_dapm_sync(codec);
+}
+
+/* For usability define a way of injecting beep events for the device -
+ * many systems will not have a keyboard.
+ */
+static int wm8962_beep_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int hz)
+{
+ struct snd_soc_codec *codec = input_get_drvdata(dev);
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "Beep event %x %x\n", code, hz);
+
+ switch (code) {
+ case SND_BELL:
+ if (hz)
+ hz = 1000;
+ case SND_TONE:
+ break;
+ default:
+ return -1;
+ }
+
+ /* Kick the beep from a workqueue */
+ wm8962->beep_rate = hz;
+ schedule_work(&wm8962->beep_work);
+ return 0;
+}
+
+static ssize_t wm8962_beep_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+ long int time;
+ int ret;
+
+ ret = strict_strtol(buf, 10, &time);
+ if (ret != 0)
+ return ret;
+
+ input_event(wm8962->beep, EV_SND, SND_TONE, time);
+
+ return count;
+}
+
+static DEVICE_ATTR(beep, 0200, NULL, wm8962_beep_set);
+
+static void wm8962_init_beep(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ wm8962->beep = input_allocate_device();
+ if (!wm8962->beep) {
+ dev_err(codec->dev, "Failed to allocate beep device\n");
+ return;
+ }
+
+ INIT_WORK(&wm8962->beep_work, wm8962_beep_work);
+ wm8962->beep_rate = 0;
+
+ wm8962->beep->name = "WM8962 Beep Generator";
+ wm8962->beep->phys = dev_name(codec->dev);
+ wm8962->beep->id.bustype = BUS_I2C;
+
+ wm8962->beep->evbit[0] = BIT_MASK(EV_SND);
+ wm8962->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
+ wm8962->beep->event = wm8962_beep_event;
+ wm8962->beep->dev.parent = codec->dev;
+ input_set_drvdata(wm8962->beep, codec);
+
+ ret = input_register_device(wm8962->beep);
+ if (ret != 0) {
+ input_free_device(wm8962->beep);
+ wm8962->beep = NULL;
+ dev_err(codec->dev, "Failed to register beep device\n");
+ }
+
+ ret = device_create_file(codec->dev, &dev_attr_beep);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to create keyclick file: %d\n",
+ ret);
+ }
+}
+
+static void wm8962_free_beep(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+ device_remove_file(codec->dev, &dev_attr_beep);
+ input_unregister_device(wm8962->beep);
+ cancel_work_sync(&wm8962->beep_work);
+ wm8962->beep = NULL;
+
+ snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1, WM8962_BEEP_ENA,0);
+}
+#else
+static void wm8962_init_beep(struct snd_soc_codec *codec)
+{
+}
+
+static void wm8962_free_beep(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+static void wm8962_set_gpio_mode(struct snd_soc_codec *codec, int gpio)
+{
+ int mask = 0;
+ int val = 0;
+
+ /* Some of the GPIOs are behind MFP configuration and need to
+ * be put into GPIO mode. */
+ switch (gpio) {
+ case 2:
+ mask = WM8962_CLKOUT2_SEL_MASK;
+ val = 1 << WM8962_CLKOUT2_SEL_SHIFT;
+ break;
+ case 3:
+ mask = WM8962_CLKOUT3_SEL_MASK;
+ val = 1 << WM8962_CLKOUT3_SEL_SHIFT;
+ break;
+ default:
+ break;
+ }
+
+ if (mask)
+ snd_soc_update_bits(codec, WM8962_ANALOGUE_CLOCKING1,
+ mask, val);
+}
+
+#ifdef CONFIG_GPIOLIB
+static inline struct wm8962_priv *gpio_to_wm8962(struct gpio_chip *chip)
+{
+ return container_of(chip, struct wm8962_priv, gpio_chip);
+}
+
+static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
+ struct snd_soc_codec *codec = wm8962->codec;
+
+ /* The WM8962 GPIOs aren't linearly numbered. For simplicity
+ * we export linear numbers and error out if the unsupported
+ * ones are requsted.
+ */
+ switch (offset + 1) {
+ case 2:
+ case 3:
+ case 5:
+ case 6:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wm8962_set_gpio_mode(codec, offset + 1);
+
+ return 0;
+}
+
+static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
+ struct snd_soc_codec *codec = wm8962->codec;
+
+ snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
+ WM8962_GP2_LVL, value << WM8962_GP2_LVL_SHIFT);
+}
+
+static int wm8962_gpio_direction_out(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
+ struct snd_soc_codec *codec = wm8962->codec;
+ int val;
+
+ /* Force function 1 (logic output) */
+ val = (1 << WM8962_GP2_FN_SHIFT) | (value << WM8962_GP2_LVL_SHIFT);
+
+ return snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
+ WM8962_GP2_FN_MASK | WM8962_GP2_LVL, val);
+}
+
+static struct gpio_chip wm8962_template_chip = {
+ .label = "wm8962",
+ .owner = THIS_MODULE,
+ .request = wm8962_gpio_request,
+ .direction_output = wm8962_gpio_direction_out,
+ .set = wm8962_gpio_set,
+ .can_sleep = 1,
+};
+
+static void wm8962_init_gpio(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
+ int ret;
+
+ wm8962->gpio_chip = wm8962_template_chip;
+ wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO;
+ wm8962->gpio_chip.dev = codec->dev;
+
+ if (pdata && pdata->gpio_base)
+ wm8962->gpio_chip.base = pdata->gpio_base;
+ else
+ wm8962->gpio_chip.base = -1;
+
+ ret = gpiochip_add(&wm8962->gpio_chip);
+ if (ret != 0)
+ dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+}
+
+static void wm8962_free_gpio(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = gpiochip_remove(&wm8962->gpio_chip);
+ if (ret != 0)
+ dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+}
+#else
+static void wm8962_init_gpio(struct snd_soc_codec *codec)
+{
+}
+
+static void wm8962_free_gpio(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+static int wm8962_probe(struct snd_soc_codec *codec)
+{
+ int ret;
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
+ struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
+ dev);
+ int i, trigger, irq_pol;
+
+ wm8962->codec = codec;
+ INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
+
+ codec->cache_sync = 1;
+ codec->idle_bias_off = 1;
+
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ goto err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
+ wm8962->supplies[i].supply = wm8962_supply_names[i];
+
+ ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ goto err;
+ }
+
+ wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
+ wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1;
+ wm8962->disable_nb[2].notifier_call = wm8962_regulator_event_2;
+ wm8962->disable_nb[3].notifier_call = wm8962_regulator_event_3;
+ wm8962->disable_nb[4].notifier_call = wm8962_regulator_event_4;
+ wm8962->disable_nb[5].notifier_call = wm8962_regulator_event_5;
+ wm8962->disable_nb[6].notifier_call = wm8962_regulator_event_6;
+ wm8962->disable_nb[7].notifier_call = wm8962_regulator_event_7;
+
+ /* This should really be moved into the regulator core */
+ for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) {
+ ret = regulator_register_notifier(wm8962->supplies[i].consumer,
+ &wm8962->disable_nb[i]);
+ if (ret != 0) {
+ dev_err(codec->dev,
+ "Failed to register regulator notifier: %d\n",
+ ret);
+ }
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_get;
+ }
+
+ ret = snd_soc_read(codec, WM8962_SOFTWARE_RESET);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to read ID register\n");
+ goto err_enable;
+ }
+ if (ret != wm8962_reg[WM8962_SOFTWARE_RESET]) {
+ dev_err(codec->dev, "Device is not a WM8962, ID %x != %x\n",
+ ret, wm8962_reg[WM8962_SOFTWARE_RESET]);
+ ret = -EINVAL;
+ goto err_enable;
+ }
+
+ ret = snd_soc_read(codec, WM8962_RIGHT_INPUT_VOLUME);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to read device revision: %d\n",
+ ret);
+ goto err_enable;
+ }
+
+ dev_info(codec->dev, "customer id %x revision %c\n",
+ (ret & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
+ ((ret & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
+ + 'A');
+
+ ret = wm8962_reset(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to issue reset\n");
+ goto err_enable;
+ }
+
+ /* SYSCLK defaults to on; make sure it is off so we can safely
+ * write to registers if the device is declocked.
+ */
+ snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0);
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+
+ if (pdata) {
+ /* Apply static configuration for GPIOs */
+ for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
+ if (pdata->gpio_init[i]) {
+ wm8962_set_gpio_mode(codec, i + 1);
+ snd_soc_write(codec, 0x200 + i,
+ pdata->gpio_init[i] & 0xffff);
+ }
+
+ /* Put the speakers into mono mode? */
+ if (pdata->spk_mono)
+ wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2]
+ |= WM8962_SPK_MONO;
+
+ /* Micbias setup, detection enable and detection
+ * threasholds. */
+ if (pdata->mic_cfg)
+ snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
+ WM8962_MICDET_ENA |
+ WM8962_MICDET_THR_MASK |
+ WM8962_MICSHORT_THR_MASK |
+ WM8962_MICBIAS_LVL,
+ pdata->mic_cfg);
+ }
+
+ /* Latch volume update bits */
+ wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
+ wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
+ wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
+ wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
+ wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
+ wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
+ wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
+ wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
+ wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
+ wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
+
+ wm8962_add_widgets(codec);
+
+ wm8962_init_beep(codec);
+ wm8962_init_gpio(codec);
+
+ if (i2c->irq) {
+ if (pdata && pdata->irq_active_low) {
+ trigger = IRQF_TRIGGER_LOW;
+ irq_pol = WM8962_IRQ_POL;
+ } else {
+ trigger = IRQF_TRIGGER_HIGH;
+ irq_pol = 0;
+ }
+
+ snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL,
+ WM8962_IRQ_POL, irq_pol);
+
+ ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq,
+ trigger | IRQF_ONESHOT,
+ "wm8962", codec);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
+ i2c->irq, ret);
+ /* Non-fatal */
+ } else {
+ /* Enable error reporting IRQs by default */
+ snd_soc_update_bits(codec,
+ WM8962_INTERRUPT_STATUS_2_MASK,
+ WM8962_TEMP_SHUT_EINT |
+ WM8962_FIFOS_ERR_EINT, 0);
+ }
+ }
+
+ return 0;
+
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err:
+ kfree(wm8962);
+ return ret;
+}
+
+static int wm8962_remove(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
+ dev);
+ int i;
+
+ if (i2c->irq)
+ free_irq(i2c->irq, codec);
+
+ cancel_delayed_work_sync(&wm8962->mic_work);
+
+ wm8962_free_gpio(codec);
+ wm8962_free_beep(codec);
+ for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
+ regulator_unregister_notifier(wm8962->supplies[i].consumer,
+ &wm8962->disable_nb[i]);
+ regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
+ .probe = wm8962_probe,
+ .remove = wm8962_remove,
+ .resume = wm8962_resume,
+ .set_bias_level = wm8962_set_bias_level,
+ .reg_cache_size = WM8962_MAX_REGISTER + 1,
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8962_reg,
+ .volatile_register = wm8962_volatile_register,
+ .readable_register = wm8962_readable_register,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8962_priv *wm8962;
+ int ret;
+
+ wm8962 = kzalloc(sizeof(struct wm8962_priv), GFP_KERNEL);
+ if (wm8962 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, wm8962);
+
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8962, &wm8962_dai, 1);
+ if (ret < 0)
+ kfree(wm8962);
+
+ return ret;
+}
+
+static __devexit int wm8962_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+static const struct i2c_device_id wm8962_i2c_id[] = {
+ { "wm8962", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id);
+
+static struct i2c_driver wm8962_i2c_driver = {
+ .driver = {
+ .name = "wm8962",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8962_i2c_probe,
+ .remove = __devexit_p(wm8962_i2c_remove),
+ .id_table = wm8962_i2c_id,
+};
+#endif
+
+static int __init wm8962_modinit(void)
+{
+ int ret;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8962_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register WM8962 I2C driver: %d\n",
+ ret);
+ }
+#endif
+ return 0;
+}
+module_init(wm8962_modinit);
+
+static void __exit wm8962_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8962_i2c_driver);
+#endif
+}
+module_exit(wm8962_exit);
+
+MODULE_DESCRIPTION("ASoC WM8962 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h
new file mode 100644
index 000000000000..a1a5d5294c19
--- /dev/null
+++ b/sound/soc/codecs/wm8962.h
@@ -0,0 +1,3780 @@
+/*
+ * wm8962.h -- WM8962 ASoC driver
+ *
+ * Copyright 2010 Wolfson Microelectronics, plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8962_H
+#define _WM8962_H
+
+#include <asm/types.h>
+#include <sound/soc.h>
+
+#define WM8962_SYSCLK_MCLK 1
+#define WM8962_SYSCLK_FLL 2
+#define WM8962_SYSCLK_PLL3 3
+
+#define WM8962_FLL 1
+
+#define WM8962_FLL_MCLK 1
+#define WM8962_FLL_BCLK 2
+#define WM8962_FLL_OSC 3
+#define WM8962_FLL_INT 4
+
+/*
+ * Register values.
+ */
+#define WM8962_LEFT_INPUT_VOLUME 0x00
+#define WM8962_RIGHT_INPUT_VOLUME 0x01
+#define WM8962_HPOUTL_VOLUME 0x02
+#define WM8962_HPOUTR_VOLUME 0x03
+#define WM8962_CLOCKING1 0x04
+#define WM8962_ADC_DAC_CONTROL_1 0x05
+#define WM8962_ADC_DAC_CONTROL_2 0x06
+#define WM8962_AUDIO_INTERFACE_0 0x07
+#define WM8962_CLOCKING2 0x08
+#define WM8962_AUDIO_INTERFACE_1 0x09
+#define WM8962_LEFT_DAC_VOLUME 0x0A
+#define WM8962_RIGHT_DAC_VOLUME 0x0B
+#define WM8962_AUDIO_INTERFACE_2 0x0E
+#define WM8962_SOFTWARE_RESET 0x0F
+#define WM8962_ALC1 0x11
+#define WM8962_ALC2 0x12
+#define WM8962_ALC3 0x13
+#define WM8962_NOISE_GATE 0x14
+#define WM8962_LEFT_ADC_VOLUME 0x15
+#define WM8962_RIGHT_ADC_VOLUME 0x16
+#define WM8962_ADDITIONAL_CONTROL_1 0x17
+#define WM8962_ADDITIONAL_CONTROL_2 0x18
+#define WM8962_PWR_MGMT_1 0x19
+#define WM8962_PWR_MGMT_2 0x1A
+#define WM8962_ADDITIONAL_CONTROL_3 0x1B
+#define WM8962_ANTI_POP 0x1C
+#define WM8962_CLOCKING_3 0x1E
+#define WM8962_INPUT_MIXER_CONTROL_1 0x1F
+#define WM8962_LEFT_INPUT_MIXER_VOLUME 0x20
+#define WM8962_RIGHT_INPUT_MIXER_VOLUME 0x21
+#define WM8962_INPUT_MIXER_CONTROL_2 0x22
+#define WM8962_INPUT_BIAS_CONTROL 0x23
+#define WM8962_LEFT_INPUT_PGA_CONTROL 0x25
+#define WM8962_RIGHT_INPUT_PGA_CONTROL 0x26
+#define WM8962_SPKOUTL_VOLUME 0x28
+#define WM8962_SPKOUTR_VOLUME 0x29
+#define WM8962_THERMAL_SHUTDOWN_STATUS 0x2F
+#define WM8962_ADDITIONAL_CONTROL_4 0x30
+#define WM8962_CLASS_D_CONTROL_1 0x31
+#define WM8962_CLASS_D_CONTROL_2 0x33
+#define WM8962_CLOCKING_4 0x38
+#define WM8962_DAC_DSP_MIXING_1 0x39
+#define WM8962_DAC_DSP_MIXING_2 0x3A
+#define WM8962_DC_SERVO_0 0x3C
+#define WM8962_DC_SERVO_1 0x3D
+#define WM8962_DC_SERVO_4 0x40
+#define WM8962_DC_SERVO_6 0x42
+#define WM8962_ANALOGUE_PGA_BIAS 0x44
+#define WM8962_ANALOGUE_HP_0 0x45
+#define WM8962_ANALOGUE_HP_2 0x47
+#define WM8962_CHARGE_PUMP_1 0x48
+#define WM8962_CHARGE_PUMP_B 0x52
+#define WM8962_WRITE_SEQUENCER_CONTROL_1 0x57
+#define WM8962_WRITE_SEQUENCER_CONTROL_2 0x5A
+#define WM8962_WRITE_SEQUENCER_CONTROL_3 0x5D
+#define WM8962_CONTROL_INTERFACE 0x5E
+#define WM8962_MIXER_ENABLES 0x63
+#define WM8962_HEADPHONE_MIXER_1 0x64
+#define WM8962_HEADPHONE_MIXER_2 0x65
+#define WM8962_HEADPHONE_MIXER_3 0x66
+#define WM8962_HEADPHONE_MIXER_4 0x67
+#define WM8962_SPEAKER_MIXER_1 0x69
+#define WM8962_SPEAKER_MIXER_2 0x6A
+#define WM8962_SPEAKER_MIXER_3 0x6B
+#define WM8962_SPEAKER_MIXER_4 0x6C
+#define WM8962_SPEAKER_MIXER_5 0x6D
+#define WM8962_BEEP_GENERATOR_1 0x6E
+#define WM8962_OSCILLATOR_TRIM_3 0x73
+#define WM8962_OSCILLATOR_TRIM_4 0x74
+#define WM8962_OSCILLATOR_TRIM_7 0x77
+#define WM8962_ANALOGUE_CLOCKING1 0x7C
+#define WM8962_ANALOGUE_CLOCKING2 0x7D
+#define WM8962_ANALOGUE_CLOCKING3 0x7E
+#define WM8962_PLL_SOFTWARE_RESET 0x7F
+#define WM8962_PLL2 0x81
+#define WM8962_PLL_4 0x83
+#define WM8962_PLL_9 0x88
+#define WM8962_PLL_10 0x89
+#define WM8962_PLL_11 0x8A
+#define WM8962_PLL_12 0x8B
+#define WM8962_PLL_13 0x8C
+#define WM8962_PLL_14 0x8D
+#define WM8962_PLL_15 0x8E
+#define WM8962_PLL_16 0x8F
+#define WM8962_FLL_CONTROL_1 0x9B
+#define WM8962_FLL_CONTROL_2 0x9C
+#define WM8962_FLL_CONTROL_3 0x9D
+#define WM8962_FLL_CONTROL_5 0x9F
+#define WM8962_FLL_CONTROL_6 0xA0
+#define WM8962_FLL_CONTROL_7 0xA1
+#define WM8962_FLL_CONTROL_8 0xA2
+#define WM8962_GENERAL_TEST_1 0xFC
+#define WM8962_DF1 0x100
+#define WM8962_DF2 0x101
+#define WM8962_DF3 0x102
+#define WM8962_DF4 0x103
+#define WM8962_DF5 0x104
+#define WM8962_DF6 0x105
+#define WM8962_DF7 0x106
+#define WM8962_LHPF1 0x108
+#define WM8962_LHPF2 0x109
+#define WM8962_THREED1 0x10C
+#define WM8962_THREED2 0x10D
+#define WM8962_THREED3 0x10E
+#define WM8962_THREED4 0x10F
+#define WM8962_DRC_1 0x114
+#define WM8962_DRC_2 0x115
+#define WM8962_DRC_3 0x116
+#define WM8962_DRC_4 0x117
+#define WM8962_DRC_5 0x118
+#define WM8962_TLOOPBACK 0x11D
+#define WM8962_EQ1 0x14F
+#define WM8962_EQ2 0x150
+#define WM8962_EQ3 0x151
+#define WM8962_EQ4 0x152
+#define WM8962_EQ5 0x153
+#define WM8962_EQ6 0x154
+#define WM8962_EQ7 0x155
+#define WM8962_EQ8 0x156
+#define WM8962_EQ9 0x157
+#define WM8962_EQ10 0x158
+#define WM8962_EQ11 0x159
+#define WM8962_EQ12 0x15A
+#define WM8962_EQ13 0x15B
+#define WM8962_EQ14 0x15C
+#define WM8962_EQ15 0x15D
+#define WM8962_EQ16 0x15E
+#define WM8962_EQ17 0x15F
+#define WM8962_EQ18 0x160
+#define WM8962_EQ19 0x161
+#define WM8962_EQ20 0x162
+#define WM8962_EQ21 0x163
+#define WM8962_EQ22 0x164
+#define WM8962_EQ23 0x165
+#define WM8962_EQ24 0x166
+#define WM8962_EQ25 0x167
+#define WM8962_EQ26 0x168
+#define WM8962_EQ27 0x169
+#define WM8962_EQ28 0x16A
+#define WM8962_EQ29 0x16B
+#define WM8962_EQ30 0x16C
+#define WM8962_EQ31 0x16D
+#define WM8962_EQ32 0x16E
+#define WM8962_EQ33 0x16F
+#define WM8962_EQ34 0x170
+#define WM8962_EQ35 0x171
+#define WM8962_EQ36 0x172
+#define WM8962_EQ37 0x173
+#define WM8962_EQ38 0x174
+#define WM8962_EQ39 0x175
+#define WM8962_EQ40 0x176
+#define WM8962_EQ41 0x177
+#define WM8962_GPIO_BASE 0x200
+#define WM8962_GPIO_2 0x201
+#define WM8962_GPIO_3 0x202
+#define WM8962_GPIO_5 0x204
+#define WM8962_GPIO_6 0x205
+#define WM8962_INTERRUPT_STATUS_1 0x230
+#define WM8962_INTERRUPT_STATUS_2 0x231
+#define WM8962_INTERRUPT_STATUS_1_MASK 0x238
+#define WM8962_INTERRUPT_STATUS_2_MASK 0x239
+#define WM8962_INTERRUPT_CONTROL 0x240
+#define WM8962_IRQ_DEBOUNCE 0x248
+#define WM8962_MICINT_SOURCE_POL 0x24A
+#define WM8962_DSP2_POWER_MANAGEMENT 0x300
+#define WM8962_DSP2_EXECCONTROL 0x40D
+#define WM8962_WRITE_SEQUENCER_0 0x1000
+#define WM8962_WRITE_SEQUENCER_1 0x1001
+#define WM8962_WRITE_SEQUENCER_2 0x1002
+#define WM8962_WRITE_SEQUENCER_3 0x1003
+#define WM8962_WRITE_SEQUENCER_4 0x1004
+#define WM8962_WRITE_SEQUENCER_5 0x1005
+#define WM8962_WRITE_SEQUENCER_6 0x1006
+#define WM8962_WRITE_SEQUENCER_7 0x1007
+#define WM8962_WRITE_SEQUENCER_8 0x1008
+#define WM8962_WRITE_SEQUENCER_9 0x1009
+#define WM8962_WRITE_SEQUENCER_10 0x100A
+#define WM8962_WRITE_SEQUENCER_11 0x100B
+#define WM8962_WRITE_SEQUENCER_12 0x100C
+#define WM8962_WRITE_SEQUENCER_13 0x100D
+#define WM8962_WRITE_SEQUENCER_14 0x100E
+#define WM8962_WRITE_SEQUENCER_15 0x100F
+#define WM8962_WRITE_SEQUENCER_16 0x1010
+#define WM8962_WRITE_SEQUENCER_17 0x1011
+#define WM8962_WRITE_SEQUENCER_18 0x1012
+#define WM8962_WRITE_SEQUENCER_19 0x1013
+#define WM8962_WRITE_SEQUENCER_20 0x1014
+#define WM8962_WRITE_SEQUENCER_21 0x1015
+#define WM8962_WRITE_SEQUENCER_22 0x1016
+#define WM8962_WRITE_SEQUENCER_23 0x1017
+#define WM8962_WRITE_SEQUENCER_24 0x1018
+#define WM8962_WRITE_SEQUENCER_25 0x1019
+#define WM8962_WRITE_SEQUENCER_26 0x101A
+#define WM8962_WRITE_SEQUENCER_27 0x101B
+#define WM8962_WRITE_SEQUENCER_28 0x101C
+#define WM8962_WRITE_SEQUENCER_29 0x101D
+#define WM8962_WRITE_SEQUENCER_30 0x101E
+#define WM8962_WRITE_SEQUENCER_31 0x101F
+#define WM8962_WRITE_SEQUENCER_32 0x1020
+#define WM8962_WRITE_SEQUENCER_33 0x1021
+#define WM8962_WRITE_SEQUENCER_34 0x1022
+#define WM8962_WRITE_SEQUENCER_35 0x1023
+#define WM8962_WRITE_SEQUENCER_36 0x1024
+#define WM8962_WRITE_SEQUENCER_37 0x1025
+#define WM8962_WRITE_SEQUENCER_38 0x1026
+#define WM8962_WRITE_SEQUENCER_39 0x1027
+#define WM8962_WRITE_SEQUENCER_40 0x1028
+#define WM8962_WRITE_SEQUENCER_41 0x1029
+#define WM8962_WRITE_SEQUENCER_42 0x102A
+#define WM8962_WRITE_SEQUENCER_43 0x102B
+#define WM8962_WRITE_SEQUENCER_44 0x102C
+#define WM8962_WRITE_SEQUENCER_45 0x102D
+#define WM8962_WRITE_SEQUENCER_46 0x102E
+#define WM8962_WRITE_SEQUENCER_47 0x102F
+#define WM8962_WRITE_SEQUENCER_48 0x1030
+#define WM8962_WRITE_SEQUENCER_49 0x1031
+#define WM8962_WRITE_SEQUENCER_50 0x1032
+#define WM8962_WRITE_SEQUENCER_51 0x1033
+#define WM8962_WRITE_SEQUENCER_52 0x1034
+#define WM8962_WRITE_SEQUENCER_53 0x1035
+#define WM8962_WRITE_SEQUENCER_54 0x1036
+#define WM8962_WRITE_SEQUENCER_55 0x1037
+#define WM8962_WRITE_SEQUENCER_56 0x1038
+#define WM8962_WRITE_SEQUENCER_57 0x1039
+#define WM8962_WRITE_SEQUENCER_58 0x103A
+#define WM8962_WRITE_SEQUENCER_59 0x103B
+#define WM8962_WRITE_SEQUENCER_60 0x103C
+#define WM8962_WRITE_SEQUENCER_61 0x103D
+#define WM8962_WRITE_SEQUENCER_62 0x103E
+#define WM8962_WRITE_SEQUENCER_63 0x103F
+#define WM8962_WRITE_SEQUENCER_64 0x1040
+#define WM8962_WRITE_SEQUENCER_65 0x1041
+#define WM8962_WRITE_SEQUENCER_66 0x1042
+#define WM8962_WRITE_SEQUENCER_67 0x1043
+#define WM8962_WRITE_SEQUENCER_68 0x1044
+#define WM8962_WRITE_SEQUENCER_69 0x1045
+#define WM8962_WRITE_SEQUENCER_70 0x1046
+#define WM8962_WRITE_SEQUENCER_71 0x1047
+#define WM8962_WRITE_SEQUENCER_72 0x1048
+#define WM8962_WRITE_SEQUENCER_73 0x1049
+#define WM8962_WRITE_SEQUENCER_74 0x104A
+#define WM8962_WRITE_SEQUENCER_75 0x104B
+#define WM8962_WRITE_SEQUENCER_76 0x104C
+#define WM8962_WRITE_SEQUENCER_77 0x104D
+#define WM8962_WRITE_SEQUENCER_78 0x104E
+#define WM8962_WRITE_SEQUENCER_79 0x104F
+#define WM8962_WRITE_SEQUENCER_80 0x1050
+#define WM8962_WRITE_SEQUENCER_81 0x1051
+#define WM8962_WRITE_SEQUENCER_82 0x1052
+#define WM8962_WRITE_SEQUENCER_83 0x1053
+#define WM8962_WRITE_SEQUENCER_84 0x1054
+#define WM8962_WRITE_SEQUENCER_85 0x1055
+#define WM8962_WRITE_SEQUENCER_86 0x1056
+#define WM8962_WRITE_SEQUENCER_87 0x1057
+#define WM8962_WRITE_SEQUENCER_88 0x1058
+#define WM8962_WRITE_SEQUENCER_89 0x1059
+#define WM8962_WRITE_SEQUENCER_90 0x105A
+#define WM8962_WRITE_SEQUENCER_91 0x105B
+#define WM8962_WRITE_SEQUENCER_92 0x105C
+#define WM8962_WRITE_SEQUENCER_93 0x105D
+#define WM8962_WRITE_SEQUENCER_94 0x105E
+#define WM8962_WRITE_SEQUENCER_95 0x105F
+#define WM8962_WRITE_SEQUENCER_96 0x1060
+#define WM8962_WRITE_SEQUENCER_97 0x1061
+#define WM8962_WRITE_SEQUENCER_98 0x1062
+#define WM8962_WRITE_SEQUENCER_99 0x1063
+#define WM8962_WRITE_SEQUENCER_100 0x1064
+#define WM8962_WRITE_SEQUENCER_101 0x1065
+#define WM8962_WRITE_SEQUENCER_102 0x1066
+#define WM8962_WRITE_SEQUENCER_103 0x1067
+#define WM8962_WRITE_SEQUENCER_104 0x1068
+#define WM8962_WRITE_SEQUENCER_105 0x1069
+#define WM8962_WRITE_SEQUENCER_106 0x106A
+#define WM8962_WRITE_SEQUENCER_107 0x106B
+#define WM8962_WRITE_SEQUENCER_108 0x106C
+#define WM8962_WRITE_SEQUENCER_109 0x106D
+#define WM8962_WRITE_SEQUENCER_110 0x106E
+#define WM8962_WRITE_SEQUENCER_111 0x106F
+#define WM8962_WRITE_SEQUENCER_112 0x1070
+#define WM8962_WRITE_SEQUENCER_113 0x1071
+#define WM8962_WRITE_SEQUENCER_114 0x1072
+#define WM8962_WRITE_SEQUENCER_115 0x1073
+#define WM8962_WRITE_SEQUENCER_116 0x1074
+#define WM8962_WRITE_SEQUENCER_117 0x1075
+#define WM8962_WRITE_SEQUENCER_118 0x1076
+#define WM8962_WRITE_SEQUENCER_119 0x1077
+#define WM8962_WRITE_SEQUENCER_120 0x1078
+#define WM8962_WRITE_SEQUENCER_121 0x1079
+#define WM8962_WRITE_SEQUENCER_122 0x107A
+#define WM8962_WRITE_SEQUENCER_123 0x107B
+#define WM8962_WRITE_SEQUENCER_124 0x107C
+#define WM8962_WRITE_SEQUENCER_125 0x107D
+#define WM8962_WRITE_SEQUENCER_126 0x107E
+#define WM8962_WRITE_SEQUENCER_127 0x107F
+#define WM8962_WRITE_SEQUENCER_128 0x1080
+#define WM8962_WRITE_SEQUENCER_129 0x1081
+#define WM8962_WRITE_SEQUENCER_130 0x1082
+#define WM8962_WRITE_SEQUENCER_131 0x1083
+#define WM8962_WRITE_SEQUENCER_132 0x1084
+#define WM8962_WRITE_SEQUENCER_133 0x1085
+#define WM8962_WRITE_SEQUENCER_134 0x1086
+#define WM8962_WRITE_SEQUENCER_135 0x1087
+#define WM8962_WRITE_SEQUENCER_136 0x1088
+#define WM8962_WRITE_SEQUENCER_137 0x1089
+#define WM8962_WRITE_SEQUENCER_138 0x108A
+#define WM8962_WRITE_SEQUENCER_139 0x108B
+#define WM8962_WRITE_SEQUENCER_140 0x108C
+#define WM8962_WRITE_SEQUENCER_141 0x108D
+#define WM8962_WRITE_SEQUENCER_142 0x108E
+#define WM8962_WRITE_SEQUENCER_143 0x108F
+#define WM8962_WRITE_SEQUENCER_144 0x1090
+#define WM8962_WRITE_SEQUENCER_145 0x1091
+#define WM8962_WRITE_SEQUENCER_146 0x1092
+#define WM8962_WRITE_SEQUENCER_147 0x1093
+#define WM8962_WRITE_SEQUENCER_148 0x1094
+#define WM8962_WRITE_SEQUENCER_149 0x1095
+#define WM8962_WRITE_SEQUENCER_150 0x1096
+#define WM8962_WRITE_SEQUENCER_151 0x1097
+#define WM8962_WRITE_SEQUENCER_152 0x1098
+#define WM8962_WRITE_SEQUENCER_153 0x1099
+#define WM8962_WRITE_SEQUENCER_154 0x109A
+#define WM8962_WRITE_SEQUENCER_155 0x109B
+#define WM8962_WRITE_SEQUENCER_156 0x109C
+#define WM8962_WRITE_SEQUENCER_157 0x109D
+#define WM8962_WRITE_SEQUENCER_158 0x109E
+#define WM8962_WRITE_SEQUENCER_159 0x109F
+#define WM8962_WRITE_SEQUENCER_160 0x10A0
+#define WM8962_WRITE_SEQUENCER_161 0x10A1
+#define WM8962_WRITE_SEQUENCER_162 0x10A2
+#define WM8962_WRITE_SEQUENCER_163 0x10A3
+#define WM8962_WRITE_SEQUENCER_164 0x10A4
+#define WM8962_WRITE_SEQUENCER_165 0x10A5
+#define WM8962_WRITE_SEQUENCER_166 0x10A6
+#define WM8962_WRITE_SEQUENCER_167 0x10A7
+#define WM8962_WRITE_SEQUENCER_168 0x10A8
+#define WM8962_WRITE_SEQUENCER_169 0x10A9
+#define WM8962_WRITE_SEQUENCER_170 0x10AA
+#define WM8962_WRITE_SEQUENCER_171 0x10AB
+#define WM8962_WRITE_SEQUENCER_172 0x10AC
+#define WM8962_WRITE_SEQUENCER_173 0x10AD
+#define WM8962_WRITE_SEQUENCER_174 0x10AE
+#define WM8962_WRITE_SEQUENCER_175 0x10AF
+#define WM8962_WRITE_SEQUENCER_176 0x10B0
+#define WM8962_WRITE_SEQUENCER_177 0x10B1
+#define WM8962_WRITE_SEQUENCER_178 0x10B2
+#define WM8962_WRITE_SEQUENCER_179 0x10B3
+#define WM8962_WRITE_SEQUENCER_180 0x10B4
+#define WM8962_WRITE_SEQUENCER_181 0x10B5
+#define WM8962_WRITE_SEQUENCER_182 0x10B6
+#define WM8962_WRITE_SEQUENCER_183 0x10B7
+#define WM8962_WRITE_SEQUENCER_184 0x10B8
+#define WM8962_WRITE_SEQUENCER_185 0x10B9
+#define WM8962_WRITE_SEQUENCER_186 0x10BA
+#define WM8962_WRITE_SEQUENCER_187 0x10BB
+#define WM8962_WRITE_SEQUENCER_188 0x10BC
+#define WM8962_WRITE_SEQUENCER_189 0x10BD
+#define WM8962_WRITE_SEQUENCER_190 0x10BE
+#define WM8962_WRITE_SEQUENCER_191 0x10BF
+#define WM8962_WRITE_SEQUENCER_192 0x10C0
+#define WM8962_WRITE_SEQUENCER_193 0x10C1
+#define WM8962_WRITE_SEQUENCER_194 0x10C2
+#define WM8962_WRITE_SEQUENCER_195 0x10C3
+#define WM8962_WRITE_SEQUENCER_196 0x10C4
+#define WM8962_WRITE_SEQUENCER_197 0x10C5
+#define WM8962_WRITE_SEQUENCER_198 0x10C6
+#define WM8962_WRITE_SEQUENCER_199 0x10C7
+#define WM8962_WRITE_SEQUENCER_200 0x10C8
+#define WM8962_WRITE_SEQUENCER_201 0x10C9
+#define WM8962_WRITE_SEQUENCER_202 0x10CA
+#define WM8962_WRITE_SEQUENCER_203 0x10CB
+#define WM8962_WRITE_SEQUENCER_204 0x10CC
+#define WM8962_WRITE_SEQUENCER_205 0x10CD
+#define WM8962_WRITE_SEQUENCER_206 0x10CE
+#define WM8962_WRITE_SEQUENCER_207 0x10CF
+#define WM8962_WRITE_SEQUENCER_208 0x10D0
+#define WM8962_WRITE_SEQUENCER_209 0x10D1
+#define WM8962_WRITE_SEQUENCER_210 0x10D2
+#define WM8962_WRITE_SEQUENCER_211 0x10D3
+#define WM8962_WRITE_SEQUENCER_212 0x10D4
+#define WM8962_WRITE_SEQUENCER_213 0x10D5
+#define WM8962_WRITE_SEQUENCER_214 0x10D6
+#define WM8962_WRITE_SEQUENCER_215 0x10D7
+#define WM8962_WRITE_SEQUENCER_216 0x10D8
+#define WM8962_WRITE_SEQUENCER_217 0x10D9
+#define WM8962_WRITE_SEQUENCER_218 0x10DA
+#define WM8962_WRITE_SEQUENCER_219 0x10DB
+#define WM8962_WRITE_SEQUENCER_220 0x10DC
+#define WM8962_WRITE_SEQUENCER_221 0x10DD
+#define WM8962_WRITE_SEQUENCER_222 0x10DE
+#define WM8962_WRITE_SEQUENCER_223 0x10DF
+#define WM8962_WRITE_SEQUENCER_224 0x10E0
+#define WM8962_WRITE_SEQUENCER_225 0x10E1
+#define WM8962_WRITE_SEQUENCER_226 0x10E2
+#define WM8962_WRITE_SEQUENCER_227 0x10E3
+#define WM8962_WRITE_SEQUENCER_228 0x10E4
+#define WM8962_WRITE_SEQUENCER_229 0x10E5
+#define WM8962_WRITE_SEQUENCER_230 0x10E6
+#define WM8962_WRITE_SEQUENCER_231 0x10E7
+#define WM8962_WRITE_SEQUENCER_232 0x10E8
+#define WM8962_WRITE_SEQUENCER_233 0x10E9
+#define WM8962_WRITE_SEQUENCER_234 0x10EA
+#define WM8962_WRITE_SEQUENCER_235 0x10EB
+#define WM8962_WRITE_SEQUENCER_236 0x10EC
+#define WM8962_WRITE_SEQUENCER_237 0x10ED
+#define WM8962_WRITE_SEQUENCER_238 0x10EE
+#define WM8962_WRITE_SEQUENCER_239 0x10EF
+#define WM8962_WRITE_SEQUENCER_240 0x10F0
+#define WM8962_WRITE_SEQUENCER_241 0x10F1
+#define WM8962_WRITE_SEQUENCER_242 0x10F2
+#define WM8962_WRITE_SEQUENCER_243 0x10F3
+#define WM8962_WRITE_SEQUENCER_244 0x10F4
+#define WM8962_WRITE_SEQUENCER_245 0x10F5
+#define WM8962_WRITE_SEQUENCER_246 0x10F6
+#define WM8962_WRITE_SEQUENCER_247 0x10F7
+#define WM8962_WRITE_SEQUENCER_248 0x10F8
+#define WM8962_WRITE_SEQUENCER_249 0x10F9
+#define WM8962_WRITE_SEQUENCER_250 0x10FA
+#define WM8962_WRITE_SEQUENCER_251 0x10FB
+#define WM8962_WRITE_SEQUENCER_252 0x10FC
+#define WM8962_WRITE_SEQUENCER_253 0x10FD
+#define WM8962_WRITE_SEQUENCER_254 0x10FE
+#define WM8962_WRITE_SEQUENCER_255 0x10FF
+#define WM8962_WRITE_SEQUENCER_256 0x1100
+#define WM8962_WRITE_SEQUENCER_257 0x1101
+#define WM8962_WRITE_SEQUENCER_258 0x1102
+#define WM8962_WRITE_SEQUENCER_259 0x1103
+#define WM8962_WRITE_SEQUENCER_260 0x1104
+#define WM8962_WRITE_SEQUENCER_261 0x1105
+#define WM8962_WRITE_SEQUENCER_262 0x1106
+#define WM8962_WRITE_SEQUENCER_263 0x1107
+#define WM8962_WRITE_SEQUENCER_264 0x1108
+#define WM8962_WRITE_SEQUENCER_265 0x1109
+#define WM8962_WRITE_SEQUENCER_266 0x110A
+#define WM8962_WRITE_SEQUENCER_267 0x110B
+#define WM8962_WRITE_SEQUENCER_268 0x110C
+#define WM8962_WRITE_SEQUENCER_269 0x110D
+#define WM8962_WRITE_SEQUENCER_270 0x110E
+#define WM8962_WRITE_SEQUENCER_271 0x110F
+#define WM8962_WRITE_SEQUENCER_272 0x1110
+#define WM8962_WRITE_SEQUENCER_273 0x1111
+#define WM8962_WRITE_SEQUENCER_274 0x1112
+#define WM8962_WRITE_SEQUENCER_275 0x1113
+#define WM8962_WRITE_SEQUENCER_276 0x1114
+#define WM8962_WRITE_SEQUENCER_277 0x1115
+#define WM8962_WRITE_SEQUENCER_278 0x1116
+#define WM8962_WRITE_SEQUENCER_279 0x1117
+#define WM8962_WRITE_SEQUENCER_280 0x1118
+#define WM8962_WRITE_SEQUENCER_281 0x1119
+#define WM8962_WRITE_SEQUENCER_282 0x111A
+#define WM8962_WRITE_SEQUENCER_283 0x111B
+#define WM8962_WRITE_SEQUENCER_284 0x111C
+#define WM8962_WRITE_SEQUENCER_285 0x111D
+#define WM8962_WRITE_SEQUENCER_286 0x111E
+#define WM8962_WRITE_SEQUENCER_287 0x111F
+#define WM8962_WRITE_SEQUENCER_288 0x1120
+#define WM8962_WRITE_SEQUENCER_289 0x1121
+#define WM8962_WRITE_SEQUENCER_290 0x1122
+#define WM8962_WRITE_SEQUENCER_291 0x1123
+#define WM8962_WRITE_SEQUENCER_292 0x1124
+#define WM8962_WRITE_SEQUENCER_293 0x1125
+#define WM8962_WRITE_SEQUENCER_294 0x1126
+#define WM8962_WRITE_SEQUENCER_295 0x1127
+#define WM8962_WRITE_SEQUENCER_296 0x1128
+#define WM8962_WRITE_SEQUENCER_297 0x1129
+#define WM8962_WRITE_SEQUENCER_298 0x112A
+#define WM8962_WRITE_SEQUENCER_299 0x112B
+#define WM8962_WRITE_SEQUENCER_300 0x112C
+#define WM8962_WRITE_SEQUENCER_301 0x112D
+#define WM8962_WRITE_SEQUENCER_302 0x112E
+#define WM8962_WRITE_SEQUENCER_303 0x112F
+#define WM8962_WRITE_SEQUENCER_304 0x1130
+#define WM8962_WRITE_SEQUENCER_305 0x1131
+#define WM8962_WRITE_SEQUENCER_306 0x1132
+#define WM8962_WRITE_SEQUENCER_307 0x1133
+#define WM8962_WRITE_SEQUENCER_308 0x1134
+#define WM8962_WRITE_SEQUENCER_309 0x1135
+#define WM8962_WRITE_SEQUENCER_310 0x1136
+#define WM8962_WRITE_SEQUENCER_311 0x1137
+#define WM8962_WRITE_SEQUENCER_312 0x1138
+#define WM8962_WRITE_SEQUENCER_313 0x1139
+#define WM8962_WRITE_SEQUENCER_314 0x113A
+#define WM8962_WRITE_SEQUENCER_315 0x113B
+#define WM8962_WRITE_SEQUENCER_316 0x113C
+#define WM8962_WRITE_SEQUENCER_317 0x113D
+#define WM8962_WRITE_SEQUENCER_318 0x113E
+#define WM8962_WRITE_SEQUENCER_319 0x113F
+#define WM8962_WRITE_SEQUENCER_320 0x1140
+#define WM8962_WRITE_SEQUENCER_321 0x1141
+#define WM8962_WRITE_SEQUENCER_322 0x1142
+#define WM8962_WRITE_SEQUENCER_323 0x1143
+#define WM8962_WRITE_SEQUENCER_324 0x1144
+#define WM8962_WRITE_SEQUENCER_325 0x1145
+#define WM8962_WRITE_SEQUENCER_326 0x1146
+#define WM8962_WRITE_SEQUENCER_327 0x1147
+#define WM8962_WRITE_SEQUENCER_328 0x1148
+#define WM8962_WRITE_SEQUENCER_329 0x1149
+#define WM8962_WRITE_SEQUENCER_330 0x114A
+#define WM8962_WRITE_SEQUENCER_331 0x114B
+#define WM8962_WRITE_SEQUENCER_332 0x114C
+#define WM8962_WRITE_SEQUENCER_333 0x114D
+#define WM8962_WRITE_SEQUENCER_334 0x114E
+#define WM8962_WRITE_SEQUENCER_335 0x114F
+#define WM8962_WRITE_SEQUENCER_336 0x1150
+#define WM8962_WRITE_SEQUENCER_337 0x1151
+#define WM8962_WRITE_SEQUENCER_338 0x1152
+#define WM8962_WRITE_SEQUENCER_339 0x1153
+#define WM8962_WRITE_SEQUENCER_340 0x1154
+#define WM8962_WRITE_SEQUENCER_341 0x1155
+#define WM8962_WRITE_SEQUENCER_342 0x1156
+#define WM8962_WRITE_SEQUENCER_343 0x1157
+#define WM8962_WRITE_SEQUENCER_344 0x1158
+#define WM8962_WRITE_SEQUENCER_345 0x1159
+#define WM8962_WRITE_SEQUENCER_346 0x115A
+#define WM8962_WRITE_SEQUENCER_347 0x115B
+#define WM8962_WRITE_SEQUENCER_348 0x115C
+#define WM8962_WRITE_SEQUENCER_349 0x115D
+#define WM8962_WRITE_SEQUENCER_350 0x115E
+#define WM8962_WRITE_SEQUENCER_351 0x115F
+#define WM8962_WRITE_SEQUENCER_352 0x1160
+#define WM8962_WRITE_SEQUENCER_353 0x1161
+#define WM8962_WRITE_SEQUENCER_354 0x1162
+#define WM8962_WRITE_SEQUENCER_355 0x1163
+#define WM8962_WRITE_SEQUENCER_356 0x1164
+#define WM8962_WRITE_SEQUENCER_357 0x1165
+#define WM8962_WRITE_SEQUENCER_358 0x1166
+#define WM8962_WRITE_SEQUENCER_359 0x1167
+#define WM8962_WRITE_SEQUENCER_360 0x1168
+#define WM8962_WRITE_SEQUENCER_361 0x1169
+#define WM8962_WRITE_SEQUENCER_362 0x116A
+#define WM8962_WRITE_SEQUENCER_363 0x116B
+#define WM8962_WRITE_SEQUENCER_364 0x116C
+#define WM8962_WRITE_SEQUENCER_365 0x116D
+#define WM8962_WRITE_SEQUENCER_366 0x116E
+#define WM8962_WRITE_SEQUENCER_367 0x116F
+#define WM8962_WRITE_SEQUENCER_368 0x1170
+#define WM8962_WRITE_SEQUENCER_369 0x1171
+#define WM8962_WRITE_SEQUENCER_370 0x1172
+#define WM8962_WRITE_SEQUENCER_371 0x1173
+#define WM8962_WRITE_SEQUENCER_372 0x1174
+#define WM8962_WRITE_SEQUENCER_373 0x1175
+#define WM8962_WRITE_SEQUENCER_374 0x1176
+#define WM8962_WRITE_SEQUENCER_375 0x1177
+#define WM8962_WRITE_SEQUENCER_376 0x1178
+#define WM8962_WRITE_SEQUENCER_377 0x1179
+#define WM8962_WRITE_SEQUENCER_378 0x117A
+#define WM8962_WRITE_SEQUENCER_379 0x117B
+#define WM8962_WRITE_SEQUENCER_380 0x117C
+#define WM8962_WRITE_SEQUENCER_381 0x117D
+#define WM8962_WRITE_SEQUENCER_382 0x117E
+#define WM8962_WRITE_SEQUENCER_383 0x117F
+#define WM8962_WRITE_SEQUENCER_384 0x1180
+#define WM8962_WRITE_SEQUENCER_385 0x1181
+#define WM8962_WRITE_SEQUENCER_386 0x1182
+#define WM8962_WRITE_SEQUENCER_387 0x1183
+#define WM8962_WRITE_SEQUENCER_388 0x1184
+#define WM8962_WRITE_SEQUENCER_389 0x1185
+#define WM8962_WRITE_SEQUENCER_390 0x1186
+#define WM8962_WRITE_SEQUENCER_391 0x1187
+#define WM8962_WRITE_SEQUENCER_392 0x1188
+#define WM8962_WRITE_SEQUENCER_393 0x1189
+#define WM8962_WRITE_SEQUENCER_394 0x118A
+#define WM8962_WRITE_SEQUENCER_395 0x118B
+#define WM8962_WRITE_SEQUENCER_396 0x118C
+#define WM8962_WRITE_SEQUENCER_397 0x118D
+#define WM8962_WRITE_SEQUENCER_398 0x118E
+#define WM8962_WRITE_SEQUENCER_399 0x118F
+#define WM8962_WRITE_SEQUENCER_400 0x1190
+#define WM8962_WRITE_SEQUENCER_401 0x1191
+#define WM8962_WRITE_SEQUENCER_402 0x1192
+#define WM8962_WRITE_SEQUENCER_403 0x1193
+#define WM8962_WRITE_SEQUENCER_404 0x1194
+#define WM8962_WRITE_SEQUENCER_405 0x1195
+#define WM8962_WRITE_SEQUENCER_406 0x1196
+#define WM8962_WRITE_SEQUENCER_407 0x1197
+#define WM8962_WRITE_SEQUENCER_408 0x1198
+#define WM8962_WRITE_SEQUENCER_409 0x1199
+#define WM8962_WRITE_SEQUENCER_410 0x119A
+#define WM8962_WRITE_SEQUENCER_411 0x119B
+#define WM8962_WRITE_SEQUENCER_412 0x119C
+#define WM8962_WRITE_SEQUENCER_413 0x119D
+#define WM8962_WRITE_SEQUENCER_414 0x119E
+#define WM8962_WRITE_SEQUENCER_415 0x119F
+#define WM8962_WRITE_SEQUENCER_416 0x11A0
+#define WM8962_WRITE_SEQUENCER_417 0x11A1
+#define WM8962_WRITE_SEQUENCER_418 0x11A2
+#define WM8962_WRITE_SEQUENCER_419 0x11A3
+#define WM8962_WRITE_SEQUENCER_420 0x11A4
+#define WM8962_WRITE_SEQUENCER_421 0x11A5
+#define WM8962_WRITE_SEQUENCER_422 0x11A6
+#define WM8962_WRITE_SEQUENCER_423 0x11A7
+#define WM8962_WRITE_SEQUENCER_424 0x11A8
+#define WM8962_WRITE_SEQUENCER_425 0x11A9
+#define WM8962_WRITE_SEQUENCER_426 0x11AA
+#define WM8962_WRITE_SEQUENCER_427 0x11AB
+#define WM8962_WRITE_SEQUENCER_428 0x11AC
+#define WM8962_WRITE_SEQUENCER_429 0x11AD
+#define WM8962_WRITE_SEQUENCER_430 0x11AE
+#define WM8962_WRITE_SEQUENCER_431 0x11AF
+#define WM8962_WRITE_SEQUENCER_432 0x11B0
+#define WM8962_WRITE_SEQUENCER_433 0x11B1
+#define WM8962_WRITE_SEQUENCER_434 0x11B2
+#define WM8962_WRITE_SEQUENCER_435 0x11B3
+#define WM8962_WRITE_SEQUENCER_436 0x11B4
+#define WM8962_WRITE_SEQUENCER_437 0x11B5
+#define WM8962_WRITE_SEQUENCER_438 0x11B6
+#define WM8962_WRITE_SEQUENCER_439 0x11B7
+#define WM8962_WRITE_SEQUENCER_440 0x11B8
+#define WM8962_WRITE_SEQUENCER_441 0x11B9
+#define WM8962_WRITE_SEQUENCER_442 0x11BA
+#define WM8962_WRITE_SEQUENCER_443 0x11BB
+#define WM8962_WRITE_SEQUENCER_444 0x11BC
+#define WM8962_WRITE_SEQUENCER_445 0x11BD
+#define WM8962_WRITE_SEQUENCER_446 0x11BE
+#define WM8962_WRITE_SEQUENCER_447 0x11BF
+#define WM8962_WRITE_SEQUENCER_448 0x11C0
+#define WM8962_WRITE_SEQUENCER_449 0x11C1
+#define WM8962_WRITE_SEQUENCER_450 0x11C2
+#define WM8962_WRITE_SEQUENCER_451 0x11C3
+#define WM8962_WRITE_SEQUENCER_452 0x11C4
+#define WM8962_WRITE_SEQUENCER_453 0x11C5
+#define WM8962_WRITE_SEQUENCER_454 0x11C6
+#define WM8962_WRITE_SEQUENCER_455 0x11C7
+#define WM8962_WRITE_SEQUENCER_456 0x11C8
+#define WM8962_WRITE_SEQUENCER_457 0x11C9
+#define WM8962_WRITE_SEQUENCER_458 0x11CA
+#define WM8962_WRITE_SEQUENCER_459 0x11CB
+#define WM8962_WRITE_SEQUENCER_460 0x11CC
+#define WM8962_WRITE_SEQUENCER_461 0x11CD
+#define WM8962_WRITE_SEQUENCER_462 0x11CE
+#define WM8962_WRITE_SEQUENCER_463 0x11CF
+#define WM8962_WRITE_SEQUENCER_464 0x11D0
+#define WM8962_WRITE_SEQUENCER_465 0x11D1
+#define WM8962_WRITE_SEQUENCER_466 0x11D2
+#define WM8962_WRITE_SEQUENCER_467 0x11D3
+#define WM8962_WRITE_SEQUENCER_468 0x11D4
+#define WM8962_WRITE_SEQUENCER_469 0x11D5
+#define WM8962_WRITE_SEQUENCER_470 0x11D6
+#define WM8962_WRITE_SEQUENCER_471 0x11D7
+#define WM8962_WRITE_SEQUENCER_472 0x11D8
+#define WM8962_WRITE_SEQUENCER_473 0x11D9
+#define WM8962_WRITE_SEQUENCER_474 0x11DA
+#define WM8962_WRITE_SEQUENCER_475 0x11DB
+#define WM8962_WRITE_SEQUENCER_476 0x11DC
+#define WM8962_WRITE_SEQUENCER_477 0x11DD
+#define WM8962_WRITE_SEQUENCER_478 0x11DE
+#define WM8962_WRITE_SEQUENCER_479 0x11DF
+#define WM8962_WRITE_SEQUENCER_480 0x11E0
+#define WM8962_WRITE_SEQUENCER_481 0x11E1
+#define WM8962_WRITE_SEQUENCER_482 0x11E2
+#define WM8962_WRITE_SEQUENCER_483 0x11E3
+#define WM8962_WRITE_SEQUENCER_484 0x11E4
+#define WM8962_WRITE_SEQUENCER_485 0x11E5
+#define WM8962_WRITE_SEQUENCER_486 0x11E6
+#define WM8962_WRITE_SEQUENCER_487 0x11E7
+#define WM8962_WRITE_SEQUENCER_488 0x11E8
+#define WM8962_WRITE_SEQUENCER_489 0x11E9
+#define WM8962_WRITE_SEQUENCER_490 0x11EA
+#define WM8962_WRITE_SEQUENCER_491 0x11EB
+#define WM8962_WRITE_SEQUENCER_492 0x11EC
+#define WM8962_WRITE_SEQUENCER_493 0x11ED
+#define WM8962_WRITE_SEQUENCER_494 0x11EE
+#define WM8962_WRITE_SEQUENCER_495 0x11EF
+#define WM8962_WRITE_SEQUENCER_496 0x11F0
+#define WM8962_WRITE_SEQUENCER_497 0x11F1
+#define WM8962_WRITE_SEQUENCER_498 0x11F2
+#define WM8962_WRITE_SEQUENCER_499 0x11F3
+#define WM8962_WRITE_SEQUENCER_500 0x11F4
+#define WM8962_WRITE_SEQUENCER_501 0x11F5
+#define WM8962_WRITE_SEQUENCER_502 0x11F6
+#define WM8962_WRITE_SEQUENCER_503 0x11F7
+#define WM8962_WRITE_SEQUENCER_504 0x11F8
+#define WM8962_WRITE_SEQUENCER_505 0x11F9
+#define WM8962_WRITE_SEQUENCER_506 0x11FA
+#define WM8962_WRITE_SEQUENCER_507 0x11FB
+#define WM8962_WRITE_SEQUENCER_508 0x11FC
+#define WM8962_WRITE_SEQUENCER_509 0x11FD
+#define WM8962_WRITE_SEQUENCER_510 0x11FE
+#define WM8962_WRITE_SEQUENCER_511 0x11FF
+#define WM8962_DSP2_INSTRUCTION_RAM_0 0x2000
+#define WM8962_DSP2_ADDRESS_RAM_2 0x2400
+#define WM8962_DSP2_ADDRESS_RAM_1 0x2401
+#define WM8962_DSP2_ADDRESS_RAM_0 0x2402
+#define WM8962_DSP2_DATA1_RAM_1 0x3000
+#define WM8962_DSP2_DATA1_RAM_0 0x3001
+#define WM8962_DSP2_DATA2_RAM_1 0x3400
+#define WM8962_DSP2_DATA2_RAM_0 0x3401
+#define WM8962_DSP2_DATA3_RAM_1 0x3800
+#define WM8962_DSP2_DATA3_RAM_0 0x3801
+#define WM8962_DSP2_COEFF_RAM_0 0x3C00
+#define WM8962_RETUNEADC_SHARED_COEFF_1 0x4000
+#define WM8962_RETUNEADC_SHARED_COEFF_0 0x4001
+#define WM8962_RETUNEDAC_SHARED_COEFF_1 0x4002
+#define WM8962_RETUNEDAC_SHARED_COEFF_0 0x4003
+#define WM8962_SOUNDSTAGE_ENABLES_1 0x4004
+#define WM8962_SOUNDSTAGE_ENABLES_0 0x4005
+#define WM8962_HDBASS_AI_1 0x4200
+#define WM8962_HDBASS_AI_0 0x4201
+#define WM8962_HDBASS_AR_1 0x4202
+#define WM8962_HDBASS_AR_0 0x4203
+#define WM8962_HDBASS_B_1 0x4204
+#define WM8962_HDBASS_B_0 0x4205
+#define WM8962_HDBASS_K_1 0x4206
+#define WM8962_HDBASS_K_0 0x4207
+#define WM8962_HDBASS_N1_1 0x4208
+#define WM8962_HDBASS_N1_0 0x4209
+#define WM8962_HDBASS_N2_1 0x420A
+#define WM8962_HDBASS_N2_0 0x420B
+#define WM8962_HDBASS_N3_1 0x420C
+#define WM8962_HDBASS_N3_0 0x420D
+#define WM8962_HDBASS_N4_1 0x420E
+#define WM8962_HDBASS_N4_0 0x420F
+#define WM8962_HDBASS_N5_1 0x4210
+#define WM8962_HDBASS_N5_0 0x4211
+#define WM8962_HDBASS_X1_1 0x4212
+#define WM8962_HDBASS_X1_0 0x4213
+#define WM8962_HDBASS_X2_1 0x4214
+#define WM8962_HDBASS_X2_0 0x4215
+#define WM8962_HDBASS_X3_1 0x4216
+#define WM8962_HDBASS_X3_0 0x4217
+#define WM8962_HDBASS_ATK_1 0x4218
+#define WM8962_HDBASS_ATK_0 0x4219
+#define WM8962_HDBASS_DCY_1 0x421A
+#define WM8962_HDBASS_DCY_0 0x421B
+#define WM8962_HDBASS_PG_1 0x421C
+#define WM8962_HDBASS_PG_0 0x421D
+#define WM8962_HPF_C_1 0x4400
+#define WM8962_HPF_C_0 0x4401
+#define WM8962_ADCL_RETUNE_C1_1 0x4600
+#define WM8962_ADCL_RETUNE_C1_0 0x4601
+#define WM8962_ADCL_RETUNE_C2_1 0x4602
+#define WM8962_ADCL_RETUNE_C2_0 0x4603
+#define WM8962_ADCL_RETUNE_C3_1 0x4604
+#define WM8962_ADCL_RETUNE_C3_0 0x4605
+#define WM8962_ADCL_RETUNE_C4_1 0x4606
+#define WM8962_ADCL_RETUNE_C4_0 0x4607
+#define WM8962_ADCL_RETUNE_C5_1 0x4608
+#define WM8962_ADCL_RETUNE_C5_0 0x4609
+#define WM8962_ADCL_RETUNE_C6_1 0x460A
+#define WM8962_ADCL_RETUNE_C6_0 0x460B
+#define WM8962_ADCL_RETUNE_C7_1 0x460C
+#define WM8962_ADCL_RETUNE_C7_0 0x460D
+#define WM8962_ADCL_RETUNE_C8_1 0x460E
+#define WM8962_ADCL_RETUNE_C8_0 0x460F
+#define WM8962_ADCL_RETUNE_C9_1 0x4610
+#define WM8962_ADCL_RETUNE_C9_0 0x4611
+#define WM8962_ADCL_RETUNE_C10_1 0x4612
+#define WM8962_ADCL_RETUNE_C10_0 0x4613
+#define WM8962_ADCL_RETUNE_C11_1 0x4614
+#define WM8962_ADCL_RETUNE_C11_0 0x4615
+#define WM8962_ADCL_RETUNE_C12_1 0x4616
+#define WM8962_ADCL_RETUNE_C12_0 0x4617
+#define WM8962_ADCL_RETUNE_C13_1 0x4618
+#define WM8962_ADCL_RETUNE_C13_0 0x4619
+#define WM8962_ADCL_RETUNE_C14_1 0x461A
+#define WM8962_ADCL_RETUNE_C14_0 0x461B
+#define WM8962_ADCL_RETUNE_C15_1 0x461C
+#define WM8962_ADCL_RETUNE_C15_0 0x461D
+#define WM8962_ADCL_RETUNE_C16_1 0x461E
+#define WM8962_ADCL_RETUNE_C16_0 0x461F
+#define WM8962_ADCL_RETUNE_C17_1 0x4620
+#define WM8962_ADCL_RETUNE_C17_0 0x4621
+#define WM8962_ADCL_RETUNE_C18_1 0x4622
+#define WM8962_ADCL_RETUNE_C18_0 0x4623
+#define WM8962_ADCL_RETUNE_C19_1 0x4624
+#define WM8962_ADCL_RETUNE_C19_0 0x4625
+#define WM8962_ADCL_RETUNE_C20_1 0x4626
+#define WM8962_ADCL_RETUNE_C20_0 0x4627
+#define WM8962_ADCL_RETUNE_C21_1 0x4628
+#define WM8962_ADCL_RETUNE_C21_0 0x4629
+#define WM8962_ADCL_RETUNE_C22_1 0x462A
+#define WM8962_ADCL_RETUNE_C22_0 0x462B
+#define WM8962_ADCL_RETUNE_C23_1 0x462C
+#define WM8962_ADCL_RETUNE_C23_0 0x462D
+#define WM8962_ADCL_RETUNE_C24_1 0x462E
+#define WM8962_ADCL_RETUNE_C24_0 0x462F
+#define WM8962_ADCL_RETUNE_C25_1 0x4630
+#define WM8962_ADCL_RETUNE_C25_0 0x4631
+#define WM8962_ADCL_RETUNE_C26_1 0x4632
+#define WM8962_ADCL_RETUNE_C26_0 0x4633
+#define WM8962_ADCL_RETUNE_C27_1 0x4634
+#define WM8962_ADCL_RETUNE_C27_0 0x4635
+#define WM8962_ADCL_RETUNE_C28_1 0x4636
+#define WM8962_ADCL_RETUNE_C28_0 0x4637
+#define WM8962_ADCL_RETUNE_C29_1 0x4638
+#define WM8962_ADCL_RETUNE_C29_0 0x4639
+#define WM8962_ADCL_RETUNE_C30_1 0x463A
+#define WM8962_ADCL_RETUNE_C30_0 0x463B
+#define WM8962_ADCL_RETUNE_C31_1 0x463C
+#define WM8962_ADCL_RETUNE_C31_0 0x463D
+#define WM8962_ADCL_RETUNE_C32_1 0x463E
+#define WM8962_ADCL_RETUNE_C32_0 0x463F
+#define WM8962_RETUNEADC_PG2_1 0x4800
+#define WM8962_RETUNEADC_PG2_0 0x4801
+#define WM8962_RETUNEADC_PG_1 0x4802
+#define WM8962_RETUNEADC_PG_0 0x4803
+#define WM8962_ADCR_RETUNE_C1_1 0x4A00
+#define WM8962_ADCR_RETUNE_C1_0 0x4A01
+#define WM8962_ADCR_RETUNE_C2_1 0x4A02
+#define WM8962_ADCR_RETUNE_C2_0 0x4A03
+#define WM8962_ADCR_RETUNE_C3_1 0x4A04
+#define WM8962_ADCR_RETUNE_C3_0 0x4A05
+#define WM8962_ADCR_RETUNE_C4_1 0x4A06
+#define WM8962_ADCR_RETUNE_C4_0 0x4A07
+#define WM8962_ADCR_RETUNE_C5_1 0x4A08
+#define WM8962_ADCR_RETUNE_C5_0 0x4A09
+#define WM8962_ADCR_RETUNE_C6_1 0x4A0A
+#define WM8962_ADCR_RETUNE_C6_0 0x4A0B
+#define WM8962_ADCR_RETUNE_C7_1 0x4A0C
+#define WM8962_ADCR_RETUNE_C7_0 0x4A0D
+#define WM8962_ADCR_RETUNE_C8_1 0x4A0E
+#define WM8962_ADCR_RETUNE_C8_0 0x4A0F
+#define WM8962_ADCR_RETUNE_C9_1 0x4A10
+#define WM8962_ADCR_RETUNE_C9_0 0x4A11
+#define WM8962_ADCR_RETUNE_C10_1 0x4A12
+#define WM8962_ADCR_RETUNE_C10_0 0x4A13
+#define WM8962_ADCR_RETUNE_C11_1 0x4A14
+#define WM8962_ADCR_RETUNE_C11_0 0x4A15
+#define WM8962_ADCR_RETUNE_C12_1 0x4A16
+#define WM8962_ADCR_RETUNE_C12_0 0x4A17
+#define WM8962_ADCR_RETUNE_C13_1 0x4A18
+#define WM8962_ADCR_RETUNE_C13_0 0x4A19
+#define WM8962_ADCR_RETUNE_C14_1 0x4A1A
+#define WM8962_ADCR_RETUNE_C14_0 0x4A1B
+#define WM8962_ADCR_RETUNE_C15_1 0x4A1C
+#define WM8962_ADCR_RETUNE_C15_0 0x4A1D
+#define WM8962_ADCR_RETUNE_C16_1 0x4A1E
+#define WM8962_ADCR_RETUNE_C16_0 0x4A1F
+#define WM8962_ADCR_RETUNE_C17_1 0x4A20
+#define WM8962_ADCR_RETUNE_C17_0 0x4A21
+#define WM8962_ADCR_RETUNE_C18_1 0x4A22
+#define WM8962_ADCR_RETUNE_C18_0 0x4A23
+#define WM8962_ADCR_RETUNE_C19_1 0x4A24
+#define WM8962_ADCR_RETUNE_C19_0 0x4A25
+#define WM8962_ADCR_RETUNE_C20_1 0x4A26
+#define WM8962_ADCR_RETUNE_C20_0 0x4A27
+#define WM8962_ADCR_RETUNE_C21_1 0x4A28
+#define WM8962_ADCR_RETUNE_C21_0 0x4A29
+#define WM8962_ADCR_RETUNE_C22_1 0x4A2A
+#define WM8962_ADCR_RETUNE_C22_0 0x4A2B
+#define WM8962_ADCR_RETUNE_C23_1 0x4A2C
+#define WM8962_ADCR_RETUNE_C23_0 0x4A2D
+#define WM8962_ADCR_RETUNE_C24_1 0x4A2E
+#define WM8962_ADCR_RETUNE_C24_0 0x4A2F
+#define WM8962_ADCR_RETUNE_C25_1 0x4A30
+#define WM8962_ADCR_RETUNE_C25_0 0x4A31
+#define WM8962_ADCR_RETUNE_C26_1 0x4A32
+#define WM8962_ADCR_RETUNE_C26_0 0x4A33
+#define WM8962_ADCR_RETUNE_C27_1 0x4A34
+#define WM8962_ADCR_RETUNE_C27_0 0x4A35
+#define WM8962_ADCR_RETUNE_C28_1 0x4A36
+#define WM8962_ADCR_RETUNE_C28_0 0x4A37
+#define WM8962_ADCR_RETUNE_C29_1 0x4A38
+#define WM8962_ADCR_RETUNE_C29_0 0x4A39
+#define WM8962_ADCR_RETUNE_C30_1 0x4A3A
+#define WM8962_ADCR_RETUNE_C30_0 0x4A3B
+#define WM8962_ADCR_RETUNE_C31_1 0x4A3C
+#define WM8962_ADCR_RETUNE_C31_0 0x4A3D
+#define WM8962_ADCR_RETUNE_C32_1 0x4A3E
+#define WM8962_ADCR_RETUNE_C32_0 0x4A3F
+#define WM8962_DACL_RETUNE_C1_1 0x4C00
+#define WM8962_DACL_RETUNE_C1_0 0x4C01
+#define WM8962_DACL_RETUNE_C2_1 0x4C02
+#define WM8962_DACL_RETUNE_C2_0 0x4C03
+#define WM8962_DACL_RETUNE_C3_1 0x4C04
+#define WM8962_DACL_RETUNE_C3_0 0x4C05
+#define WM8962_DACL_RETUNE_C4_1 0x4C06
+#define WM8962_DACL_RETUNE_C4_0 0x4C07
+#define WM8962_DACL_RETUNE_C5_1 0x4C08
+#define WM8962_DACL_RETUNE_C5_0 0x4C09
+#define WM8962_DACL_RETUNE_C6_1 0x4C0A
+#define WM8962_DACL_RETUNE_C6_0 0x4C0B
+#define WM8962_DACL_RETUNE_C7_1 0x4C0C
+#define WM8962_DACL_RETUNE_C7_0 0x4C0D
+#define WM8962_DACL_RETUNE_C8_1 0x4C0E
+#define WM8962_DACL_RETUNE_C8_0 0x4C0F
+#define WM8962_DACL_RETUNE_C9_1 0x4C10
+#define WM8962_DACL_RETUNE_C9_0 0x4C11
+#define WM8962_DACL_RETUNE_C10_1 0x4C12
+#define WM8962_DACL_RETUNE_C10_0 0x4C13
+#define WM8962_DACL_RETUNE_C11_1 0x4C14
+#define WM8962_DACL_RETUNE_C11_0 0x4C15
+#define WM8962_DACL_RETUNE_C12_1 0x4C16
+#define WM8962_DACL_RETUNE_C12_0 0x4C17
+#define WM8962_DACL_RETUNE_C13_1 0x4C18
+#define WM8962_DACL_RETUNE_C13_0 0x4C19
+#define WM8962_DACL_RETUNE_C14_1 0x4C1A
+#define WM8962_DACL_RETUNE_C14_0 0x4C1B
+#define WM8962_DACL_RETUNE_C15_1 0x4C1C
+#define WM8962_DACL_RETUNE_C15_0 0x4C1D
+#define WM8962_DACL_RETUNE_C16_1 0x4C1E
+#define WM8962_DACL_RETUNE_C16_0 0x4C1F
+#define WM8962_DACL_RETUNE_C17_1 0x4C20
+#define WM8962_DACL_RETUNE_C17_0 0x4C21
+#define WM8962_DACL_RETUNE_C18_1 0x4C22
+#define WM8962_DACL_RETUNE_C18_0 0x4C23
+#define WM8962_DACL_RETUNE_C19_1 0x4C24
+#define WM8962_DACL_RETUNE_C19_0 0x4C25
+#define WM8962_DACL_RETUNE_C20_1 0x4C26
+#define WM8962_DACL_RETUNE_C20_0 0x4C27
+#define WM8962_DACL_RETUNE_C21_1 0x4C28
+#define WM8962_DACL_RETUNE_C21_0 0x4C29
+#define WM8962_DACL_RETUNE_C22_1 0x4C2A
+#define WM8962_DACL_RETUNE_C22_0 0x4C2B
+#define WM8962_DACL_RETUNE_C23_1 0x4C2C
+#define WM8962_DACL_RETUNE_C23_0 0x4C2D
+#define WM8962_DACL_RETUNE_C24_1 0x4C2E
+#define WM8962_DACL_RETUNE_C24_0 0x4C2F
+#define WM8962_DACL_RETUNE_C25_1 0x4C30
+#define WM8962_DACL_RETUNE_C25_0 0x4C31
+#define WM8962_DACL_RETUNE_C26_1 0x4C32
+#define WM8962_DACL_RETUNE_C26_0 0x4C33
+#define WM8962_DACL_RETUNE_C27_1 0x4C34
+#define WM8962_DACL_RETUNE_C27_0 0x4C35
+#define WM8962_DACL_RETUNE_C28_1 0x4C36
+#define WM8962_DACL_RETUNE_C28_0 0x4C37
+#define WM8962_DACL_RETUNE_C29_1 0x4C38
+#define WM8962_DACL_RETUNE_C29_0 0x4C39
+#define WM8962_DACL_RETUNE_C30_1 0x4C3A
+#define WM8962_DACL_RETUNE_C30_0 0x4C3B
+#define WM8962_DACL_RETUNE_C31_1 0x4C3C
+#define WM8962_DACL_RETUNE_C31_0 0x4C3D
+#define WM8962_DACL_RETUNE_C32_1 0x4C3E
+#define WM8962_DACL_RETUNE_C32_0 0x4C3F
+#define WM8962_RETUNEDAC_PG2_1 0x4E00
+#define WM8962_RETUNEDAC_PG2_0 0x4E01
+#define WM8962_RETUNEDAC_PG_1 0x4E02
+#define WM8962_RETUNEDAC_PG_0 0x4E03
+#define WM8962_DACR_RETUNE_C1_1 0x5000
+#define WM8962_DACR_RETUNE_C1_0 0x5001
+#define WM8962_DACR_RETUNE_C2_1 0x5002
+#define WM8962_DACR_RETUNE_C2_0 0x5003
+#define WM8962_DACR_RETUNE_C3_1 0x5004
+#define WM8962_DACR_RETUNE_C3_0 0x5005
+#define WM8962_DACR_RETUNE_C4_1 0x5006
+#define WM8962_DACR_RETUNE_C4_0 0x5007
+#define WM8962_DACR_RETUNE_C5_1 0x5008
+#define WM8962_DACR_RETUNE_C5_0 0x5009
+#define WM8962_DACR_RETUNE_C6_1 0x500A
+#define WM8962_DACR_RETUNE_C6_0 0x500B
+#define WM8962_DACR_RETUNE_C7_1 0x500C
+#define WM8962_DACR_RETUNE_C7_0 0x500D
+#define WM8962_DACR_RETUNE_C8_1 0x500E
+#define WM8962_DACR_RETUNE_C8_0 0x500F
+#define WM8962_DACR_RETUNE_C9_1 0x5010
+#define WM8962_DACR_RETUNE_C9_0 0x5011
+#define WM8962_DACR_RETUNE_C10_1 0x5012
+#define WM8962_DACR_RETUNE_C10_0 0x5013
+#define WM8962_DACR_RETUNE_C11_1 0x5014
+#define WM8962_DACR_RETUNE_C11_0 0x5015
+#define WM8962_DACR_RETUNE_C12_1 0x5016
+#define WM8962_DACR_RETUNE_C12_0 0x5017
+#define WM8962_DACR_RETUNE_C13_1 0x5018
+#define WM8962_DACR_RETUNE_C13_0 0x5019
+#define WM8962_DACR_RETUNE_C14_1 0x501A
+#define WM8962_DACR_RETUNE_C14_0 0x501B
+#define WM8962_DACR_RETUNE_C15_1 0x501C
+#define WM8962_DACR_RETUNE_C15_0 0x501D
+#define WM8962_DACR_RETUNE_C16_1 0x501E
+#define WM8962_DACR_RETUNE_C16_0 0x501F
+#define WM8962_DACR_RETUNE_C17_1 0x5020
+#define WM8962_DACR_RETUNE_C17_0 0x5021
+#define WM8962_DACR_RETUNE_C18_1 0x5022
+#define WM8962_DACR_RETUNE_C18_0 0x5023
+#define WM8962_DACR_RETUNE_C19_1 0x5024
+#define WM8962_DACR_RETUNE_C19_0 0x5025
+#define WM8962_DACR_RETUNE_C20_1 0x5026
+#define WM8962_DACR_RETUNE_C20_0 0x5027
+#define WM8962_DACR_RETUNE_C21_1 0x5028
+#define WM8962_DACR_RETUNE_C21_0 0x5029
+#define WM8962_DACR_RETUNE_C22_1 0x502A
+#define WM8962_DACR_RETUNE_C22_0 0x502B
+#define WM8962_DACR_RETUNE_C23_1 0x502C
+#define WM8962_DACR_RETUNE_C23_0 0x502D
+#define WM8962_DACR_RETUNE_C24_1 0x502E
+#define WM8962_DACR_RETUNE_C24_0 0x502F
+#define WM8962_DACR_RETUNE_C25_1 0x5030
+#define WM8962_DACR_RETUNE_C25_0 0x5031
+#define WM8962_DACR_RETUNE_C26_1 0x5032
+#define WM8962_DACR_RETUNE_C26_0 0x5033
+#define WM8962_DACR_RETUNE_C27_1 0x5034
+#define WM8962_DACR_RETUNE_C27_0 0x5035
+#define WM8962_DACR_RETUNE_C28_1 0x5036
+#define WM8962_DACR_RETUNE_C28_0 0x5037
+#define WM8962_DACR_RETUNE_C29_1 0x5038
+#define WM8962_DACR_RETUNE_C29_0 0x5039
+#define WM8962_DACR_RETUNE_C30_1 0x503A
+#define WM8962_DACR_RETUNE_C30_0 0x503B
+#define WM8962_DACR_RETUNE_C31_1 0x503C
+#define WM8962_DACR_RETUNE_C31_0 0x503D
+#define WM8962_DACR_RETUNE_C32_1 0x503E
+#define WM8962_DACR_RETUNE_C32_0 0x503F
+#define WM8962_VSS_XHD2_1 0x5200
+#define WM8962_VSS_XHD2_0 0x5201
+#define WM8962_VSS_XHD3_1 0x5202
+#define WM8962_VSS_XHD3_0 0x5203
+#define WM8962_VSS_XHN1_1 0x5204
+#define WM8962_VSS_XHN1_0 0x5205
+#define WM8962_VSS_XHN2_1 0x5206
+#define WM8962_VSS_XHN2_0 0x5207
+#define WM8962_VSS_XHN3_1 0x5208
+#define WM8962_VSS_XHN3_0 0x5209
+#define WM8962_VSS_XLA_1 0x520A
+#define WM8962_VSS_XLA_0 0x520B
+#define WM8962_VSS_XLB_1 0x520C
+#define WM8962_VSS_XLB_0 0x520D
+#define WM8962_VSS_XLG_1 0x520E
+#define WM8962_VSS_XLG_0 0x520F
+#define WM8962_VSS_PG2_1 0x5210
+#define WM8962_VSS_PG2_0 0x5211
+#define WM8962_VSS_PG_1 0x5212
+#define WM8962_VSS_PG_0 0x5213
+#define WM8962_VSS_XTD1_1 0x5214
+#define WM8962_VSS_XTD1_0 0x5215
+#define WM8962_VSS_XTD2_1 0x5216
+#define WM8962_VSS_XTD2_0 0x5217
+#define WM8962_VSS_XTD3_1 0x5218
+#define WM8962_VSS_XTD3_0 0x5219
+#define WM8962_VSS_XTD4_1 0x521A
+#define WM8962_VSS_XTD4_0 0x521B
+#define WM8962_VSS_XTD5_1 0x521C
+#define WM8962_VSS_XTD5_0 0x521D
+#define WM8962_VSS_XTD6_1 0x521E
+#define WM8962_VSS_XTD6_0 0x521F
+#define WM8962_VSS_XTD7_1 0x5220
+#define WM8962_VSS_XTD7_0 0x5221
+#define WM8962_VSS_XTD8_1 0x5222
+#define WM8962_VSS_XTD8_0 0x5223
+#define WM8962_VSS_XTD9_1 0x5224
+#define WM8962_VSS_XTD9_0 0x5225
+#define WM8962_VSS_XTD10_1 0x5226
+#define WM8962_VSS_XTD10_0 0x5227
+#define WM8962_VSS_XTD11_1 0x5228
+#define WM8962_VSS_XTD11_0 0x5229
+#define WM8962_VSS_XTD12_1 0x522A
+#define WM8962_VSS_XTD12_0 0x522B
+#define WM8962_VSS_XTD13_1 0x522C
+#define WM8962_VSS_XTD13_0 0x522D
+#define WM8962_VSS_XTD14_1 0x522E
+#define WM8962_VSS_XTD14_0 0x522F
+#define WM8962_VSS_XTD15_1 0x5230
+#define WM8962_VSS_XTD15_0 0x5231
+#define WM8962_VSS_XTD16_1 0x5232
+#define WM8962_VSS_XTD16_0 0x5233
+#define WM8962_VSS_XTD17_1 0x5234
+#define WM8962_VSS_XTD17_0 0x5235
+#define WM8962_VSS_XTD18_1 0x5236
+#define WM8962_VSS_XTD18_0 0x5237
+#define WM8962_VSS_XTD19_1 0x5238
+#define WM8962_VSS_XTD19_0 0x5239
+#define WM8962_VSS_XTD20_1 0x523A
+#define WM8962_VSS_XTD20_0 0x523B
+#define WM8962_VSS_XTD21_1 0x523C
+#define WM8962_VSS_XTD21_0 0x523D
+#define WM8962_VSS_XTD22_1 0x523E
+#define WM8962_VSS_XTD22_0 0x523F
+#define WM8962_VSS_XTD23_1 0x5240
+#define WM8962_VSS_XTD23_0 0x5241
+#define WM8962_VSS_XTD24_1 0x5242
+#define WM8962_VSS_XTD24_0 0x5243
+#define WM8962_VSS_XTD25_1 0x5244
+#define WM8962_VSS_XTD25_0 0x5245
+#define WM8962_VSS_XTD26_1 0x5246
+#define WM8962_VSS_XTD26_0 0x5247
+#define WM8962_VSS_XTD27_1 0x5248
+#define WM8962_VSS_XTD27_0 0x5249
+#define WM8962_VSS_XTD28_1 0x524A
+#define WM8962_VSS_XTD28_0 0x524B
+#define WM8962_VSS_XTD29_1 0x524C
+#define WM8962_VSS_XTD29_0 0x524D
+#define WM8962_VSS_XTD30_1 0x524E
+#define WM8962_VSS_XTD30_0 0x524F
+#define WM8962_VSS_XTD31_1 0x5250
+#define WM8962_VSS_XTD31_0 0x5251
+#define WM8962_VSS_XTD32_1 0x5252
+#define WM8962_VSS_XTD32_0 0x5253
+#define WM8962_VSS_XTS1_1 0x5254
+#define WM8962_VSS_XTS1_0 0x5255
+#define WM8962_VSS_XTS2_1 0x5256
+#define WM8962_VSS_XTS2_0 0x5257
+#define WM8962_VSS_XTS3_1 0x5258
+#define WM8962_VSS_XTS3_0 0x5259
+#define WM8962_VSS_XTS4_1 0x525A
+#define WM8962_VSS_XTS4_0 0x525B
+#define WM8962_VSS_XTS5_1 0x525C
+#define WM8962_VSS_XTS5_0 0x525D
+#define WM8962_VSS_XTS6_1 0x525E
+#define WM8962_VSS_XTS6_0 0x525F
+#define WM8962_VSS_XTS7_1 0x5260
+#define WM8962_VSS_XTS7_0 0x5261
+#define WM8962_VSS_XTS8_1 0x5262
+#define WM8962_VSS_XTS8_0 0x5263
+#define WM8962_VSS_XTS9_1 0x5264
+#define WM8962_VSS_XTS9_0 0x5265
+#define WM8962_VSS_XTS10_1 0x5266
+#define WM8962_VSS_XTS10_0 0x5267
+#define WM8962_VSS_XTS11_1 0x5268
+#define WM8962_VSS_XTS11_0 0x5269
+#define WM8962_VSS_XTS12_1 0x526A
+#define WM8962_VSS_XTS12_0 0x526B
+#define WM8962_VSS_XTS13_1 0x526C
+#define WM8962_VSS_XTS13_0 0x526D
+#define WM8962_VSS_XTS14_1 0x526E
+#define WM8962_VSS_XTS14_0 0x526F
+#define WM8962_VSS_XTS15_1 0x5270
+#define WM8962_VSS_XTS15_0 0x5271
+#define WM8962_VSS_XTS16_1 0x5272
+#define WM8962_VSS_XTS16_0 0x5273
+#define WM8962_VSS_XTS17_1 0x5274
+#define WM8962_VSS_XTS17_0 0x5275
+#define WM8962_VSS_XTS18_1 0x5276
+#define WM8962_VSS_XTS18_0 0x5277
+#define WM8962_VSS_XTS19_1 0x5278
+#define WM8962_VSS_XTS19_0 0x5279
+#define WM8962_VSS_XTS20_1 0x527A
+#define WM8962_VSS_XTS20_0 0x527B
+#define WM8962_VSS_XTS21_1 0x527C
+#define WM8962_VSS_XTS21_0 0x527D
+#define WM8962_VSS_XTS22_1 0x527E
+#define WM8962_VSS_XTS22_0 0x527F
+#define WM8962_VSS_XTS23_1 0x5280
+#define WM8962_VSS_XTS23_0 0x5281
+#define WM8962_VSS_XTS24_1 0x5282
+#define WM8962_VSS_XTS24_0 0x5283
+#define WM8962_VSS_XTS25_1 0x5284
+#define WM8962_VSS_XTS25_0 0x5285
+#define WM8962_VSS_XTS26_1 0x5286
+#define WM8962_VSS_XTS26_0 0x5287
+#define WM8962_VSS_XTS27_1 0x5288
+#define WM8962_VSS_XTS27_0 0x5289
+#define WM8962_VSS_XTS28_1 0x528A
+#define WM8962_VSS_XTS28_0 0x528B
+#define WM8962_VSS_XTS29_1 0x528C
+#define WM8962_VSS_XTS29_0 0x528D
+#define WM8962_VSS_XTS30_1 0x528E
+#define WM8962_VSS_XTS30_0 0x528F
+#define WM8962_VSS_XTS31_1 0x5290
+#define WM8962_VSS_XTS31_0 0x5291
+#define WM8962_VSS_XTS32_1 0x5292
+#define WM8962_VSS_XTS32_0 0x5293
+
+#define WM8962_REGISTER_COUNT 1138
+#define WM8962_MAX_REGISTER 0x5293
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Left Input volume
+ */
+#define WM8962_IN_VU 0x0100 /* IN_VU */
+#define WM8962_IN_VU_MASK 0x0100 /* IN_VU */
+#define WM8962_IN_VU_SHIFT 8 /* IN_VU */
+#define WM8962_IN_VU_WIDTH 1 /* IN_VU */
+#define WM8962_INPGAL_MUTE 0x0080 /* INPGAL_MUTE */
+#define WM8962_INPGAL_MUTE_MASK 0x0080 /* INPGAL_MUTE */
+#define WM8962_INPGAL_MUTE_SHIFT 7 /* INPGAL_MUTE */
+#define WM8962_INPGAL_MUTE_WIDTH 1 /* INPGAL_MUTE */
+#define WM8962_INL_ZC 0x0040 /* INL_ZC */
+#define WM8962_INL_ZC_MASK 0x0040 /* INL_ZC */
+#define WM8962_INL_ZC_SHIFT 6 /* INL_ZC */
+#define WM8962_INL_ZC_WIDTH 1 /* INL_ZC */
+#define WM8962_INL_VOL_MASK 0x003F /* INL_VOL - [5:0] */
+#define WM8962_INL_VOL_SHIFT 0 /* INL_VOL - [5:0] */
+#define WM8962_INL_VOL_WIDTH 6 /* INL_VOL - [5:0] */
+
+/*
+ * R1 (0x01) - Right Input volume
+ */
+#define WM8962_CUST_ID_MASK 0xF000 /* CUST_ID - [15:12] */
+#define WM8962_CUST_ID_SHIFT 12 /* CUST_ID - [15:12] */
+#define WM8962_CUST_ID_WIDTH 4 /* CUST_ID - [15:12] */
+#define WM8962_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */
+#define WM8962_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */
+#define WM8962_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */
+#define WM8962_IN_VU 0x0100 /* IN_VU */
+#define WM8962_IN_VU_MASK 0x0100 /* IN_VU */
+#define WM8962_IN_VU_SHIFT 8 /* IN_VU */
+#define WM8962_IN_VU_WIDTH 1 /* IN_VU */
+#define WM8962_INPGAR_MUTE 0x0080 /* INPGAR_MUTE */
+#define WM8962_INPGAR_MUTE_MASK 0x0080 /* INPGAR_MUTE */
+#define WM8962_INPGAR_MUTE_SHIFT 7 /* INPGAR_MUTE */
+#define WM8962_INPGAR_MUTE_WIDTH 1 /* INPGAR_MUTE */
+#define WM8962_INR_ZC 0x0040 /* INR_ZC */
+#define WM8962_INR_ZC_MASK 0x0040 /* INR_ZC */
+#define WM8962_INR_ZC_SHIFT 6 /* INR_ZC */
+#define WM8962_INR_ZC_WIDTH 1 /* INR_ZC */
+#define WM8962_INR_VOL_MASK 0x003F /* INR_VOL - [5:0] */
+#define WM8962_INR_VOL_SHIFT 0 /* INR_VOL - [5:0] */
+#define WM8962_INR_VOL_WIDTH 6 /* INR_VOL - [5:0] */
+
+/*
+ * R2 (0x02) - HPOUTL volume
+ */
+#define WM8962_HPOUT_VU 0x0100 /* HPOUT_VU */
+#define WM8962_HPOUT_VU_MASK 0x0100 /* HPOUT_VU */
+#define WM8962_HPOUT_VU_SHIFT 8 /* HPOUT_VU */
+#define WM8962_HPOUT_VU_WIDTH 1 /* HPOUT_VU */
+#define WM8962_HPOUTL_ZC 0x0080 /* HPOUTL_ZC */
+#define WM8962_HPOUTL_ZC_MASK 0x0080 /* HPOUTL_ZC */
+#define WM8962_HPOUTL_ZC_SHIFT 7 /* HPOUTL_ZC */
+#define WM8962_HPOUTL_ZC_WIDTH 1 /* HPOUTL_ZC */
+#define WM8962_HPOUTL_VOL_MASK 0x007F /* HPOUTL_VOL - [6:0] */
+#define WM8962_HPOUTL_VOL_SHIFT 0 /* HPOUTL_VOL - [6:0] */
+#define WM8962_HPOUTL_VOL_WIDTH 7 /* HPOUTL_VOL - [6:0] */
+
+/*
+ * R3 (0x03) - HPOUTR volume
+ */
+#define WM8962_HPOUT_VU 0x0100 /* HPOUT_VU */
+#define WM8962_HPOUT_VU_MASK 0x0100 /* HPOUT_VU */
+#define WM8962_HPOUT_VU_SHIFT 8 /* HPOUT_VU */
+#define WM8962_HPOUT_VU_WIDTH 1 /* HPOUT_VU */
+#define WM8962_HPOUTR_ZC 0x0080 /* HPOUTR_ZC */
+#define WM8962_HPOUTR_ZC_MASK 0x0080 /* HPOUTR_ZC */
+#define WM8962_HPOUTR_ZC_SHIFT 7 /* HPOUTR_ZC */
+#define WM8962_HPOUTR_ZC_WIDTH 1 /* HPOUTR_ZC */
+#define WM8962_HPOUTR_VOL_MASK 0x007F /* HPOUTR_VOL - [6:0] */
+#define WM8962_HPOUTR_VOL_SHIFT 0 /* HPOUTR_VOL - [6:0] */
+#define WM8962_HPOUTR_VOL_WIDTH 7 /* HPOUTR_VOL - [6:0] */
+
+/*
+ * R4 (0x04) - Clocking1
+ */
+#define WM8962_DSPCLK_DIV_MASK 0x0600 /* DSPCLK_DIV - [10:9] */
+#define WM8962_DSPCLK_DIV_SHIFT 9 /* DSPCLK_DIV - [10:9] */
+#define WM8962_DSPCLK_DIV_WIDTH 2 /* DSPCLK_DIV - [10:9] */
+#define WM8962_ADCSYS_CLK_DIV_MASK 0x01C0 /* ADCSYS_CLK_DIV - [8:6] */
+#define WM8962_ADCSYS_CLK_DIV_SHIFT 6 /* ADCSYS_CLK_DIV - [8:6] */
+#define WM8962_ADCSYS_CLK_DIV_WIDTH 3 /* ADCSYS_CLK_DIV - [8:6] */
+#define WM8962_DACSYS_CLK_DIV_MASK 0x0038 /* DACSYS_CLK_DIV - [5:3] */
+#define WM8962_DACSYS_CLK_DIV_SHIFT 3 /* DACSYS_CLK_DIV - [5:3] */
+#define WM8962_DACSYS_CLK_DIV_WIDTH 3 /* DACSYS_CLK_DIV - [5:3] */
+#define WM8962_MCLKDIV_MASK 0x0006 /* MCLKDIV - [2:1] */
+#define WM8962_MCLKDIV_SHIFT 1 /* MCLKDIV - [2:1] */
+#define WM8962_MCLKDIV_WIDTH 2 /* MCLKDIV - [2:1] */
+
+/*
+ * R5 (0x05) - ADC & DAC Control 1
+ */
+#define WM8962_ADCR_DAT_INV 0x0040 /* ADCR_DAT_INV */
+#define WM8962_ADCR_DAT_INV_MASK 0x0040 /* ADCR_DAT_INV */
+#define WM8962_ADCR_DAT_INV_SHIFT 6 /* ADCR_DAT_INV */
+#define WM8962_ADCR_DAT_INV_WIDTH 1 /* ADCR_DAT_INV */
+#define WM8962_ADCL_DAT_INV 0x0020 /* ADCL_DAT_INV */
+#define WM8962_ADCL_DAT_INV_MASK 0x0020 /* ADCL_DAT_INV */
+#define WM8962_ADCL_DAT_INV_SHIFT 5 /* ADCL_DAT_INV */
+#define WM8962_ADCL_DAT_INV_WIDTH 1 /* ADCL_DAT_INV */
+#define WM8962_DAC_MUTE_RAMP 0x0010 /* DAC_MUTE_RAMP */
+#define WM8962_DAC_MUTE_RAMP_MASK 0x0010 /* DAC_MUTE_RAMP */
+#define WM8962_DAC_MUTE_RAMP_SHIFT 4 /* DAC_MUTE_RAMP */
+#define WM8962_DAC_MUTE_RAMP_WIDTH 1 /* DAC_MUTE_RAMP */
+#define WM8962_DAC_MUTE 0x0008 /* DAC_MUTE */
+#define WM8962_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */
+#define WM8962_DAC_MUTE_SHIFT 3 /* DAC_MUTE */
+#define WM8962_DAC_MUTE_WIDTH 1 /* DAC_MUTE */
+#define WM8962_DAC_DEEMP_MASK 0x0006 /* DAC_DEEMP - [2:1] */
+#define WM8962_DAC_DEEMP_SHIFT 1 /* DAC_DEEMP - [2:1] */
+#define WM8962_DAC_DEEMP_WIDTH 2 /* DAC_DEEMP - [2:1] */
+#define WM8962_ADC_HPF_DIS 0x0001 /* ADC_HPF_DIS */
+#define WM8962_ADC_HPF_DIS_MASK 0x0001 /* ADC_HPF_DIS */
+#define WM8962_ADC_HPF_DIS_SHIFT 0 /* ADC_HPF_DIS */
+#define WM8962_ADC_HPF_DIS_WIDTH 1 /* ADC_HPF_DIS */
+
+/*
+ * R6 (0x06) - ADC & DAC Control 2
+ */
+#define WM8962_ADC_HPF_SR_MASK 0x3000 /* ADC_HPF_SR - [13:12] */
+#define WM8962_ADC_HPF_SR_SHIFT 12 /* ADC_HPF_SR - [13:12] */
+#define WM8962_ADC_HPF_SR_WIDTH 2 /* ADC_HPF_SR - [13:12] */
+#define WM8962_ADC_HPF_MODE 0x0400 /* ADC_HPF_MODE */
+#define WM8962_ADC_HPF_MODE_MASK 0x0400 /* ADC_HPF_MODE */
+#define WM8962_ADC_HPF_MODE_SHIFT 10 /* ADC_HPF_MODE */
+#define WM8962_ADC_HPF_MODE_WIDTH 1 /* ADC_HPF_MODE */
+#define WM8962_ADC_HPF_CUT_MASK 0x0380 /* ADC_HPF_CUT - [9:7] */
+#define WM8962_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [9:7] */
+#define WM8962_ADC_HPF_CUT_WIDTH 3 /* ADC_HPF_CUT - [9:7] */
+#define WM8962_DACR_DAT_INV 0x0040 /* DACR_DAT_INV */
+#define WM8962_DACR_DAT_INV_MASK 0x0040 /* DACR_DAT_INV */
+#define WM8962_DACR_DAT_INV_SHIFT 6 /* DACR_DAT_INV */
+#define WM8962_DACR_DAT_INV_WIDTH 1 /* DACR_DAT_INV */
+#define WM8962_DACL_DAT_INV 0x0020 /* DACL_DAT_INV */
+#define WM8962_DACL_DAT_INV_MASK 0x0020 /* DACL_DAT_INV */
+#define WM8962_DACL_DAT_INV_SHIFT 5 /* DACL_DAT_INV */
+#define WM8962_DACL_DAT_INV_WIDTH 1 /* DACL_DAT_INV */
+#define WM8962_DAC_UNMUTE_RAMP 0x0008 /* DAC_UNMUTE_RAMP */
+#define WM8962_DAC_UNMUTE_RAMP_MASK 0x0008 /* DAC_UNMUTE_RAMP */
+#define WM8962_DAC_UNMUTE_RAMP_SHIFT 3 /* DAC_UNMUTE_RAMP */
+#define WM8962_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */
+#define WM8962_DAC_MUTERATE 0x0004 /* DAC_MUTERATE */
+#define WM8962_DAC_MUTERATE_MASK 0x0004 /* DAC_MUTERATE */
+#define WM8962_DAC_MUTERATE_SHIFT 2 /* DAC_MUTERATE */
+#define WM8962_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
+#define WM8962_DAC_HP 0x0001 /* DAC_HP */
+#define WM8962_DAC_HP_MASK 0x0001 /* DAC_HP */
+#define WM8962_DAC_HP_SHIFT 0 /* DAC_HP */
+#define WM8962_DAC_HP_WIDTH 1 /* DAC_HP */
+
+/*
+ * R7 (0x07) - Audio Interface 0
+ */
+#define WM8962_AIFDAC_TDM_MODE 0x1000 /* AIFDAC_TDM_MODE */
+#define WM8962_AIFDAC_TDM_MODE_MASK 0x1000 /* AIFDAC_TDM_MODE */
+#define WM8962_AIFDAC_TDM_MODE_SHIFT 12 /* AIFDAC_TDM_MODE */
+#define WM8962_AIFDAC_TDM_MODE_WIDTH 1 /* AIFDAC_TDM_MODE */
+#define WM8962_AIFDAC_TDM_SLOT 0x0800 /* AIFDAC_TDM_SLOT */
+#define WM8962_AIFDAC_TDM_SLOT_MASK 0x0800 /* AIFDAC_TDM_SLOT */
+#define WM8962_AIFDAC_TDM_SLOT_SHIFT 11 /* AIFDAC_TDM_SLOT */
+#define WM8962_AIFDAC_TDM_SLOT_WIDTH 1 /* AIFDAC_TDM_SLOT */
+#define WM8962_AIFADC_TDM_MODE 0x0400 /* AIFADC_TDM_MODE */
+#define WM8962_AIFADC_TDM_MODE_MASK 0x0400 /* AIFADC_TDM_MODE */
+#define WM8962_AIFADC_TDM_MODE_SHIFT 10 /* AIFADC_TDM_MODE */
+#define WM8962_AIFADC_TDM_MODE_WIDTH 1 /* AIFADC_TDM_MODE */
+#define WM8962_AIFADC_TDM_SLOT 0x0200 /* AIFADC_TDM_SLOT */
+#define WM8962_AIFADC_TDM_SLOT_MASK 0x0200 /* AIFADC_TDM_SLOT */
+#define WM8962_AIFADC_TDM_SLOT_SHIFT 9 /* AIFADC_TDM_SLOT */
+#define WM8962_AIFADC_TDM_SLOT_WIDTH 1 /* AIFADC_TDM_SLOT */
+#define WM8962_ADC_LRSWAP 0x0100 /* ADC_LRSWAP */
+#define WM8962_ADC_LRSWAP_MASK 0x0100 /* ADC_LRSWAP */
+#define WM8962_ADC_LRSWAP_SHIFT 8 /* ADC_LRSWAP */
+#define WM8962_ADC_LRSWAP_WIDTH 1 /* ADC_LRSWAP */
+#define WM8962_BCLK_INV 0x0080 /* BCLK_INV */
+#define WM8962_BCLK_INV_MASK 0x0080 /* BCLK_INV */
+#define WM8962_BCLK_INV_SHIFT 7 /* BCLK_INV */
+#define WM8962_BCLK_INV_WIDTH 1 /* BCLK_INV */
+#define WM8962_MSTR 0x0040 /* MSTR */
+#define WM8962_MSTR_MASK 0x0040 /* MSTR */
+#define WM8962_MSTR_SHIFT 6 /* MSTR */
+#define WM8962_MSTR_WIDTH 1 /* MSTR */
+#define WM8962_DAC_LRSWAP 0x0020 /* DAC_LRSWAP */
+#define WM8962_DAC_LRSWAP_MASK 0x0020 /* DAC_LRSWAP */
+#define WM8962_DAC_LRSWAP_SHIFT 5 /* DAC_LRSWAP */
+#define WM8962_DAC_LRSWAP_WIDTH 1 /* DAC_LRSWAP */
+#define WM8962_LRCLK_INV 0x0010 /* LRCLK_INV */
+#define WM8962_LRCLK_INV_MASK 0x0010 /* LRCLK_INV */
+#define WM8962_LRCLK_INV_SHIFT 4 /* LRCLK_INV */
+#define WM8962_LRCLK_INV_WIDTH 1 /* LRCLK_INV */
+#define WM8962_WL_MASK 0x000C /* WL - [3:2] */
+#define WM8962_WL_SHIFT 2 /* WL - [3:2] */
+#define WM8962_WL_WIDTH 2 /* WL - [3:2] */
+#define WM8962_FMT_MASK 0x0003 /* FMT - [1:0] */
+#define WM8962_FMT_SHIFT 0 /* FMT - [1:0] */
+#define WM8962_FMT_WIDTH 2 /* FMT - [1:0] */
+
+/*
+ * R8 (0x08) - Clocking2
+ */
+#define WM8962_CLKREG_OVD 0x0800 /* CLKREG_OVD */
+#define WM8962_CLKREG_OVD_MASK 0x0800 /* CLKREG_OVD */
+#define WM8962_CLKREG_OVD_SHIFT 11 /* CLKREG_OVD */
+#define WM8962_CLKREG_OVD_WIDTH 1 /* CLKREG_OVD */
+#define WM8962_SYSCLK_SRC_MASK 0x0600 /* SYSCLK_SRC - [10:9] */
+#define WM8962_SYSCLK_SRC_SHIFT 9 /* SYSCLK_SRC - [10:9] */
+#define WM8962_SYSCLK_SRC_WIDTH 2 /* SYSCLK_SRC - [10:9] */
+#define WM8962_CLASSD_CLK_DIV_MASK 0x01C0 /* CLASSD_CLK_DIV - [8:6] */
+#define WM8962_CLASSD_CLK_DIV_SHIFT 6 /* CLASSD_CLK_DIV - [8:6] */
+#define WM8962_CLASSD_CLK_DIV_WIDTH 3 /* CLASSD_CLK_DIV - [8:6] */
+#define WM8962_SYSCLK_ENA 0x0020 /* SYSCLK_ENA */
+#define WM8962_SYSCLK_ENA_MASK 0x0020 /* SYSCLK_ENA */
+#define WM8962_SYSCLK_ENA_SHIFT 5 /* SYSCLK_ENA */
+#define WM8962_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */
+#define WM8962_BCLK_DIV_MASK 0x000F /* BCLK_DIV - [3:0] */
+#define WM8962_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [3:0] */
+#define WM8962_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [3:0] */
+
+/*
+ * R9 (0x09) - Audio Interface 1
+ */
+#define WM8962_AUTOMUTE_STS 0x0800 /* AUTOMUTE_STS */
+#define WM8962_AUTOMUTE_STS_MASK 0x0800 /* AUTOMUTE_STS */
+#define WM8962_AUTOMUTE_STS_SHIFT 11 /* AUTOMUTE_STS */
+#define WM8962_AUTOMUTE_STS_WIDTH 1 /* AUTOMUTE_STS */
+#define WM8962_DAC_AUTOMUTE_SAMPLES_MASK 0x0300 /* DAC_AUTOMUTE_SAMPLES - [9:8] */
+#define WM8962_DAC_AUTOMUTE_SAMPLES_SHIFT 8 /* DAC_AUTOMUTE_SAMPLES - [9:8] */
+#define WM8962_DAC_AUTOMUTE_SAMPLES_WIDTH 2 /* DAC_AUTOMUTE_SAMPLES - [9:8] */
+#define WM8962_DAC_AUTOMUTE 0x0080 /* DAC_AUTOMUTE */
+#define WM8962_DAC_AUTOMUTE_MASK 0x0080 /* DAC_AUTOMUTE */
+#define WM8962_DAC_AUTOMUTE_SHIFT 7 /* DAC_AUTOMUTE */
+#define WM8962_DAC_AUTOMUTE_WIDTH 1 /* DAC_AUTOMUTE */
+#define WM8962_DAC_COMP 0x0010 /* DAC_COMP */
+#define WM8962_DAC_COMP_MASK 0x0010 /* DAC_COMP */
+#define WM8962_DAC_COMP_SHIFT 4 /* DAC_COMP */
+#define WM8962_DAC_COMP_WIDTH 1 /* DAC_COMP */
+#define WM8962_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */
+#define WM8962_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */
+#define WM8962_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */
+#define WM8962_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */
+#define WM8962_ADC_COMP 0x0004 /* ADC_COMP */
+#define WM8962_ADC_COMP_MASK 0x0004 /* ADC_COMP */
+#define WM8962_ADC_COMP_SHIFT 2 /* ADC_COMP */
+#define WM8962_ADC_COMP_WIDTH 1 /* ADC_COMP */
+#define WM8962_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */
+#define WM8962_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */
+#define WM8962_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */
+#define WM8962_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */
+#define WM8962_LOOPBACK 0x0001 /* LOOPBACK */
+#define WM8962_LOOPBACK_MASK 0x0001 /* LOOPBACK */
+#define WM8962_LOOPBACK_SHIFT 0 /* LOOPBACK */
+#define WM8962_LOOPBACK_WIDTH 1 /* LOOPBACK */
+
+/*
+ * R10 (0x0A) - Left DAC volume
+ */
+#define WM8962_DAC_VU 0x0100 /* DAC_VU */
+#define WM8962_DAC_VU_MASK 0x0100 /* DAC_VU */
+#define WM8962_DAC_VU_SHIFT 8 /* DAC_VU */
+#define WM8962_DAC_VU_WIDTH 1 /* DAC_VU */
+#define WM8962_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */
+#define WM8962_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */
+#define WM8962_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */
+
+/*
+ * R11 (0x0B) - Right DAC volume
+ */
+#define WM8962_DAC_VU 0x0100 /* DAC_VU */
+#define WM8962_DAC_VU_MASK 0x0100 /* DAC_VU */
+#define WM8962_DAC_VU_SHIFT 8 /* DAC_VU */
+#define WM8962_DAC_VU_WIDTH 1 /* DAC_VU */
+#define WM8962_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */
+#define WM8962_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */
+#define WM8962_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */
+
+/*
+ * R14 (0x0E) - Audio Interface 2
+ */
+#define WM8962_AIF_RATE_MASK 0x07FF /* AIF_RATE - [10:0] */
+#define WM8962_AIF_RATE_SHIFT 0 /* AIF_RATE - [10:0] */
+#define WM8962_AIF_RATE_WIDTH 11 /* AIF_RATE - [10:0] */
+
+/*
+ * R15 (0x0F) - Software Reset
+ */
+#define WM8962_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */
+#define WM8962_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */
+#define WM8962_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */
+
+/*
+ * R17 (0x11) - ALC1
+ */
+#define WM8962_ALC_INACTIVE_ENA 0x0400 /* ALC_INACTIVE_ENA */
+#define WM8962_ALC_INACTIVE_ENA_MASK 0x0400 /* ALC_INACTIVE_ENA */
+#define WM8962_ALC_INACTIVE_ENA_SHIFT 10 /* ALC_INACTIVE_ENA */
+#define WM8962_ALC_INACTIVE_ENA_WIDTH 1 /* ALC_INACTIVE_ENA */
+#define WM8962_ALC_LVL_MODE 0x0200 /* ALC_LVL_MODE */
+#define WM8962_ALC_LVL_MODE_MASK 0x0200 /* ALC_LVL_MODE */
+#define WM8962_ALC_LVL_MODE_SHIFT 9 /* ALC_LVL_MODE */
+#define WM8962_ALC_LVL_MODE_WIDTH 1 /* ALC_LVL_MODE */
+#define WM8962_ALCL_ENA 0x0100 /* ALCL_ENA */
+#define WM8962_ALCL_ENA_MASK 0x0100 /* ALCL_ENA */
+#define WM8962_ALCL_ENA_SHIFT 8 /* ALCL_ENA */
+#define WM8962_ALCL_ENA_WIDTH 1 /* ALCL_ENA */
+#define WM8962_ALCR_ENA 0x0080 /* ALCR_ENA */
+#define WM8962_ALCR_ENA_MASK 0x0080 /* ALCR_ENA */
+#define WM8962_ALCR_ENA_SHIFT 7 /* ALCR_ENA */
+#define WM8962_ALCR_ENA_WIDTH 1 /* ALCR_ENA */
+#define WM8962_ALC_MAXGAIN_MASK 0x0070 /* ALC_MAXGAIN - [6:4] */
+#define WM8962_ALC_MAXGAIN_SHIFT 4 /* ALC_MAXGAIN - [6:4] */
+#define WM8962_ALC_MAXGAIN_WIDTH 3 /* ALC_MAXGAIN - [6:4] */
+#define WM8962_ALC_LVL_MASK 0x000F /* ALC_LVL - [3:0] */
+#define WM8962_ALC_LVL_SHIFT 0 /* ALC_LVL - [3:0] */
+#define WM8962_ALC_LVL_WIDTH 4 /* ALC_LVL - [3:0] */
+
+/*
+ * R18 (0x12) - ALC2
+ */
+#define WM8962_ALC_LOCK_STS 0x8000 /* ALC_LOCK_STS */
+#define WM8962_ALC_LOCK_STS_MASK 0x8000 /* ALC_LOCK_STS */
+#define WM8962_ALC_LOCK_STS_SHIFT 15 /* ALC_LOCK_STS */
+#define WM8962_ALC_LOCK_STS_WIDTH 1 /* ALC_LOCK_STS */
+#define WM8962_ALC_THRESH_STS 0x4000 /* ALC_THRESH_STS */
+#define WM8962_ALC_THRESH_STS_MASK 0x4000 /* ALC_THRESH_STS */
+#define WM8962_ALC_THRESH_STS_SHIFT 14 /* ALC_THRESH_STS */
+#define WM8962_ALC_THRESH_STS_WIDTH 1 /* ALC_THRESH_STS */
+#define WM8962_ALC_SAT_STS 0x2000 /* ALC_SAT_STS */
+#define WM8962_ALC_SAT_STS_MASK 0x2000 /* ALC_SAT_STS */
+#define WM8962_ALC_SAT_STS_SHIFT 13 /* ALC_SAT_STS */
+#define WM8962_ALC_SAT_STS_WIDTH 1 /* ALC_SAT_STS */
+#define WM8962_ALC_PKOVR_STS 0x1000 /* ALC_PKOVR_STS */
+#define WM8962_ALC_PKOVR_STS_MASK 0x1000 /* ALC_PKOVR_STS */
+#define WM8962_ALC_PKOVR_STS_SHIFT 12 /* ALC_PKOVR_STS */
+#define WM8962_ALC_PKOVR_STS_WIDTH 1 /* ALC_PKOVR_STS */
+#define WM8962_ALC_NGATE_STS 0x0800 /* ALC_NGATE_STS */
+#define WM8962_ALC_NGATE_STS_MASK 0x0800 /* ALC_NGATE_STS */
+#define WM8962_ALC_NGATE_STS_SHIFT 11 /* ALC_NGATE_STS */
+#define WM8962_ALC_NGATE_STS_WIDTH 1 /* ALC_NGATE_STS */
+#define WM8962_ALC_ZC 0x0080 /* ALC_ZC */
+#define WM8962_ALC_ZC_MASK 0x0080 /* ALC_ZC */
+#define WM8962_ALC_ZC_SHIFT 7 /* ALC_ZC */
+#define WM8962_ALC_ZC_WIDTH 1 /* ALC_ZC */
+#define WM8962_ALC_MINGAIN_MASK 0x0070 /* ALC_MINGAIN - [6:4] */
+#define WM8962_ALC_MINGAIN_SHIFT 4 /* ALC_MINGAIN - [6:4] */
+#define WM8962_ALC_MINGAIN_WIDTH 3 /* ALC_MINGAIN - [6:4] */
+#define WM8962_ALC_HLD_MASK 0x000F /* ALC_HLD - [3:0] */
+#define WM8962_ALC_HLD_SHIFT 0 /* ALC_HLD - [3:0] */
+#define WM8962_ALC_HLD_WIDTH 4 /* ALC_HLD - [3:0] */
+
+/*
+ * R19 (0x13) - ALC3
+ */
+#define WM8962_ALC_NGATE_GAIN_MASK 0x1C00 /* ALC_NGATE_GAIN - [12:10] */
+#define WM8962_ALC_NGATE_GAIN_SHIFT 10 /* ALC_NGATE_GAIN - [12:10] */
+#define WM8962_ALC_NGATE_GAIN_WIDTH 3 /* ALC_NGATE_GAIN - [12:10] */
+#define WM8962_ALC_MODE 0x0100 /* ALC_MODE */
+#define WM8962_ALC_MODE_MASK 0x0100 /* ALC_MODE */
+#define WM8962_ALC_MODE_SHIFT 8 /* ALC_MODE */
+#define WM8962_ALC_MODE_WIDTH 1 /* ALC_MODE */
+#define WM8962_ALC_DCY_MASK 0x00F0 /* ALC_DCY - [7:4] */
+#define WM8962_ALC_DCY_SHIFT 4 /* ALC_DCY - [7:4] */
+#define WM8962_ALC_DCY_WIDTH 4 /* ALC_DCY - [7:4] */
+#define WM8962_ALC_ATK_MASK 0x000F /* ALC_ATK - [3:0] */
+#define WM8962_ALC_ATK_SHIFT 0 /* ALC_ATK - [3:0] */
+#define WM8962_ALC_ATK_WIDTH 4 /* ALC_ATK - [3:0] */
+
+/*
+ * R20 (0x14) - Noise Gate
+ */
+#define WM8962_ALC_NGATE_DCY_MASK 0xF000 /* ALC_NGATE_DCY - [15:12] */
+#define WM8962_ALC_NGATE_DCY_SHIFT 12 /* ALC_NGATE_DCY - [15:12] */
+#define WM8962_ALC_NGATE_DCY_WIDTH 4 /* ALC_NGATE_DCY - [15:12] */
+#define WM8962_ALC_NGATE_ATK_MASK 0x0F00 /* ALC_NGATE_ATK - [11:8] */
+#define WM8962_ALC_NGATE_ATK_SHIFT 8 /* ALC_NGATE_ATK - [11:8] */
+#define WM8962_ALC_NGATE_ATK_WIDTH 4 /* ALC_NGATE_ATK - [11:8] */
+#define WM8962_ALC_NGATE_THR_MASK 0x00F8 /* ALC_NGATE_THR - [7:3] */
+#define WM8962_ALC_NGATE_THR_SHIFT 3 /* ALC_NGATE_THR - [7:3] */
+#define WM8962_ALC_NGATE_THR_WIDTH 5 /* ALC_NGATE_THR - [7:3] */
+#define WM8962_ALC_NGATE_MODE_MASK 0x0006 /* ALC_NGATE_MODE - [2:1] */
+#define WM8962_ALC_NGATE_MODE_SHIFT 1 /* ALC_NGATE_MODE - [2:1] */
+#define WM8962_ALC_NGATE_MODE_WIDTH 2 /* ALC_NGATE_MODE - [2:1] */
+#define WM8962_ALC_NGATE_ENA 0x0001 /* ALC_NGATE_ENA */
+#define WM8962_ALC_NGATE_ENA_MASK 0x0001 /* ALC_NGATE_ENA */
+#define WM8962_ALC_NGATE_ENA_SHIFT 0 /* ALC_NGATE_ENA */
+#define WM8962_ALC_NGATE_ENA_WIDTH 1 /* ALC_NGATE_ENA */
+
+/*
+ * R21 (0x15) - Left ADC volume
+ */
+#define WM8962_ADC_VU 0x0100 /* ADC_VU */
+#define WM8962_ADC_VU_MASK 0x0100 /* ADC_VU */
+#define WM8962_ADC_VU_SHIFT 8 /* ADC_VU */
+#define WM8962_ADC_VU_WIDTH 1 /* ADC_VU */
+#define WM8962_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */
+#define WM8962_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */
+#define WM8962_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */
+
+/*
+ * R22 (0x16) - Right ADC volume
+ */
+#define WM8962_ADC_VU 0x0100 /* ADC_VU */
+#define WM8962_ADC_VU_MASK 0x0100 /* ADC_VU */
+#define WM8962_ADC_VU_SHIFT 8 /* ADC_VU */
+#define WM8962_ADC_VU_WIDTH 1 /* ADC_VU */
+#define WM8962_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */
+#define WM8962_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */
+#define WM8962_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */
+
+/*
+ * R23 (0x17) - Additional control(1)
+ */
+#define WM8962_THERR_ACT 0x0100 /* THERR_ACT */
+#define WM8962_THERR_ACT_MASK 0x0100 /* THERR_ACT */
+#define WM8962_THERR_ACT_SHIFT 8 /* THERR_ACT */
+#define WM8962_THERR_ACT_WIDTH 1 /* THERR_ACT */
+#define WM8962_ADC_BIAS 0x0040 /* ADC_BIAS */
+#define WM8962_ADC_BIAS_MASK 0x0040 /* ADC_BIAS */
+#define WM8962_ADC_BIAS_SHIFT 6 /* ADC_BIAS */
+#define WM8962_ADC_BIAS_WIDTH 1 /* ADC_BIAS */
+#define WM8962_ADC_HP 0x0020 /* ADC_HP */
+#define WM8962_ADC_HP_MASK 0x0020 /* ADC_HP */
+#define WM8962_ADC_HP_SHIFT 5 /* ADC_HP */
+#define WM8962_ADC_HP_WIDTH 1 /* ADC_HP */
+#define WM8962_TOCLK_ENA 0x0001 /* TOCLK_ENA */
+#define WM8962_TOCLK_ENA_MASK 0x0001 /* TOCLK_ENA */
+#define WM8962_TOCLK_ENA_SHIFT 0 /* TOCLK_ENA */
+#define WM8962_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */
+
+/*
+ * R24 (0x18) - Additional control(2)
+ */
+#define WM8962_AIF_TRI 0x0008 /* AIF_TRI */
+#define WM8962_AIF_TRI_MASK 0x0008 /* AIF_TRI */
+#define WM8962_AIF_TRI_SHIFT 3 /* AIF_TRI */
+#define WM8962_AIF_TRI_WIDTH 1 /* AIF_TRI */
+
+/*
+ * R25 (0x19) - Pwr Mgmt (1)
+ */
+#define WM8962_DMIC_ENA 0x0400 /* DMIC_ENA */
+#define WM8962_DMIC_ENA_MASK 0x0400 /* DMIC_ENA */
+#define WM8962_DMIC_ENA_SHIFT 10 /* DMIC_ENA */
+#define WM8962_DMIC_ENA_WIDTH 1 /* DMIC_ENA */
+#define WM8962_OPCLK_ENA 0x0200 /* OPCLK_ENA */
+#define WM8962_OPCLK_ENA_MASK 0x0200 /* OPCLK_ENA */
+#define WM8962_OPCLK_ENA_SHIFT 9 /* OPCLK_ENA */
+#define WM8962_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */
+#define WM8962_VMID_SEL_MASK 0x0180 /* VMID_SEL - [8:7] */
+#define WM8962_VMID_SEL_SHIFT 7 /* VMID_SEL - [8:7] */
+#define WM8962_VMID_SEL_WIDTH 2 /* VMID_SEL - [8:7] */
+#define WM8962_BIAS_ENA 0x0040 /* BIAS_ENA */
+#define WM8962_BIAS_ENA_MASK 0x0040 /* BIAS_ENA */
+#define WM8962_BIAS_ENA_SHIFT 6 /* BIAS_ENA */
+#define WM8962_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
+#define WM8962_INL_ENA 0x0020 /* INL_ENA */
+#define WM8962_INL_ENA_MASK 0x0020 /* INL_ENA */
+#define WM8962_INL_ENA_SHIFT 5 /* INL_ENA */
+#define WM8962_INL_ENA_WIDTH 1 /* INL_ENA */
+#define WM8962_INR_ENA 0x0010 /* INR_ENA */
+#define WM8962_INR_ENA_MASK 0x0010 /* INR_ENA */
+#define WM8962_INR_ENA_SHIFT 4 /* INR_ENA */
+#define WM8962_INR_ENA_WIDTH 1 /* INR_ENA */
+#define WM8962_ADCL_ENA 0x0008 /* ADCL_ENA */
+#define WM8962_ADCL_ENA_MASK 0x0008 /* ADCL_ENA */
+#define WM8962_ADCL_ENA_SHIFT 3 /* ADCL_ENA */
+#define WM8962_ADCL_ENA_WIDTH 1 /* ADCL_ENA */
+#define WM8962_ADCR_ENA 0x0004 /* ADCR_ENA */
+#define WM8962_ADCR_ENA_MASK 0x0004 /* ADCR_ENA */
+#define WM8962_ADCR_ENA_SHIFT 2 /* ADCR_ENA */
+#define WM8962_ADCR_ENA_WIDTH 1 /* ADCR_ENA */
+#define WM8962_MICBIAS_ENA 0x0002 /* MICBIAS_ENA */
+#define WM8962_MICBIAS_ENA_MASK 0x0002 /* MICBIAS_ENA */
+#define WM8962_MICBIAS_ENA_SHIFT 1 /* MICBIAS_ENA */
+#define WM8962_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
+
+/*
+ * R26 (0x1A) - Pwr Mgmt (2)
+ */
+#define WM8962_DACL_ENA 0x0100 /* DACL_ENA */
+#define WM8962_DACL_ENA_MASK 0x0100 /* DACL_ENA */
+#define WM8962_DACL_ENA_SHIFT 8 /* DACL_ENA */
+#define WM8962_DACL_ENA_WIDTH 1 /* DACL_ENA */
+#define WM8962_DACR_ENA 0x0080 /* DACR_ENA */
+#define WM8962_DACR_ENA_MASK 0x0080 /* DACR_ENA */
+#define WM8962_DACR_ENA_SHIFT 7 /* DACR_ENA */
+#define WM8962_DACR_ENA_WIDTH 1 /* DACR_ENA */
+#define WM8962_HPOUTL_PGA_ENA 0x0040 /* HPOUTL_PGA_ENA */
+#define WM8962_HPOUTL_PGA_ENA_MASK 0x0040 /* HPOUTL_PGA_ENA */
+#define WM8962_HPOUTL_PGA_ENA_SHIFT 6 /* HPOUTL_PGA_ENA */
+#define WM8962_HPOUTL_PGA_ENA_WIDTH 1 /* HPOUTL_PGA_ENA */
+#define WM8962_HPOUTR_PGA_ENA 0x0020 /* HPOUTR_PGA_ENA */
+#define WM8962_HPOUTR_PGA_ENA_MASK 0x0020 /* HPOUTR_PGA_ENA */
+#define WM8962_HPOUTR_PGA_ENA_SHIFT 5 /* HPOUTR_PGA_ENA */
+#define WM8962_HPOUTR_PGA_ENA_WIDTH 1 /* HPOUTR_PGA_ENA */
+#define WM8962_SPKOUTL_PGA_ENA 0x0010 /* SPKOUTL_PGA_ENA */
+#define WM8962_SPKOUTL_PGA_ENA_MASK 0x0010 /* SPKOUTL_PGA_ENA */
+#define WM8962_SPKOUTL_PGA_ENA_SHIFT 4 /* SPKOUTL_PGA_ENA */
+#define WM8962_SPKOUTL_PGA_ENA_WIDTH 1 /* SPKOUTL_PGA_ENA */
+#define WM8962_SPKOUTR_PGA_ENA 0x0008 /* SPKOUTR_PGA_ENA */
+#define WM8962_SPKOUTR_PGA_ENA_MASK 0x0008 /* SPKOUTR_PGA_ENA */
+#define WM8962_SPKOUTR_PGA_ENA_SHIFT 3 /* SPKOUTR_PGA_ENA */
+#define WM8962_SPKOUTR_PGA_ENA_WIDTH 1 /* SPKOUTR_PGA_ENA */
+#define WM8962_HPOUTL_PGA_MUTE 0x0002 /* HPOUTL_PGA_MUTE */
+#define WM8962_HPOUTL_PGA_MUTE_MASK 0x0002 /* HPOUTL_PGA_MUTE */
+#define WM8962_HPOUTL_PGA_MUTE_SHIFT 1 /* HPOUTL_PGA_MUTE */
+#define WM8962_HPOUTL_PGA_MUTE_WIDTH 1 /* HPOUTL_PGA_MUTE */
+#define WM8962_HPOUTR_PGA_MUTE 0x0001 /* HPOUTR_PGA_MUTE */
+#define WM8962_HPOUTR_PGA_MUTE_MASK 0x0001 /* HPOUTR_PGA_MUTE */
+#define WM8962_HPOUTR_PGA_MUTE_SHIFT 0 /* HPOUTR_PGA_MUTE */
+#define WM8962_HPOUTR_PGA_MUTE_WIDTH 1 /* HPOUTR_PGA_MUTE */
+
+/*
+ * R27 (0x1B) - Additional Control (3)
+ */
+#define WM8962_SAMPLE_RATE_INT_MODE 0x0010 /* SAMPLE_RATE_INT_MODE */
+#define WM8962_SAMPLE_RATE_INT_MODE_MASK 0x0010 /* SAMPLE_RATE_INT_MODE */
+#define WM8962_SAMPLE_RATE_INT_MODE_SHIFT 4 /* SAMPLE_RATE_INT_MODE */
+#define WM8962_SAMPLE_RATE_INT_MODE_WIDTH 1 /* SAMPLE_RATE_INT_MODE */
+#define WM8962_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */
+#define WM8962_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */
+#define WM8962_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */
+
+/*
+ * R28 (0x1C) - Anti-pop
+ */
+#define WM8962_STARTUP_BIAS_ENA 0x0010 /* STARTUP_BIAS_ENA */
+#define WM8962_STARTUP_BIAS_ENA_MASK 0x0010 /* STARTUP_BIAS_ENA */
+#define WM8962_STARTUP_BIAS_ENA_SHIFT 4 /* STARTUP_BIAS_ENA */
+#define WM8962_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
+#define WM8962_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */
+#define WM8962_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */
+#define WM8962_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */
+#define WM8962_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
+#define WM8962_VMID_RAMP 0x0004 /* VMID_RAMP */
+#define WM8962_VMID_RAMP_MASK 0x0004 /* VMID_RAMP */
+#define WM8962_VMID_RAMP_SHIFT 2 /* VMID_RAMP */
+#define WM8962_VMID_RAMP_WIDTH 1 /* VMID_RAMP */
+
+/*
+ * R30 (0x1E) - Clocking 3
+ */
+#define WM8962_DBCLK_DIV_MASK 0xE000 /* DBCLK_DIV - [15:13] */
+#define WM8962_DBCLK_DIV_SHIFT 13 /* DBCLK_DIV - [15:13] */
+#define WM8962_DBCLK_DIV_WIDTH 3 /* DBCLK_DIV - [15:13] */
+#define WM8962_OPCLK_DIV_MASK 0x1C00 /* OPCLK_DIV - [12:10] */
+#define WM8962_OPCLK_DIV_SHIFT 10 /* OPCLK_DIV - [12:10] */
+#define WM8962_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [12:10] */
+#define WM8962_TOCLK_DIV_MASK 0x0380 /* TOCLK_DIV - [9:7] */
+#define WM8962_TOCLK_DIV_SHIFT 7 /* TOCLK_DIV - [9:7] */
+#define WM8962_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [9:7] */
+#define WM8962_F256KCLK_DIV_MASK 0x007E /* F256KCLK_DIV - [6:1] */
+#define WM8962_F256KCLK_DIV_SHIFT 1 /* F256KCLK_DIV - [6:1] */
+#define WM8962_F256KCLK_DIV_WIDTH 6 /* F256KCLK_DIV - [6:1] */
+
+/*
+ * R31 (0x1F) - Input mixer control (1)
+ */
+#define WM8962_MIXINL_MUTE 0x0008 /* MIXINL_MUTE */
+#define WM8962_MIXINL_MUTE_MASK 0x0008 /* MIXINL_MUTE */
+#define WM8962_MIXINL_MUTE_SHIFT 3 /* MIXINL_MUTE */
+#define WM8962_MIXINL_MUTE_WIDTH 1 /* MIXINL_MUTE */
+#define WM8962_MIXINR_MUTE 0x0004 /* MIXINR_MUTE */
+#define WM8962_MIXINR_MUTE_MASK 0x0004 /* MIXINR_MUTE */
+#define WM8962_MIXINR_MUTE_SHIFT 2 /* MIXINR_MUTE */
+#define WM8962_MIXINR_MUTE_WIDTH 1 /* MIXINR_MUTE */
+#define WM8962_MIXINL_ENA 0x0002 /* MIXINL_ENA */
+#define WM8962_MIXINL_ENA_MASK 0x0002 /* MIXINL_ENA */
+#define WM8962_MIXINL_ENA_SHIFT 1 /* MIXINL_ENA */
+#define WM8962_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */
+#define WM8962_MIXINR_ENA 0x0001 /* MIXINR_ENA */
+#define WM8962_MIXINR_ENA_MASK 0x0001 /* MIXINR_ENA */
+#define WM8962_MIXINR_ENA_SHIFT 0 /* MIXINR_ENA */
+#define WM8962_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */
+
+/*
+ * R32 (0x20) - Left input mixer volume
+ */
+#define WM8962_IN2L_MIXINL_VOL_MASK 0x01C0 /* IN2L_MIXINL_VOL - [8:6] */
+#define WM8962_IN2L_MIXINL_VOL_SHIFT 6 /* IN2L_MIXINL_VOL - [8:6] */
+#define WM8962_IN2L_MIXINL_VOL_WIDTH 3 /* IN2L_MIXINL_VOL - [8:6] */
+#define WM8962_INPGAL_MIXINL_VOL_MASK 0x0038 /* INPGAL_MIXINL_VOL - [5:3] */
+#define WM8962_INPGAL_MIXINL_VOL_SHIFT 3 /* INPGAL_MIXINL_VOL - [5:3] */
+#define WM8962_INPGAL_MIXINL_VOL_WIDTH 3 /* INPGAL_MIXINL_VOL - [5:3] */
+#define WM8962_IN3L_MIXINL_VOL_MASK 0x0007 /* IN3L_MIXINL_VOL - [2:0] */
+#define WM8962_IN3L_MIXINL_VOL_SHIFT 0 /* IN3L_MIXINL_VOL - [2:0] */
+#define WM8962_IN3L_MIXINL_VOL_WIDTH 3 /* IN3L_MIXINL_VOL - [2:0] */
+
+/*
+ * R33 (0x21) - Right input mixer volume
+ */
+#define WM8962_IN2R_MIXINR_VOL_MASK 0x01C0 /* IN2R_MIXINR_VOL - [8:6] */
+#define WM8962_IN2R_MIXINR_VOL_SHIFT 6 /* IN2R_MIXINR_VOL - [8:6] */
+#define WM8962_IN2R_MIXINR_VOL_WIDTH 3 /* IN2R_MIXINR_VOL - [8:6] */
+#define WM8962_INPGAR_MIXINR_VOL_MASK 0x0038 /* INPGAR_MIXINR_VOL - [5:3] */
+#define WM8962_INPGAR_MIXINR_VOL_SHIFT 3 /* INPGAR_MIXINR_VOL - [5:3] */
+#define WM8962_INPGAR_MIXINR_VOL_WIDTH 3 /* INPGAR_MIXINR_VOL - [5:3] */
+#define WM8962_IN3R_MIXINR_VOL_MASK 0x0007 /* IN3R_MIXINR_VOL - [2:0] */
+#define WM8962_IN3R_MIXINR_VOL_SHIFT 0 /* IN3R_MIXINR_VOL - [2:0] */
+#define WM8962_IN3R_MIXINR_VOL_WIDTH 3 /* IN3R_MIXINR_VOL - [2:0] */
+
+/*
+ * R34 (0x22) - Input mixer control (2)
+ */
+#define WM8962_IN2L_TO_MIXINL 0x0020 /* IN2L_TO_MIXINL */
+#define WM8962_IN2L_TO_MIXINL_MASK 0x0020 /* IN2L_TO_MIXINL */
+#define WM8962_IN2L_TO_MIXINL_SHIFT 5 /* IN2L_TO_MIXINL */
+#define WM8962_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */
+#define WM8962_IN3L_TO_MIXINL 0x0010 /* IN3L_TO_MIXINL */
+#define WM8962_IN3L_TO_MIXINL_MASK 0x0010 /* IN3L_TO_MIXINL */
+#define WM8962_IN3L_TO_MIXINL_SHIFT 4 /* IN3L_TO_MIXINL */
+#define WM8962_IN3L_TO_MIXINL_WIDTH 1 /* IN3L_TO_MIXINL */
+#define WM8962_INPGAL_TO_MIXINL 0x0008 /* INPGAL_TO_MIXINL */
+#define WM8962_INPGAL_TO_MIXINL_MASK 0x0008 /* INPGAL_TO_MIXINL */
+#define WM8962_INPGAL_TO_MIXINL_SHIFT 3 /* INPGAL_TO_MIXINL */
+#define WM8962_INPGAL_TO_MIXINL_WIDTH 1 /* INPGAL_TO_MIXINL */
+#define WM8962_IN2R_TO_MIXINR 0x0004 /* IN2R_TO_MIXINR */
+#define WM8962_IN2R_TO_MIXINR_MASK 0x0004 /* IN2R_TO_MIXINR */
+#define WM8962_IN2R_TO_MIXINR_SHIFT 2 /* IN2R_TO_MIXINR */
+#define WM8962_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */
+#define WM8962_IN3R_TO_MIXINR 0x0002 /* IN3R_TO_MIXINR */
+#define WM8962_IN3R_TO_MIXINR_MASK 0x0002 /* IN3R_TO_MIXINR */
+#define WM8962_IN3R_TO_MIXINR_SHIFT 1 /* IN3R_TO_MIXINR */
+#define WM8962_IN3R_TO_MIXINR_WIDTH 1 /* IN3R_TO_MIXINR */
+#define WM8962_INPGAR_TO_MIXINR 0x0001 /* INPGAR_TO_MIXINR */
+#define WM8962_INPGAR_TO_MIXINR_MASK 0x0001 /* INPGAR_TO_MIXINR */
+#define WM8962_INPGAR_TO_MIXINR_SHIFT 0 /* INPGAR_TO_MIXINR */
+#define WM8962_INPGAR_TO_MIXINR_WIDTH 1 /* INPGAR_TO_MIXINR */
+
+/*
+ * R35 (0x23) - Input bias control
+ */
+#define WM8962_MIXIN_BIAS_MASK 0x0038 /* MIXIN_BIAS - [5:3] */
+#define WM8962_MIXIN_BIAS_SHIFT 3 /* MIXIN_BIAS - [5:3] */
+#define WM8962_MIXIN_BIAS_WIDTH 3 /* MIXIN_BIAS - [5:3] */
+#define WM8962_INPGA_BIAS_MASK 0x0007 /* INPGA_BIAS - [2:0] */
+#define WM8962_INPGA_BIAS_SHIFT 0 /* INPGA_BIAS - [2:0] */
+#define WM8962_INPGA_BIAS_WIDTH 3 /* INPGA_BIAS - [2:0] */
+
+/*
+ * R37 (0x25) - Left input PGA control
+ */
+#define WM8962_INPGAL_ENA 0x0010 /* INPGAL_ENA */
+#define WM8962_INPGAL_ENA_MASK 0x0010 /* INPGAL_ENA */
+#define WM8962_INPGAL_ENA_SHIFT 4 /* INPGAL_ENA */
+#define WM8962_INPGAL_ENA_WIDTH 1 /* INPGAL_ENA */
+#define WM8962_IN1L_TO_INPGAL 0x0008 /* IN1L_TO_INPGAL */
+#define WM8962_IN1L_TO_INPGAL_MASK 0x0008 /* IN1L_TO_INPGAL */
+#define WM8962_IN1L_TO_INPGAL_SHIFT 3 /* IN1L_TO_INPGAL */
+#define WM8962_IN1L_TO_INPGAL_WIDTH 1 /* IN1L_TO_INPGAL */
+#define WM8962_IN2L_TO_INPGAL 0x0004 /* IN2L_TO_INPGAL */
+#define WM8962_IN2L_TO_INPGAL_MASK 0x0004 /* IN2L_TO_INPGAL */
+#define WM8962_IN2L_TO_INPGAL_SHIFT 2 /* IN2L_TO_INPGAL */
+#define WM8962_IN2L_TO_INPGAL_WIDTH 1 /* IN2L_TO_INPGAL */
+#define WM8962_IN3L_TO_INPGAL 0x0002 /* IN3L_TO_INPGAL */
+#define WM8962_IN3L_TO_INPGAL_MASK 0x0002 /* IN3L_TO_INPGAL */
+#define WM8962_IN3L_TO_INPGAL_SHIFT 1 /* IN3L_TO_INPGAL */
+#define WM8962_IN3L_TO_INPGAL_WIDTH 1 /* IN3L_TO_INPGAL */
+#define WM8962_IN4L_TO_INPGAL 0x0001 /* IN4L_TO_INPGAL */
+#define WM8962_IN4L_TO_INPGAL_MASK 0x0001 /* IN4L_TO_INPGAL */
+#define WM8962_IN4L_TO_INPGAL_SHIFT 0 /* IN4L_TO_INPGAL */
+#define WM8962_IN4L_TO_INPGAL_WIDTH 1 /* IN4L_TO_INPGAL */
+
+/*
+ * R38 (0x26) - Right input PGA control
+ */
+#define WM8962_INPGAR_ENA 0x0010 /* INPGAR_ENA */
+#define WM8962_INPGAR_ENA_MASK 0x0010 /* INPGAR_ENA */
+#define WM8962_INPGAR_ENA_SHIFT 4 /* INPGAR_ENA */
+#define WM8962_INPGAR_ENA_WIDTH 1 /* INPGAR_ENA */
+#define WM8962_IN1R_TO_INPGAR 0x0008 /* IN1R_TO_INPGAR */
+#define WM8962_IN1R_TO_INPGAR_MASK 0x0008 /* IN1R_TO_INPGAR */
+#define WM8962_IN1R_TO_INPGAR_SHIFT 3 /* IN1R_TO_INPGAR */
+#define WM8962_IN1R_TO_INPGAR_WIDTH 1 /* IN1R_TO_INPGAR */
+#define WM8962_IN2R_TO_INPGAR 0x0004 /* IN2R_TO_INPGAR */
+#define WM8962_IN2R_TO_INPGAR_MASK 0x0004 /* IN2R_TO_INPGAR */
+#define WM8962_IN2R_TO_INPGAR_SHIFT 2 /* IN2R_TO_INPGAR */
+#define WM8962_IN2R_TO_INPGAR_WIDTH 1 /* IN2R_TO_INPGAR */
+#define WM8962_IN3R_TO_INPGAR 0x0002 /* IN3R_TO_INPGAR */
+#define WM8962_IN3R_TO_INPGAR_MASK 0x0002 /* IN3R_TO_INPGAR */
+#define WM8962_IN3R_TO_INPGAR_SHIFT 1 /* IN3R_TO_INPGAR */
+#define WM8962_IN3R_TO_INPGAR_WIDTH 1 /* IN3R_TO_INPGAR */
+#define WM8962_IN4R_TO_INPGAR 0x0001 /* IN4R_TO_INPGAR */
+#define WM8962_IN4R_TO_INPGAR_MASK 0x0001 /* IN4R_TO_INPGAR */
+#define WM8962_IN4R_TO_INPGAR_SHIFT 0 /* IN4R_TO_INPGAR */
+#define WM8962_IN4R_TO_INPGAR_WIDTH 1 /* IN4R_TO_INPGAR */
+
+/*
+ * R40 (0x28) - SPKOUTL volume
+ */
+#define WM8962_SPKOUT_VU 0x0100 /* SPKOUT_VU */
+#define WM8962_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
+#define WM8962_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
+#define WM8962_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
+#define WM8962_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */
+#define WM8962_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */
+#define WM8962_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */
+#define WM8962_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */
+#define WM8962_SPKOUTL_VOL_MASK 0x007F /* SPKOUTL_VOL - [6:0] */
+#define WM8962_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [6:0] */
+#define WM8962_SPKOUTL_VOL_WIDTH 7 /* SPKOUTL_VOL - [6:0] */
+
+/*
+ * R41 (0x29) - SPKOUTR volume
+ */
+#define WM8962_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */
+#define WM8962_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */
+#define WM8962_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */
+#define WM8962_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */
+#define WM8962_SPKOUTR_VOL_MASK 0x007F /* SPKOUTR_VOL - [6:0] */
+#define WM8962_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [6:0] */
+#define WM8962_SPKOUTR_VOL_WIDTH 7 /* SPKOUTR_VOL - [6:0] */
+
+/*
+ * R47 (0x2F) - Thermal Shutdown Status
+ */
+#define WM8962_TEMP_ERR_HP 0x0008 /* TEMP_ERR_HP */
+#define WM8962_TEMP_ERR_HP_MASK 0x0008 /* TEMP_ERR_HP */
+#define WM8962_TEMP_ERR_HP_SHIFT 3 /* TEMP_ERR_HP */
+#define WM8962_TEMP_ERR_HP_WIDTH 1 /* TEMP_ERR_HP */
+#define WM8962_TEMP_WARN_HP 0x0004 /* TEMP_WARN_HP */
+#define WM8962_TEMP_WARN_HP_MASK 0x0004 /* TEMP_WARN_HP */
+#define WM8962_TEMP_WARN_HP_SHIFT 2 /* TEMP_WARN_HP */
+#define WM8962_TEMP_WARN_HP_WIDTH 1 /* TEMP_WARN_HP */
+#define WM8962_TEMP_ERR_SPK 0x0002 /* TEMP_ERR_SPK */
+#define WM8962_TEMP_ERR_SPK_MASK 0x0002 /* TEMP_ERR_SPK */
+#define WM8962_TEMP_ERR_SPK_SHIFT 1 /* TEMP_ERR_SPK */
+#define WM8962_TEMP_ERR_SPK_WIDTH 1 /* TEMP_ERR_SPK */
+#define WM8962_TEMP_WARN_SPK 0x0001 /* TEMP_WARN_SPK */
+#define WM8962_TEMP_WARN_SPK_MASK 0x0001 /* TEMP_WARN_SPK */
+#define WM8962_TEMP_WARN_SPK_SHIFT 0 /* TEMP_WARN_SPK */
+#define WM8962_TEMP_WARN_SPK_WIDTH 1 /* TEMP_WARN_SPK */
+
+/*
+ * R48 (0x30) - Additional Control (4)
+ */
+#define WM8962_MICDET_THR_MASK 0x7000 /* MICDET_THR - [14:12] */
+#define WM8962_MICDET_THR_SHIFT 12 /* MICDET_THR - [14:12] */
+#define WM8962_MICDET_THR_WIDTH 3 /* MICDET_THR - [14:12] */
+#define WM8962_MICSHORT_THR_MASK 0x0C00 /* MICSHORT_THR - [11:10] */
+#define WM8962_MICSHORT_THR_SHIFT 10 /* MICSHORT_THR - [11:10] */
+#define WM8962_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [11:10] */
+#define WM8962_MICDET_ENA 0x0200 /* MICDET_ENA */
+#define WM8962_MICDET_ENA_MASK 0x0200 /* MICDET_ENA */
+#define WM8962_MICDET_ENA_SHIFT 9 /* MICDET_ENA */
+#define WM8962_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
+#define WM8962_MICDET_STS 0x0080 /* MICDET_STS */
+#define WM8962_MICDET_STS_MASK 0x0080 /* MICDET_STS */
+#define WM8962_MICDET_STS_SHIFT 7 /* MICDET_STS */
+#define WM8962_MICDET_STS_WIDTH 1 /* MICDET_STS */
+#define WM8962_MICSHORT_STS 0x0040 /* MICSHORT_STS */
+#define WM8962_MICSHORT_STS_MASK 0x0040 /* MICSHORT_STS */
+#define WM8962_MICSHORT_STS_SHIFT 6 /* MICSHORT_STS */
+#define WM8962_MICSHORT_STS_WIDTH 1 /* MICSHORT_STS */
+#define WM8962_TEMP_ENA_HP 0x0004 /* TEMP_ENA_HP */
+#define WM8962_TEMP_ENA_HP_MASK 0x0004 /* TEMP_ENA_HP */
+#define WM8962_TEMP_ENA_HP_SHIFT 2 /* TEMP_ENA_HP */
+#define WM8962_TEMP_ENA_HP_WIDTH 1 /* TEMP_ENA_HP */
+#define WM8962_TEMP_ENA_SPK 0x0002 /* TEMP_ENA_SPK */
+#define WM8962_TEMP_ENA_SPK_MASK 0x0002 /* TEMP_ENA_SPK */
+#define WM8962_TEMP_ENA_SPK_SHIFT 1 /* TEMP_ENA_SPK */
+#define WM8962_TEMP_ENA_SPK_WIDTH 1 /* TEMP_ENA_SPK */
+#define WM8962_MICBIAS_LVL 0x0001 /* MICBIAS_LVL */
+#define WM8962_MICBIAS_LVL_MASK 0x0001 /* MICBIAS_LVL */
+#define WM8962_MICBIAS_LVL_SHIFT 0 /* MICBIAS_LVL */
+#define WM8962_MICBIAS_LVL_WIDTH 1 /* MICBIAS_LVL */
+
+/*
+ * R49 (0x31) - Class D Control 1
+ */
+#define WM8962_SPKOUTR_ENA 0x0080 /* SPKOUTR_ENA */
+#define WM8962_SPKOUTR_ENA_MASK 0x0080 /* SPKOUTR_ENA */
+#define WM8962_SPKOUTR_ENA_SHIFT 7 /* SPKOUTR_ENA */
+#define WM8962_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */
+#define WM8962_SPKOUTL_ENA 0x0040 /* SPKOUTL_ENA */
+#define WM8962_SPKOUTL_ENA_MASK 0x0040 /* SPKOUTL_ENA */
+#define WM8962_SPKOUTL_ENA_SHIFT 6 /* SPKOUTL_ENA */
+#define WM8962_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */
+#define WM8962_SPKOUTL_PGA_MUTE 0x0002 /* SPKOUTL_PGA_MUTE */
+#define WM8962_SPKOUTL_PGA_MUTE_MASK 0x0002 /* SPKOUTL_PGA_MUTE */
+#define WM8962_SPKOUTL_PGA_MUTE_SHIFT 1 /* SPKOUTL_PGA_MUTE */
+#define WM8962_SPKOUTL_PGA_MUTE_WIDTH 1 /* SPKOUTL_PGA_MUTE */
+#define WM8962_SPKOUTR_PGA_MUTE 0x0001 /* SPKOUTR_PGA_MUTE */
+#define WM8962_SPKOUTR_PGA_MUTE_MASK 0x0001 /* SPKOUTR_PGA_MUTE */
+#define WM8962_SPKOUTR_PGA_MUTE_SHIFT 0 /* SPKOUTR_PGA_MUTE */
+#define WM8962_SPKOUTR_PGA_MUTE_WIDTH 1 /* SPKOUTR_PGA_MUTE */
+
+/*
+ * R51 (0x33) - Class D Control 2
+ */
+#define WM8962_SPK_MONO 0x0040 /* SPK_MONO */
+#define WM8962_SPK_MONO_MASK 0x0040 /* SPK_MONO */
+#define WM8962_SPK_MONO_SHIFT 6 /* SPK_MONO */
+#define WM8962_SPK_MONO_WIDTH 1 /* SPK_MONO */
+#define WM8962_CLASSD_VOL_MASK 0x0007 /* CLASSD_VOL - [2:0] */
+#define WM8962_CLASSD_VOL_SHIFT 0 /* CLASSD_VOL - [2:0] */
+#define WM8962_CLASSD_VOL_WIDTH 3 /* CLASSD_VOL - [2:0] */
+
+/*
+ * R56 (0x38) - Clocking 4
+ */
+#define WM8962_SYSCLK_RATE_MASK 0x001E /* SYSCLK_RATE - [4:1] */
+#define WM8962_SYSCLK_RATE_SHIFT 1 /* SYSCLK_RATE - [4:1] */
+#define WM8962_SYSCLK_RATE_WIDTH 4 /* SYSCLK_RATE - [4:1] */
+
+/*
+ * R57 (0x39) - DAC DSP Mixing (1)
+ */
+#define WM8962_DAC_MONOMIX 0x0200 /* DAC_MONOMIX */
+#define WM8962_DAC_MONOMIX_MASK 0x0200 /* DAC_MONOMIX */
+#define WM8962_DAC_MONOMIX_SHIFT 9 /* DAC_MONOMIX */
+#define WM8962_DAC_MONOMIX_WIDTH 1 /* DAC_MONOMIX */
+#define WM8962_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */
+#define WM8962_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */
+#define WM8962_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */
+#define WM8962_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */
+#define WM8962_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */
+#define WM8962_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */
+
+/*
+ * R58 (0x3A) - DAC DSP Mixing (2)
+ */
+#define WM8962_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */
+#define WM8962_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */
+#define WM8962_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */
+#define WM8962_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */
+#define WM8962_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */
+#define WM8962_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */
+
+/*
+ * R60 (0x3C) - DC Servo 0
+ */
+#define WM8962_INL_DCS_ENA 0x0080 /* INL_DCS_ENA */
+#define WM8962_INL_DCS_ENA_MASK 0x0080 /* INL_DCS_ENA */
+#define WM8962_INL_DCS_ENA_SHIFT 7 /* INL_DCS_ENA */
+#define WM8962_INL_DCS_ENA_WIDTH 1 /* INL_DCS_ENA */
+#define WM8962_INL_DCS_STARTUP 0x0040 /* INL_DCS_STARTUP */
+#define WM8962_INL_DCS_STARTUP_MASK 0x0040 /* INL_DCS_STARTUP */
+#define WM8962_INL_DCS_STARTUP_SHIFT 6 /* INL_DCS_STARTUP */
+#define WM8962_INL_DCS_STARTUP_WIDTH 1 /* INL_DCS_STARTUP */
+#define WM8962_INR_DCS_ENA 0x0008 /* INR_DCS_ENA */
+#define WM8962_INR_DCS_ENA_MASK 0x0008 /* INR_DCS_ENA */
+#define WM8962_INR_DCS_ENA_SHIFT 3 /* INR_DCS_ENA */
+#define WM8962_INR_DCS_ENA_WIDTH 1 /* INR_DCS_ENA */
+#define WM8962_INR_DCS_STARTUP 0x0004 /* INR_DCS_STARTUP */
+#define WM8962_INR_DCS_STARTUP_MASK 0x0004 /* INR_DCS_STARTUP */
+#define WM8962_INR_DCS_STARTUP_SHIFT 2 /* INR_DCS_STARTUP */
+#define WM8962_INR_DCS_STARTUP_WIDTH 1 /* INR_DCS_STARTUP */
+
+/*
+ * R61 (0x3D) - DC Servo 1
+ */
+#define WM8962_HP1L_DCS_ENA 0x0080 /* HP1L_DCS_ENA */
+#define WM8962_HP1L_DCS_ENA_MASK 0x0080 /* HP1L_DCS_ENA */
+#define WM8962_HP1L_DCS_ENA_SHIFT 7 /* HP1L_DCS_ENA */
+#define WM8962_HP1L_DCS_ENA_WIDTH 1 /* HP1L_DCS_ENA */
+#define WM8962_HP1L_DCS_STARTUP 0x0040 /* HP1L_DCS_STARTUP */
+#define WM8962_HP1L_DCS_STARTUP_MASK 0x0040 /* HP1L_DCS_STARTUP */
+#define WM8962_HP1L_DCS_STARTUP_SHIFT 6 /* HP1L_DCS_STARTUP */
+#define WM8962_HP1L_DCS_STARTUP_WIDTH 1 /* HP1L_DCS_STARTUP */
+#define WM8962_HP1L_DCS_SYNC 0x0010 /* HP1L_DCS_SYNC */
+#define WM8962_HP1L_DCS_SYNC_MASK 0x0010 /* HP1L_DCS_SYNC */
+#define WM8962_HP1L_DCS_SYNC_SHIFT 4 /* HP1L_DCS_SYNC */
+#define WM8962_HP1L_DCS_SYNC_WIDTH 1 /* HP1L_DCS_SYNC */
+#define WM8962_HP1R_DCS_ENA 0x0008 /* HP1R_DCS_ENA */
+#define WM8962_HP1R_DCS_ENA_MASK 0x0008 /* HP1R_DCS_ENA */
+#define WM8962_HP1R_DCS_ENA_SHIFT 3 /* HP1R_DCS_ENA */
+#define WM8962_HP1R_DCS_ENA_WIDTH 1 /* HP1R_DCS_ENA */
+#define WM8962_HP1R_DCS_STARTUP 0x0004 /* HP1R_DCS_STARTUP */
+#define WM8962_HP1R_DCS_STARTUP_MASK 0x0004 /* HP1R_DCS_STARTUP */
+#define WM8962_HP1R_DCS_STARTUP_SHIFT 2 /* HP1R_DCS_STARTUP */
+#define WM8962_HP1R_DCS_STARTUP_WIDTH 1 /* HP1R_DCS_STARTUP */
+#define WM8962_HP1R_DCS_SYNC 0x0001 /* HP1R_DCS_SYNC */
+#define WM8962_HP1R_DCS_SYNC_MASK 0x0001 /* HP1R_DCS_SYNC */
+#define WM8962_HP1R_DCS_SYNC_SHIFT 0 /* HP1R_DCS_SYNC */
+#define WM8962_HP1R_DCS_SYNC_WIDTH 1 /* HP1R_DCS_SYNC */
+
+/*
+ * R64 (0x40) - DC Servo 4
+ */
+#define WM8962_HP1_DCS_SYNC_STEPS_MASK 0x3F80 /* HP1_DCS_SYNC_STEPS - [13:7] */
+#define WM8962_HP1_DCS_SYNC_STEPS_SHIFT 7 /* HP1_DCS_SYNC_STEPS - [13:7] */
+#define WM8962_HP1_DCS_SYNC_STEPS_WIDTH 7 /* HP1_DCS_SYNC_STEPS - [13:7] */
+
+/*
+ * R66 (0x42) - DC Servo 6
+ */
+#define WM8962_DCS_STARTUP_DONE_INL 0x0400 /* DCS_STARTUP_DONE_INL */
+#define WM8962_DCS_STARTUP_DONE_INL_MASK 0x0400 /* DCS_STARTUP_DONE_INL */
+#define WM8962_DCS_STARTUP_DONE_INL_SHIFT 10 /* DCS_STARTUP_DONE_INL */
+#define WM8962_DCS_STARTUP_DONE_INL_WIDTH 1 /* DCS_STARTUP_DONE_INL */
+#define WM8962_DCS_STARTUP_DONE_INR 0x0200 /* DCS_STARTUP_DONE_INR */
+#define WM8962_DCS_STARTUP_DONE_INR_MASK 0x0200 /* DCS_STARTUP_DONE_INR */
+#define WM8962_DCS_STARTUP_DONE_INR_SHIFT 9 /* DCS_STARTUP_DONE_INR */
+#define WM8962_DCS_STARTUP_DONE_INR_WIDTH 1 /* DCS_STARTUP_DONE_INR */
+#define WM8962_DCS_STARTUP_DONE_HP1L 0x0100 /* DCS_STARTUP_DONE_HP1L */
+#define WM8962_DCS_STARTUP_DONE_HP1L_MASK 0x0100 /* DCS_STARTUP_DONE_HP1L */
+#define WM8962_DCS_STARTUP_DONE_HP1L_SHIFT 8 /* DCS_STARTUP_DONE_HP1L */
+#define WM8962_DCS_STARTUP_DONE_HP1L_WIDTH 1 /* DCS_STARTUP_DONE_HP1L */
+#define WM8962_DCS_STARTUP_DONE_HP1R 0x0080 /* DCS_STARTUP_DONE_HP1R */
+#define WM8962_DCS_STARTUP_DONE_HP1R_MASK 0x0080 /* DCS_STARTUP_DONE_HP1R */
+#define WM8962_DCS_STARTUP_DONE_HP1R_SHIFT 7 /* DCS_STARTUP_DONE_HP1R */
+#define WM8962_DCS_STARTUP_DONE_HP1R_WIDTH 1 /* DCS_STARTUP_DONE_HP1R */
+
+/*
+ * R68 (0x44) - Analogue PGA Bias
+ */
+#define WM8962_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */
+#define WM8962_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */
+#define WM8962_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */
+
+/*
+ * R69 (0x45) - Analogue HP 0
+ */
+#define WM8962_HP1L_RMV_SHORT 0x0080 /* HP1L_RMV_SHORT */
+#define WM8962_HP1L_RMV_SHORT_MASK 0x0080 /* HP1L_RMV_SHORT */
+#define WM8962_HP1L_RMV_SHORT_SHIFT 7 /* HP1L_RMV_SHORT */
+#define WM8962_HP1L_RMV_SHORT_WIDTH 1 /* HP1L_RMV_SHORT */
+#define WM8962_HP1L_ENA_OUTP 0x0040 /* HP1L_ENA_OUTP */
+#define WM8962_HP1L_ENA_OUTP_MASK 0x0040 /* HP1L_ENA_OUTP */
+#define WM8962_HP1L_ENA_OUTP_SHIFT 6 /* HP1L_ENA_OUTP */
+#define WM8962_HP1L_ENA_OUTP_WIDTH 1 /* HP1L_ENA_OUTP */
+#define WM8962_HP1L_ENA_DLY 0x0020 /* HP1L_ENA_DLY */
+#define WM8962_HP1L_ENA_DLY_MASK 0x0020 /* HP1L_ENA_DLY */
+#define WM8962_HP1L_ENA_DLY_SHIFT 5 /* HP1L_ENA_DLY */
+#define WM8962_HP1L_ENA_DLY_WIDTH 1 /* HP1L_ENA_DLY */
+#define WM8962_HP1L_ENA 0x0010 /* HP1L_ENA */
+#define WM8962_HP1L_ENA_MASK 0x0010 /* HP1L_ENA */
+#define WM8962_HP1L_ENA_SHIFT 4 /* HP1L_ENA */
+#define WM8962_HP1L_ENA_WIDTH 1 /* HP1L_ENA */
+#define WM8962_HP1R_RMV_SHORT 0x0008 /* HP1R_RMV_SHORT */
+#define WM8962_HP1R_RMV_SHORT_MASK 0x0008 /* HP1R_RMV_SHORT */
+#define WM8962_HP1R_RMV_SHORT_SHIFT 3 /* HP1R_RMV_SHORT */
+#define WM8962_HP1R_RMV_SHORT_WIDTH 1 /* HP1R_RMV_SHORT */
+#define WM8962_HP1R_ENA_OUTP 0x0004 /* HP1R_ENA_OUTP */
+#define WM8962_HP1R_ENA_OUTP_MASK 0x0004 /* HP1R_ENA_OUTP */
+#define WM8962_HP1R_ENA_OUTP_SHIFT 2 /* HP1R_ENA_OUTP */
+#define WM8962_HP1R_ENA_OUTP_WIDTH 1 /* HP1R_ENA_OUTP */
+#define WM8962_HP1R_ENA_DLY 0x0002 /* HP1R_ENA_DLY */
+#define WM8962_HP1R_ENA_DLY_MASK 0x0002 /* HP1R_ENA_DLY */
+#define WM8962_HP1R_ENA_DLY_SHIFT 1 /* HP1R_ENA_DLY */
+#define WM8962_HP1R_ENA_DLY_WIDTH 1 /* HP1R_ENA_DLY */
+#define WM8962_HP1R_ENA 0x0001 /* HP1R_ENA */
+#define WM8962_HP1R_ENA_MASK 0x0001 /* HP1R_ENA */
+#define WM8962_HP1R_ENA_SHIFT 0 /* HP1R_ENA */
+#define WM8962_HP1R_ENA_WIDTH 1 /* HP1R_ENA */
+
+/*
+ * R71 (0x47) - Analogue HP 2
+ */
+#define WM8962_HP1L_VOL_MASK 0x01C0 /* HP1L_VOL - [8:6] */
+#define WM8962_HP1L_VOL_SHIFT 6 /* HP1L_VOL - [8:6] */
+#define WM8962_HP1L_VOL_WIDTH 3 /* HP1L_VOL - [8:6] */
+#define WM8962_HP1R_VOL_MASK 0x0038 /* HP1R_VOL - [5:3] */
+#define WM8962_HP1R_VOL_SHIFT 3 /* HP1R_VOL - [5:3] */
+#define WM8962_HP1R_VOL_WIDTH 3 /* HP1R_VOL - [5:3] */
+#define WM8962_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */
+#define WM8962_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */
+#define WM8962_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */
+
+/*
+ * R72 (0x48) - Charge Pump 1
+ */
+#define WM8962_CP_ENA 0x0001 /* CP_ENA */
+#define WM8962_CP_ENA_MASK 0x0001 /* CP_ENA */
+#define WM8962_CP_ENA_SHIFT 0 /* CP_ENA */
+#define WM8962_CP_ENA_WIDTH 1 /* CP_ENA */
+
+/*
+ * R82 (0x52) - Charge Pump B
+ */
+#define WM8962_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */
+#define WM8962_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */
+#define WM8962_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */
+#define WM8962_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */
+
+/*
+ * R87 (0x57) - Write Sequencer Control 1
+ */
+#define WM8962_WSEQ_AUTOSEQ_ENA 0x0080 /* WSEQ_AUTOSEQ_ENA */
+#define WM8962_WSEQ_AUTOSEQ_ENA_MASK 0x0080 /* WSEQ_AUTOSEQ_ENA */
+#define WM8962_WSEQ_AUTOSEQ_ENA_SHIFT 7 /* WSEQ_AUTOSEQ_ENA */
+#define WM8962_WSEQ_AUTOSEQ_ENA_WIDTH 1 /* WSEQ_AUTOSEQ_ENA */
+#define WM8962_WSEQ_ENA 0x0020 /* WSEQ_ENA */
+#define WM8962_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */
+#define WM8962_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */
+#define WM8962_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
+
+/*
+ * R90 (0x5A) - Write Sequencer Control 2
+ */
+#define WM8962_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */
+#define WM8962_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */
+#define WM8962_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */
+#define WM8962_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
+#define WM8962_WSEQ_START 0x0080 /* WSEQ_START */
+#define WM8962_WSEQ_START_MASK 0x0080 /* WSEQ_START */
+#define WM8962_WSEQ_START_SHIFT 7 /* WSEQ_START */
+#define WM8962_WSEQ_START_WIDTH 1 /* WSEQ_START */
+#define WM8962_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */
+#define WM8962_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */
+#define WM8962_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */
+
+/*
+ * R93 (0x5D) - Write Sequencer Control 3
+ */
+#define WM8962_WSEQ_CURRENT_INDEX_MASK 0x03F8 /* WSEQ_CURRENT_INDEX - [9:3] */
+#define WM8962_WSEQ_CURRENT_INDEX_SHIFT 3 /* WSEQ_CURRENT_INDEX - [9:3] */
+#define WM8962_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [9:3] */
+#define WM8962_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
+#define WM8962_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
+#define WM8962_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
+#define WM8962_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
+
+/*
+ * R94 (0x5E) - Control Interface
+ */
+#define WM8962_SPI_CONTRD 0x0040 /* SPI_CONTRD */
+#define WM8962_SPI_CONTRD_MASK 0x0040 /* SPI_CONTRD */
+#define WM8962_SPI_CONTRD_SHIFT 6 /* SPI_CONTRD */
+#define WM8962_SPI_CONTRD_WIDTH 1 /* SPI_CONTRD */
+#define WM8962_SPI_4WIRE 0x0020 /* SPI_4WIRE */
+#define WM8962_SPI_4WIRE_MASK 0x0020 /* SPI_4WIRE */
+#define WM8962_SPI_4WIRE_SHIFT 5 /* SPI_4WIRE */
+#define WM8962_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */
+#define WM8962_SPI_CFG 0x0010 /* SPI_CFG */
+#define WM8962_SPI_CFG_MASK 0x0010 /* SPI_CFG */
+#define WM8962_SPI_CFG_SHIFT 4 /* SPI_CFG */
+#define WM8962_SPI_CFG_WIDTH 1 /* SPI_CFG */
+
+/*
+ * R99 (0x63) - Mixer Enables
+ */
+#define WM8962_HPMIXL_ENA 0x0008 /* HPMIXL_ENA */
+#define WM8962_HPMIXL_ENA_MASK 0x0008 /* HPMIXL_ENA */
+#define WM8962_HPMIXL_ENA_SHIFT 3 /* HPMIXL_ENA */
+#define WM8962_HPMIXL_ENA_WIDTH 1 /* HPMIXL_ENA */
+#define WM8962_HPMIXR_ENA 0x0004 /* HPMIXR_ENA */
+#define WM8962_HPMIXR_ENA_MASK 0x0004 /* HPMIXR_ENA */
+#define WM8962_HPMIXR_ENA_SHIFT 2 /* HPMIXR_ENA */
+#define WM8962_HPMIXR_ENA_WIDTH 1 /* HPMIXR_ENA */
+#define WM8962_SPKMIXL_ENA 0x0002 /* SPKMIXL_ENA */
+#define WM8962_SPKMIXL_ENA_MASK 0x0002 /* SPKMIXL_ENA */
+#define WM8962_SPKMIXL_ENA_SHIFT 1 /* SPKMIXL_ENA */
+#define WM8962_SPKMIXL_ENA_WIDTH 1 /* SPKMIXL_ENA */
+#define WM8962_SPKMIXR_ENA 0x0001 /* SPKMIXR_ENA */
+#define WM8962_SPKMIXR_ENA_MASK 0x0001 /* SPKMIXR_ENA */
+#define WM8962_SPKMIXR_ENA_SHIFT 0 /* SPKMIXR_ENA */
+#define WM8962_SPKMIXR_ENA_WIDTH 1 /* SPKMIXR_ENA */
+
+/*
+ * R100 (0x64) - Headphone Mixer (1)
+ */
+#define WM8962_HPMIXL_TO_HPOUTL_PGA 0x0080 /* HPMIXL_TO_HPOUTL_PGA */
+#define WM8962_HPMIXL_TO_HPOUTL_PGA_MASK 0x0080 /* HPMIXL_TO_HPOUTL_PGA */
+#define WM8962_HPMIXL_TO_HPOUTL_PGA_SHIFT 7 /* HPMIXL_TO_HPOUTL_PGA */
+#define WM8962_HPMIXL_TO_HPOUTL_PGA_WIDTH 1 /* HPMIXL_TO_HPOUTL_PGA */
+#define WM8962_DACL_TO_HPMIXL 0x0020 /* DACL_TO_HPMIXL */
+#define WM8962_DACL_TO_HPMIXL_MASK 0x0020 /* DACL_TO_HPMIXL */
+#define WM8962_DACL_TO_HPMIXL_SHIFT 5 /* DACL_TO_HPMIXL */
+#define WM8962_DACL_TO_HPMIXL_WIDTH 1 /* DACL_TO_HPMIXL */
+#define WM8962_DACR_TO_HPMIXL 0x0010 /* DACR_TO_HPMIXL */
+#define WM8962_DACR_TO_HPMIXL_MASK 0x0010 /* DACR_TO_HPMIXL */
+#define WM8962_DACR_TO_HPMIXL_SHIFT 4 /* DACR_TO_HPMIXL */
+#define WM8962_DACR_TO_HPMIXL_WIDTH 1 /* DACR_TO_HPMIXL */
+#define WM8962_MIXINL_TO_HPMIXL 0x0008 /* MIXINL_TO_HPMIXL */
+#define WM8962_MIXINL_TO_HPMIXL_MASK 0x0008 /* MIXINL_TO_HPMIXL */
+#define WM8962_MIXINL_TO_HPMIXL_SHIFT 3 /* MIXINL_TO_HPMIXL */
+#define WM8962_MIXINL_TO_HPMIXL_WIDTH 1 /* MIXINL_TO_HPMIXL */
+#define WM8962_MIXINR_TO_HPMIXL 0x0004 /* MIXINR_TO_HPMIXL */
+#define WM8962_MIXINR_TO_HPMIXL_MASK 0x0004 /* MIXINR_TO_HPMIXL */
+#define WM8962_MIXINR_TO_HPMIXL_SHIFT 2 /* MIXINR_TO_HPMIXL */
+#define WM8962_MIXINR_TO_HPMIXL_WIDTH 1 /* MIXINR_TO_HPMIXL */
+#define WM8962_IN4L_TO_HPMIXL 0x0002 /* IN4L_TO_HPMIXL */
+#define WM8962_IN4L_TO_HPMIXL_MASK 0x0002 /* IN4L_TO_HPMIXL */
+#define WM8962_IN4L_TO_HPMIXL_SHIFT 1 /* IN4L_TO_HPMIXL */
+#define WM8962_IN4L_TO_HPMIXL_WIDTH 1 /* IN4L_TO_HPMIXL */
+#define WM8962_IN4R_TO_HPMIXL 0x0001 /* IN4R_TO_HPMIXL */
+#define WM8962_IN4R_TO_HPMIXL_MASK 0x0001 /* IN4R_TO_HPMIXL */
+#define WM8962_IN4R_TO_HPMIXL_SHIFT 0 /* IN4R_TO_HPMIXL */
+#define WM8962_IN4R_TO_HPMIXL_WIDTH 1 /* IN4R_TO_HPMIXL */
+
+/*
+ * R101 (0x65) - Headphone Mixer (2)
+ */
+#define WM8962_HPMIXR_TO_HPOUTR_PGA 0x0080 /* HPMIXR_TO_HPOUTR_PGA */
+#define WM8962_HPMIXR_TO_HPOUTR_PGA_MASK 0x0080 /* HPMIXR_TO_HPOUTR_PGA */
+#define WM8962_HPMIXR_TO_HPOUTR_PGA_SHIFT 7 /* HPMIXR_TO_HPOUTR_PGA */
+#define WM8962_HPMIXR_TO_HPOUTR_PGA_WIDTH 1 /* HPMIXR_TO_HPOUTR_PGA */
+#define WM8962_DACL_TO_HPMIXR 0x0020 /* DACL_TO_HPMIXR */
+#define WM8962_DACL_TO_HPMIXR_MASK 0x0020 /* DACL_TO_HPMIXR */
+#define WM8962_DACL_TO_HPMIXR_SHIFT 5 /* DACL_TO_HPMIXR */
+#define WM8962_DACL_TO_HPMIXR_WIDTH 1 /* DACL_TO_HPMIXR */
+#define WM8962_DACR_TO_HPMIXR 0x0010 /* DACR_TO_HPMIXR */
+#define WM8962_DACR_TO_HPMIXR_MASK 0x0010 /* DACR_TO_HPMIXR */
+#define WM8962_DACR_TO_HPMIXR_SHIFT 4 /* DACR_TO_HPMIXR */
+#define WM8962_DACR_TO_HPMIXR_WIDTH 1 /* DACR_TO_HPMIXR */
+#define WM8962_MIXINL_TO_HPMIXR 0x0008 /* MIXINL_TO_HPMIXR */
+#define WM8962_MIXINL_TO_HPMIXR_MASK 0x0008 /* MIXINL_TO_HPMIXR */
+#define WM8962_MIXINL_TO_HPMIXR_SHIFT 3 /* MIXINL_TO_HPMIXR */
+#define WM8962_MIXINL_TO_HPMIXR_WIDTH 1 /* MIXINL_TO_HPMIXR */
+#define WM8962_MIXINR_TO_HPMIXR 0x0004 /* MIXINR_TO_HPMIXR */
+#define WM8962_MIXINR_TO_HPMIXR_MASK 0x0004 /* MIXINR_TO_HPMIXR */
+#define WM8962_MIXINR_TO_HPMIXR_SHIFT 2 /* MIXINR_TO_HPMIXR */
+#define WM8962_MIXINR_TO_HPMIXR_WIDTH 1 /* MIXINR_TO_HPMIXR */
+#define WM8962_IN4L_TO_HPMIXR 0x0002 /* IN4L_TO_HPMIXR */
+#define WM8962_IN4L_TO_HPMIXR_MASK 0x0002 /* IN4L_TO_HPMIXR */
+#define WM8962_IN4L_TO_HPMIXR_SHIFT 1 /* IN4L_TO_HPMIXR */
+#define WM8962_IN4L_TO_HPMIXR_WIDTH 1 /* IN4L_TO_HPMIXR */
+#define WM8962_IN4R_TO_HPMIXR 0x0001 /* IN4R_TO_HPMIXR */
+#define WM8962_IN4R_TO_HPMIXR_MASK 0x0001 /* IN4R_TO_HPMIXR */
+#define WM8962_IN4R_TO_HPMIXR_SHIFT 0 /* IN4R_TO_HPMIXR */
+#define WM8962_IN4R_TO_HPMIXR_WIDTH 1 /* IN4R_TO_HPMIXR */
+
+/*
+ * R102 (0x66) - Headphone Mixer (3)
+ */
+#define WM8962_HPMIXL_MUTE 0x0100 /* HPMIXL_MUTE */
+#define WM8962_HPMIXL_MUTE_MASK 0x0100 /* HPMIXL_MUTE */
+#define WM8962_HPMIXL_MUTE_SHIFT 8 /* HPMIXL_MUTE */
+#define WM8962_HPMIXL_MUTE_WIDTH 1 /* HPMIXL_MUTE */
+#define WM8962_MIXINL_HPMIXL_VOL 0x0080 /* MIXINL_HPMIXL_VOL */
+#define WM8962_MIXINL_HPMIXL_VOL_MASK 0x0080 /* MIXINL_HPMIXL_VOL */
+#define WM8962_MIXINL_HPMIXL_VOL_SHIFT 7 /* MIXINL_HPMIXL_VOL */
+#define WM8962_MIXINL_HPMIXL_VOL_WIDTH 1 /* MIXINL_HPMIXL_VOL */
+#define WM8962_MIXINR_HPMIXL_VOL 0x0040 /* MIXINR_HPMIXL_VOL */
+#define WM8962_MIXINR_HPMIXL_VOL_MASK 0x0040 /* MIXINR_HPMIXL_VOL */
+#define WM8962_MIXINR_HPMIXL_VOL_SHIFT 6 /* MIXINR_HPMIXL_VOL */
+#define WM8962_MIXINR_HPMIXL_VOL_WIDTH 1 /* MIXINR_HPMIXL_VOL */
+#define WM8962_IN4L_HPMIXL_VOL_MASK 0x0038 /* IN4L_HPMIXL_VOL - [5:3] */
+#define WM8962_IN4L_HPMIXL_VOL_SHIFT 3 /* IN4L_HPMIXL_VOL - [5:3] */
+#define WM8962_IN4L_HPMIXL_VOL_WIDTH 3 /* IN4L_HPMIXL_VOL - [5:3] */
+#define WM8962_IN4R_HPMIXL_VOL_MASK 0x0007 /* IN4R_HPMIXL_VOL - [2:0] */
+#define WM8962_IN4R_HPMIXL_VOL_SHIFT 0 /* IN4R_HPMIXL_VOL - [2:0] */
+#define WM8962_IN4R_HPMIXL_VOL_WIDTH 3 /* IN4R_HPMIXL_VOL - [2:0] */
+
+/*
+ * R103 (0x67) - Headphone Mixer (4)
+ */
+#define WM8962_HPMIXR_MUTE 0x0100 /* HPMIXR_MUTE */
+#define WM8962_HPMIXR_MUTE_MASK 0x0100 /* HPMIXR_MUTE */
+#define WM8962_HPMIXR_MUTE_SHIFT 8 /* HPMIXR_MUTE */
+#define WM8962_HPMIXR_MUTE_WIDTH 1 /* HPMIXR_MUTE */
+#define WM8962_MIXINL_HPMIXR_VOL 0x0080 /* MIXINL_HPMIXR_VOL */
+#define WM8962_MIXINL_HPMIXR_VOL_MASK 0x0080 /* MIXINL_HPMIXR_VOL */
+#define WM8962_MIXINL_HPMIXR_VOL_SHIFT 7 /* MIXINL_HPMIXR_VOL */
+#define WM8962_MIXINL_HPMIXR_VOL_WIDTH 1 /* MIXINL_HPMIXR_VOL */
+#define WM8962_MIXINR_HPMIXR_VOL 0x0040 /* MIXINR_HPMIXR_VOL */
+#define WM8962_MIXINR_HPMIXR_VOL_MASK 0x0040 /* MIXINR_HPMIXR_VOL */
+#define WM8962_MIXINR_HPMIXR_VOL_SHIFT 6 /* MIXINR_HPMIXR_VOL */
+#define WM8962_MIXINR_HPMIXR_VOL_WIDTH 1 /* MIXINR_HPMIXR_VOL */
+#define WM8962_IN4L_HPMIXR_VOL_MASK 0x0038 /* IN4L_HPMIXR_VOL - [5:3] */
+#define WM8962_IN4L_HPMIXR_VOL_SHIFT 3 /* IN4L_HPMIXR_VOL - [5:3] */
+#define WM8962_IN4L_HPMIXR_VOL_WIDTH 3 /* IN4L_HPMIXR_VOL - [5:3] */
+#define WM8962_IN4R_HPMIXR_VOL_MASK 0x0007 /* IN4R_HPMIXR_VOL - [2:0] */
+#define WM8962_IN4R_HPMIXR_VOL_SHIFT 0 /* IN4R_HPMIXR_VOL - [2:0] */
+#define WM8962_IN4R_HPMIXR_VOL_WIDTH 3 /* IN4R_HPMIXR_VOL - [2:0] */
+
+/*
+ * R105 (0x69) - Speaker Mixer (1)
+ */
+#define WM8962_SPKMIXL_TO_SPKOUTL_PGA 0x0080 /* SPKMIXL_TO_SPKOUTL_PGA */
+#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_MASK 0x0080 /* SPKMIXL_TO_SPKOUTL_PGA */
+#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_SHIFT 7 /* SPKMIXL_TO_SPKOUTL_PGA */
+#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_WIDTH 1 /* SPKMIXL_TO_SPKOUTL_PGA */
+#define WM8962_DACL_TO_SPKMIXL 0x0020 /* DACL_TO_SPKMIXL */
+#define WM8962_DACL_TO_SPKMIXL_MASK 0x0020 /* DACL_TO_SPKMIXL */
+#define WM8962_DACL_TO_SPKMIXL_SHIFT 5 /* DACL_TO_SPKMIXL */
+#define WM8962_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */
+#define WM8962_DACR_TO_SPKMIXL 0x0010 /* DACR_TO_SPKMIXL */
+#define WM8962_DACR_TO_SPKMIXL_MASK 0x0010 /* DACR_TO_SPKMIXL */
+#define WM8962_DACR_TO_SPKMIXL_SHIFT 4 /* DACR_TO_SPKMIXL */
+#define WM8962_DACR_TO_SPKMIXL_WIDTH 1 /* DACR_TO_SPKMIXL */
+#define WM8962_MIXINL_TO_SPKMIXL 0x0008 /* MIXINL_TO_SPKMIXL */
+#define WM8962_MIXINL_TO_SPKMIXL_MASK 0x0008 /* MIXINL_TO_SPKMIXL */
+#define WM8962_MIXINL_TO_SPKMIXL_SHIFT 3 /* MIXINL_TO_SPKMIXL */
+#define WM8962_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */
+#define WM8962_MIXINR_TO_SPKMIXL 0x0004 /* MIXINR_TO_SPKMIXL */
+#define WM8962_MIXINR_TO_SPKMIXL_MASK 0x0004 /* MIXINR_TO_SPKMIXL */
+#define WM8962_MIXINR_TO_SPKMIXL_SHIFT 2 /* MIXINR_TO_SPKMIXL */
+#define WM8962_MIXINR_TO_SPKMIXL_WIDTH 1 /* MIXINR_TO_SPKMIXL */
+#define WM8962_IN4L_TO_SPKMIXL 0x0002 /* IN4L_TO_SPKMIXL */
+#define WM8962_IN4L_TO_SPKMIXL_MASK 0x0002 /* IN4L_TO_SPKMIXL */
+#define WM8962_IN4L_TO_SPKMIXL_SHIFT 1 /* IN4L_TO_SPKMIXL */
+#define WM8962_IN4L_TO_SPKMIXL_WIDTH 1 /* IN4L_TO_SPKMIXL */
+#define WM8962_IN4R_TO_SPKMIXL 0x0001 /* IN4R_TO_SPKMIXL */
+#define WM8962_IN4R_TO_SPKMIXL_MASK 0x0001 /* IN4R_TO_SPKMIXL */
+#define WM8962_IN4R_TO_SPKMIXL_SHIFT 0 /* IN4R_TO_SPKMIXL */
+#define WM8962_IN4R_TO_SPKMIXL_WIDTH 1 /* IN4R_TO_SPKMIXL */
+
+/*
+ * R106 (0x6A) - Speaker Mixer (2)
+ */
+#define WM8962_SPKMIXR_TO_SPKOUTR_PGA 0x0080 /* SPKMIXR_TO_SPKOUTR_PGA */
+#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_MASK 0x0080 /* SPKMIXR_TO_SPKOUTR_PGA */
+#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_SHIFT 7 /* SPKMIXR_TO_SPKOUTR_PGA */
+#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_WIDTH 1 /* SPKMIXR_TO_SPKOUTR_PGA */
+#define WM8962_DACL_TO_SPKMIXR 0x0020 /* DACL_TO_SPKMIXR */
+#define WM8962_DACL_TO_SPKMIXR_MASK 0x0020 /* DACL_TO_SPKMIXR */
+#define WM8962_DACL_TO_SPKMIXR_SHIFT 5 /* DACL_TO_SPKMIXR */
+#define WM8962_DACL_TO_SPKMIXR_WIDTH 1 /* DACL_TO_SPKMIXR */
+#define WM8962_DACR_TO_SPKMIXR 0x0010 /* DACR_TO_SPKMIXR */
+#define WM8962_DACR_TO_SPKMIXR_MASK 0x0010 /* DACR_TO_SPKMIXR */
+#define WM8962_DACR_TO_SPKMIXR_SHIFT 4 /* DACR_TO_SPKMIXR */
+#define WM8962_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */
+#define WM8962_MIXINL_TO_SPKMIXR 0x0008 /* MIXINL_TO_SPKMIXR */
+#define WM8962_MIXINL_TO_SPKMIXR_MASK 0x0008 /* MIXINL_TO_SPKMIXR */
+#define WM8962_MIXINL_TO_SPKMIXR_SHIFT 3 /* MIXINL_TO_SPKMIXR */
+#define WM8962_MIXINL_TO_SPKMIXR_WIDTH 1 /* MIXINL_TO_SPKMIXR */
+#define WM8962_MIXINR_TO_SPKMIXR 0x0004 /* MIXINR_TO_SPKMIXR */
+#define WM8962_MIXINR_TO_SPKMIXR_MASK 0x0004 /* MIXINR_TO_SPKMIXR */
+#define WM8962_MIXINR_TO_SPKMIXR_SHIFT 2 /* MIXINR_TO_SPKMIXR */
+#define WM8962_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */
+#define WM8962_IN4L_TO_SPKMIXR 0x0002 /* IN4L_TO_SPKMIXR */
+#define WM8962_IN4L_TO_SPKMIXR_MASK 0x0002 /* IN4L_TO_SPKMIXR */
+#define WM8962_IN4L_TO_SPKMIXR_SHIFT 1 /* IN4L_TO_SPKMIXR */
+#define WM8962_IN4L_TO_SPKMIXR_WIDTH 1 /* IN4L_TO_SPKMIXR */
+#define WM8962_IN4R_TO_SPKMIXR 0x0001 /* IN4R_TO_SPKMIXR */
+#define WM8962_IN4R_TO_SPKMIXR_MASK 0x0001 /* IN4R_TO_SPKMIXR */
+#define WM8962_IN4R_TO_SPKMIXR_SHIFT 0 /* IN4R_TO_SPKMIXR */
+#define WM8962_IN4R_TO_SPKMIXR_WIDTH 1 /* IN4R_TO_SPKMIXR */
+
+/*
+ * R107 (0x6B) - Speaker Mixer (3)
+ */
+#define WM8962_SPKMIXL_MUTE 0x0100 /* SPKMIXL_MUTE */
+#define WM8962_SPKMIXL_MUTE_MASK 0x0100 /* SPKMIXL_MUTE */
+#define WM8962_SPKMIXL_MUTE_SHIFT 8 /* SPKMIXL_MUTE */
+#define WM8962_SPKMIXL_MUTE_WIDTH 1 /* SPKMIXL_MUTE */
+#define WM8962_MIXINL_SPKMIXL_VOL 0x0080 /* MIXINL_SPKMIXL_VOL */
+#define WM8962_MIXINL_SPKMIXL_VOL_MASK 0x0080 /* MIXINL_SPKMIXL_VOL */
+#define WM8962_MIXINL_SPKMIXL_VOL_SHIFT 7 /* MIXINL_SPKMIXL_VOL */
+#define WM8962_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */
+#define WM8962_MIXINR_SPKMIXL_VOL 0x0040 /* MIXINR_SPKMIXL_VOL */
+#define WM8962_MIXINR_SPKMIXL_VOL_MASK 0x0040 /* MIXINR_SPKMIXL_VOL */
+#define WM8962_MIXINR_SPKMIXL_VOL_SHIFT 6 /* MIXINR_SPKMIXL_VOL */
+#define WM8962_MIXINR_SPKMIXL_VOL_WIDTH 1 /* MIXINR_SPKMIXL_VOL */
+#define WM8962_IN4L_SPKMIXL_VOL_MASK 0x0038 /* IN4L_SPKMIXL_VOL - [5:3] */
+#define WM8962_IN4L_SPKMIXL_VOL_SHIFT 3 /* IN4L_SPKMIXL_VOL - [5:3] */
+#define WM8962_IN4L_SPKMIXL_VOL_WIDTH 3 /* IN4L_SPKMIXL_VOL - [5:3] */
+#define WM8962_IN4R_SPKMIXL_VOL_MASK 0x0007 /* IN4R_SPKMIXL_VOL - [2:0] */
+#define WM8962_IN4R_SPKMIXL_VOL_SHIFT 0 /* IN4R_SPKMIXL_VOL - [2:0] */
+#define WM8962_IN4R_SPKMIXL_VOL_WIDTH 3 /* IN4R_SPKMIXL_VOL - [2:0] */
+
+/*
+ * R108 (0x6C) - Speaker Mixer (4)
+ */
+#define WM8962_SPKMIXR_MUTE 0x0100 /* SPKMIXR_MUTE */
+#define WM8962_SPKMIXR_MUTE_MASK 0x0100 /* SPKMIXR_MUTE */
+#define WM8962_SPKMIXR_MUTE_SHIFT 8 /* SPKMIXR_MUTE */
+#define WM8962_SPKMIXR_MUTE_WIDTH 1 /* SPKMIXR_MUTE */
+#define WM8962_MIXINL_SPKMIXR_VOL 0x0080 /* MIXINL_SPKMIXR_VOL */
+#define WM8962_MIXINL_SPKMIXR_VOL_MASK 0x0080 /* MIXINL_SPKMIXR_VOL */
+#define WM8962_MIXINL_SPKMIXR_VOL_SHIFT 7 /* MIXINL_SPKMIXR_VOL */
+#define WM8962_MIXINL_SPKMIXR_VOL_WIDTH 1 /* MIXINL_SPKMIXR_VOL */
+#define WM8962_MIXINR_SPKMIXR_VOL 0x0040 /* MIXINR_SPKMIXR_VOL */
+#define WM8962_MIXINR_SPKMIXR_VOL_MASK 0x0040 /* MIXINR_SPKMIXR_VOL */
+#define WM8962_MIXINR_SPKMIXR_VOL_SHIFT 6 /* MIXINR_SPKMIXR_VOL */
+#define WM8962_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */
+#define WM8962_IN4L_SPKMIXR_VOL_MASK 0x0038 /* IN4L_SPKMIXR_VOL - [5:3] */
+#define WM8962_IN4L_SPKMIXR_VOL_SHIFT 3 /* IN4L_SPKMIXR_VOL - [5:3] */
+#define WM8962_IN4L_SPKMIXR_VOL_WIDTH 3 /* IN4L_SPKMIXR_VOL - [5:3] */
+#define WM8962_IN4R_SPKMIXR_VOL_MASK 0x0007 /* IN4R_SPKMIXR_VOL - [2:0] */
+#define WM8962_IN4R_SPKMIXR_VOL_SHIFT 0 /* IN4R_SPKMIXR_VOL - [2:0] */
+#define WM8962_IN4R_SPKMIXR_VOL_WIDTH 3 /* IN4R_SPKMIXR_VOL - [2:0] */
+
+/*
+ * R109 (0x6D) - Speaker Mixer (5)
+ */
+#define WM8962_DACL_SPKMIXL_VOL 0x0080 /* DACL_SPKMIXL_VOL */
+#define WM8962_DACL_SPKMIXL_VOL_MASK 0x0080 /* DACL_SPKMIXL_VOL */
+#define WM8962_DACL_SPKMIXL_VOL_SHIFT 7 /* DACL_SPKMIXL_VOL */
+#define WM8962_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */
+#define WM8962_DACR_SPKMIXL_VOL 0x0040 /* DACR_SPKMIXL_VOL */
+#define WM8962_DACR_SPKMIXL_VOL_MASK 0x0040 /* DACR_SPKMIXL_VOL */
+#define WM8962_DACR_SPKMIXL_VOL_SHIFT 6 /* DACR_SPKMIXL_VOL */
+#define WM8962_DACR_SPKMIXL_VOL_WIDTH 1 /* DACR_SPKMIXL_VOL */
+#define WM8962_DACL_SPKMIXR_VOL 0x0020 /* DACL_SPKMIXR_VOL */
+#define WM8962_DACL_SPKMIXR_VOL_MASK 0x0020 /* DACL_SPKMIXR_VOL */
+#define WM8962_DACL_SPKMIXR_VOL_SHIFT 5 /* DACL_SPKMIXR_VOL */
+#define WM8962_DACL_SPKMIXR_VOL_WIDTH 1 /* DACL_SPKMIXR_VOL */
+#define WM8962_DACR_SPKMIXR_VOL 0x0010 /* DACR_SPKMIXR_VOL */
+#define WM8962_DACR_SPKMIXR_VOL_MASK 0x0010 /* DACR_SPKMIXR_VOL */
+#define WM8962_DACR_SPKMIXR_VOL_SHIFT 4 /* DACR_SPKMIXR_VOL */
+#define WM8962_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */
+
+/*
+ * R110 (0x6E) - Beep Generator (1)
+ */
+#define WM8962_BEEP_GAIN_MASK 0x00F0 /* BEEP_GAIN - [7:4] */
+#define WM8962_BEEP_GAIN_SHIFT 4 /* BEEP_GAIN - [7:4] */
+#define WM8962_BEEP_GAIN_WIDTH 4 /* BEEP_GAIN - [7:4] */
+#define WM8962_BEEP_RATE_MASK 0x0006 /* BEEP_RATE - [2:1] */
+#define WM8962_BEEP_RATE_SHIFT 1 /* BEEP_RATE - [2:1] */
+#define WM8962_BEEP_RATE_WIDTH 2 /* BEEP_RATE - [2:1] */
+#define WM8962_BEEP_ENA 0x0001 /* BEEP_ENA */
+#define WM8962_BEEP_ENA_MASK 0x0001 /* BEEP_ENA */
+#define WM8962_BEEP_ENA_SHIFT 0 /* BEEP_ENA */
+#define WM8962_BEEP_ENA_WIDTH 1 /* BEEP_ENA */
+
+/*
+ * R115 (0x73) - Oscillator Trim (3)
+ */
+#define WM8962_OSC_TRIM_XTI_MASK 0x001F /* OSC_TRIM_XTI - [4:0] */
+#define WM8962_OSC_TRIM_XTI_SHIFT 0 /* OSC_TRIM_XTI - [4:0] */
+#define WM8962_OSC_TRIM_XTI_WIDTH 5 /* OSC_TRIM_XTI - [4:0] */
+
+/*
+ * R116 (0x74) - Oscillator Trim (4)
+ */
+#define WM8962_OSC_TRIM_XTO_MASK 0x001F /* OSC_TRIM_XTO - [4:0] */
+#define WM8962_OSC_TRIM_XTO_SHIFT 0 /* OSC_TRIM_XTO - [4:0] */
+#define WM8962_OSC_TRIM_XTO_WIDTH 5 /* OSC_TRIM_XTO - [4:0] */
+
+/*
+ * R119 (0x77) - Oscillator Trim (7)
+ */
+#define WM8962_XTO_CAP_SEL_MASK 0x00F0 /* XTO_CAP_SEL - [7:4] */
+#define WM8962_XTO_CAP_SEL_SHIFT 4 /* XTO_CAP_SEL - [7:4] */
+#define WM8962_XTO_CAP_SEL_WIDTH 4 /* XTO_CAP_SEL - [7:4] */
+#define WM8962_XTI_CAP_SEL_MASK 0x000F /* XTI_CAP_SEL - [3:0] */
+#define WM8962_XTI_CAP_SEL_SHIFT 0 /* XTI_CAP_SEL - [3:0] */
+#define WM8962_XTI_CAP_SEL_WIDTH 4 /* XTI_CAP_SEL - [3:0] */
+
+/*
+ * R124 (0x7C) - Analogue Clocking1
+ */
+#define WM8962_CLKOUT2_SEL_MASK 0x0060 /* CLKOUT2_SEL - [6:5] */
+#define WM8962_CLKOUT2_SEL_SHIFT 5 /* CLKOUT2_SEL - [6:5] */
+#define WM8962_CLKOUT2_SEL_WIDTH 2 /* CLKOUT2_SEL - [6:5] */
+#define WM8962_CLKOUT3_SEL_MASK 0x0018 /* CLKOUT3_SEL - [4:3] */
+#define WM8962_CLKOUT3_SEL_SHIFT 3 /* CLKOUT3_SEL - [4:3] */
+#define WM8962_CLKOUT3_SEL_WIDTH 2 /* CLKOUT3_SEL - [4:3] */
+#define WM8962_CLKOUT5_SEL 0x0001 /* CLKOUT5_SEL */
+#define WM8962_CLKOUT5_SEL_MASK 0x0001 /* CLKOUT5_SEL */
+#define WM8962_CLKOUT5_SEL_SHIFT 0 /* CLKOUT5_SEL */
+#define WM8962_CLKOUT5_SEL_WIDTH 1 /* CLKOUT5_SEL */
+
+/*
+ * R125 (0x7D) - Analogue Clocking2
+ */
+#define WM8962_PLL2_OUTDIV 0x0080 /* PLL2_OUTDIV */
+#define WM8962_PLL2_OUTDIV_MASK 0x0080 /* PLL2_OUTDIV */
+#define WM8962_PLL2_OUTDIV_SHIFT 7 /* PLL2_OUTDIV */
+#define WM8962_PLL2_OUTDIV_WIDTH 1 /* PLL2_OUTDIV */
+#define WM8962_PLL3_OUTDIV 0x0040 /* PLL3_OUTDIV */
+#define WM8962_PLL3_OUTDIV_MASK 0x0040 /* PLL3_OUTDIV */
+#define WM8962_PLL3_OUTDIV_SHIFT 6 /* PLL3_OUTDIV */
+#define WM8962_PLL3_OUTDIV_WIDTH 1 /* PLL3_OUTDIV */
+#define WM8962_PLL_SYSCLK_DIV_MASK 0x0018 /* PLL_SYSCLK_DIV - [4:3] */
+#define WM8962_PLL_SYSCLK_DIV_SHIFT 3 /* PLL_SYSCLK_DIV - [4:3] */
+#define WM8962_PLL_SYSCLK_DIV_WIDTH 2 /* PLL_SYSCLK_DIV - [4:3] */
+#define WM8962_CLKOUT3_DIV 0x0004 /* CLKOUT3_DIV */
+#define WM8962_CLKOUT3_DIV_MASK 0x0004 /* CLKOUT3_DIV */
+#define WM8962_CLKOUT3_DIV_SHIFT 2 /* CLKOUT3_DIV */
+#define WM8962_CLKOUT3_DIV_WIDTH 1 /* CLKOUT3_DIV */
+#define WM8962_CLKOUT2_DIV 0x0002 /* CLKOUT2_DIV */
+#define WM8962_CLKOUT2_DIV_MASK 0x0002 /* CLKOUT2_DIV */
+#define WM8962_CLKOUT2_DIV_SHIFT 1 /* CLKOUT2_DIV */
+#define WM8962_CLKOUT2_DIV_WIDTH 1 /* CLKOUT2_DIV */
+#define WM8962_CLKOUT5_DIV 0x0001 /* CLKOUT5_DIV */
+#define WM8962_CLKOUT5_DIV_MASK 0x0001 /* CLKOUT5_DIV */
+#define WM8962_CLKOUT5_DIV_SHIFT 0 /* CLKOUT5_DIV */
+#define WM8962_CLKOUT5_DIV_WIDTH 1 /* CLKOUT5_DIV */
+
+/*
+ * R126 (0x7E) - Analogue Clocking3
+ */
+#define WM8962_CLKOUT2_OE 0x0008 /* CLKOUT2_OE */
+#define WM8962_CLKOUT2_OE_MASK 0x0008 /* CLKOUT2_OE */
+#define WM8962_CLKOUT2_OE_SHIFT 3 /* CLKOUT2_OE */
+#define WM8962_CLKOUT2_OE_WIDTH 1 /* CLKOUT2_OE */
+#define WM8962_CLKOUT3_OE 0x0004 /* CLKOUT3_OE */
+#define WM8962_CLKOUT3_OE_MASK 0x0004 /* CLKOUT3_OE */
+#define WM8962_CLKOUT3_OE_SHIFT 2 /* CLKOUT3_OE */
+#define WM8962_CLKOUT3_OE_WIDTH 1 /* CLKOUT3_OE */
+#define WM8962_CLKOUT5_OE 0x0001 /* CLKOUT5_OE */
+#define WM8962_CLKOUT5_OE_MASK 0x0001 /* CLKOUT5_OE */
+#define WM8962_CLKOUT5_OE_SHIFT 0 /* CLKOUT5_OE */
+#define WM8962_CLKOUT5_OE_WIDTH 1 /* CLKOUT5_OE */
+
+/*
+ * R127 (0x7F) - PLL Software Reset
+ */
+#define WM8962_SW_RESET_PLL_MASK 0xFFFF /* SW_RESET_PLL - [15:0] */
+#define WM8962_SW_RESET_PLL_SHIFT 0 /* SW_RESET_PLL - [15:0] */
+#define WM8962_SW_RESET_PLL_WIDTH 16 /* SW_RESET_PLL - [15:0] */
+
+/*
+ * R129 (0x81) - PLL2
+ */
+#define WM8962_OSC_ENA 0x0080 /* OSC_ENA */
+#define WM8962_OSC_ENA_MASK 0x0080 /* OSC_ENA */
+#define WM8962_OSC_ENA_SHIFT 7 /* OSC_ENA */
+#define WM8962_OSC_ENA_WIDTH 1 /* OSC_ENA */
+#define WM8962_PLL2_ENA 0x0020 /* PLL2_ENA */
+#define WM8962_PLL2_ENA_MASK 0x0020 /* PLL2_ENA */
+#define WM8962_PLL2_ENA_SHIFT 5 /* PLL2_ENA */
+#define WM8962_PLL2_ENA_WIDTH 1 /* PLL2_ENA */
+#define WM8962_PLL3_ENA 0x0010 /* PLL3_ENA */
+#define WM8962_PLL3_ENA_MASK 0x0010 /* PLL3_ENA */
+#define WM8962_PLL3_ENA_SHIFT 4 /* PLL3_ENA */
+#define WM8962_PLL3_ENA_WIDTH 1 /* PLL3_ENA */
+
+/*
+ * R131 (0x83) - PLL 4
+ */
+#define WM8962_PLL_CLK_SRC 0x0002 /* PLL_CLK_SRC */
+#define WM8962_PLL_CLK_SRC_MASK 0x0002 /* PLL_CLK_SRC */
+#define WM8962_PLL_CLK_SRC_SHIFT 1 /* PLL_CLK_SRC */
+#define WM8962_PLL_CLK_SRC_WIDTH 1 /* PLL_CLK_SRC */
+#define WM8962_FLL_TO_PLL3 0x0001 /* FLL_TO_PLL3 */
+#define WM8962_FLL_TO_PLL3_MASK 0x0001 /* FLL_TO_PLL3 */
+#define WM8962_FLL_TO_PLL3_SHIFT 0 /* FLL_TO_PLL3 */
+#define WM8962_FLL_TO_PLL3_WIDTH 1 /* FLL_TO_PLL3 */
+
+/*
+ * R136 (0x88) - PLL 9
+ */
+#define WM8962_PLL2_FRAC 0x0040 /* PLL2_FRAC */
+#define WM8962_PLL2_FRAC_MASK 0x0040 /* PLL2_FRAC */
+#define WM8962_PLL2_FRAC_SHIFT 6 /* PLL2_FRAC */
+#define WM8962_PLL2_FRAC_WIDTH 1 /* PLL2_FRAC */
+#define WM8962_PLL2_N_MASK 0x001F /* PLL2_N - [4:0] */
+#define WM8962_PLL2_N_SHIFT 0 /* PLL2_N - [4:0] */
+#define WM8962_PLL2_N_WIDTH 5 /* PLL2_N - [4:0] */
+
+/*
+ * R137 (0x89) - PLL 10
+ */
+#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */
+
+/*
+ * R138 (0x8A) - PLL 11
+ */
+#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */
+
+/*
+ * R139 (0x8B) - PLL 12
+ */
+#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */
+
+/*
+ * R140 (0x8C) - PLL 13
+ */
+#define WM8962_PLL3_FRAC 0x0040 /* PLL3_FRAC */
+#define WM8962_PLL3_FRAC_MASK 0x0040 /* PLL3_FRAC */
+#define WM8962_PLL3_FRAC_SHIFT 6 /* PLL3_FRAC */
+#define WM8962_PLL3_FRAC_WIDTH 1 /* PLL3_FRAC */
+#define WM8962_PLL3_N_MASK 0x001F /* PLL3_N - [4:0] */
+#define WM8962_PLL3_N_SHIFT 0 /* PLL3_N - [4:0] */
+#define WM8962_PLL3_N_WIDTH 5 /* PLL3_N - [4:0] */
+
+/*
+ * R141 (0x8D) - PLL 14
+ */
+#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */
+
+/*
+ * R142 (0x8E) - PLL 15
+ */
+#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */
+
+/*
+ * R143 (0x8F) - PLL 16
+ */
+#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */
+
+/*
+ * R155 (0x9B) - FLL Control (1)
+ */
+#define WM8962_FLL_REFCLK_SRC_MASK 0x0060 /* FLL_REFCLK_SRC - [6:5] */
+#define WM8962_FLL_REFCLK_SRC_SHIFT 5 /* FLL_REFCLK_SRC - [6:5] */
+#define WM8962_FLL_REFCLK_SRC_WIDTH 2 /* FLL_REFCLK_SRC - [6:5] */
+#define WM8962_FLL_FRAC 0x0004 /* FLL_FRAC */
+#define WM8962_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */
+#define WM8962_FLL_FRAC_SHIFT 2 /* FLL_FRAC */
+#define WM8962_FLL_FRAC_WIDTH 1 /* FLL_FRAC */
+#define WM8962_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */
+#define WM8962_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */
+#define WM8962_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */
+#define WM8962_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */
+#define WM8962_FLL_ENA 0x0001 /* FLL_ENA */
+#define WM8962_FLL_ENA_MASK 0x0001 /* FLL_ENA */
+#define WM8962_FLL_ENA_SHIFT 0 /* FLL_ENA */
+#define WM8962_FLL_ENA_WIDTH 1 /* FLL_ENA */
+
+/*
+ * R156 (0x9C) - FLL Control (2)
+ */
+#define WM8962_FLL_OUTDIV_MASK 0x01F8 /* FLL_OUTDIV - [8:3] */
+#define WM8962_FLL_OUTDIV_SHIFT 3 /* FLL_OUTDIV - [8:3] */
+#define WM8962_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [8:3] */
+#define WM8962_FLL_REFCLK_DIV_MASK 0x0003 /* FLL_REFCLK_DIV - [1:0] */
+#define WM8962_FLL_REFCLK_DIV_SHIFT 0 /* FLL_REFCLK_DIV - [1:0] */
+#define WM8962_FLL_REFCLK_DIV_WIDTH 2 /* FLL_REFCLK_DIV - [1:0] */
+
+/*
+ * R157 (0x9D) - FLL Control (3)
+ */
+#define WM8962_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
+#define WM8962_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
+#define WM8962_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
+
+/*
+ * R159 (0x9F) - FLL Control (5)
+ */
+#define WM8962_FLL_FRC_NCO_VAL_MASK 0x007E /* FLL_FRC_NCO_VAL - [6:1] */
+#define WM8962_FLL_FRC_NCO_VAL_SHIFT 1 /* FLL_FRC_NCO_VAL - [6:1] */
+#define WM8962_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [6:1] */
+#define WM8962_FLL_FRC_NCO 0x0001 /* FLL_FRC_NCO */
+#define WM8962_FLL_FRC_NCO_MASK 0x0001 /* FLL_FRC_NCO */
+#define WM8962_FLL_FRC_NCO_SHIFT 0 /* FLL_FRC_NCO */
+#define WM8962_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */
+
+/*
+ * R160 (0xA0) - FLL Control (6)
+ */
+#define WM8962_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */
+#define WM8962_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */
+#define WM8962_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */
+
+/*
+ * R161 (0xA1) - FLL Control (7)
+ */
+#define WM8962_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */
+#define WM8962_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */
+#define WM8962_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */
+
+/*
+ * R162 (0xA2) - FLL Control (8)
+ */
+#define WM8962_FLL_N_MASK 0x03FF /* FLL_N - [9:0] */
+#define WM8962_FLL_N_SHIFT 0 /* FLL_N - [9:0] */
+#define WM8962_FLL_N_WIDTH 10 /* FLL_N - [9:0] */
+
+/*
+ * R252 (0xFC) - General test 1
+ */
+#define WM8962_REG_SYNC 0x0004 /* REG_SYNC */
+#define WM8962_REG_SYNC_MASK 0x0004 /* REG_SYNC */
+#define WM8962_REG_SYNC_SHIFT 2 /* REG_SYNC */
+#define WM8962_REG_SYNC_WIDTH 1 /* REG_SYNC */
+#define WM8962_AUTO_INC 0x0001 /* AUTO_INC */
+#define WM8962_AUTO_INC_MASK 0x0001 /* AUTO_INC */
+#define WM8962_AUTO_INC_SHIFT 0 /* AUTO_INC */
+#define WM8962_AUTO_INC_WIDTH 1 /* AUTO_INC */
+
+/*
+ * R256 (0x100) - DF1
+ */
+#define WM8962_DRC_DF1_ENA 0x0008 /* DRC_DF1_ENA */
+#define WM8962_DRC_DF1_ENA_MASK 0x0008 /* DRC_DF1_ENA */
+#define WM8962_DRC_DF1_ENA_SHIFT 3 /* DRC_DF1_ENA */
+#define WM8962_DRC_DF1_ENA_WIDTH 1 /* DRC_DF1_ENA */
+#define WM8962_DF1_SHARED_COEFF 0x0004 /* DF1_SHARED_COEFF */
+#define WM8962_DF1_SHARED_COEFF_MASK 0x0004 /* DF1_SHARED_COEFF */
+#define WM8962_DF1_SHARED_COEFF_SHIFT 2 /* DF1_SHARED_COEFF */
+#define WM8962_DF1_SHARED_COEFF_WIDTH 1 /* DF1_SHARED_COEFF */
+#define WM8962_DF1_SHARED_COEFF_SEL 0x0002 /* DF1_SHARED_COEFF_SEL */
+#define WM8962_DF1_SHARED_COEFF_SEL_MASK 0x0002 /* DF1_SHARED_COEFF_SEL */
+#define WM8962_DF1_SHARED_COEFF_SEL_SHIFT 1 /* DF1_SHARED_COEFF_SEL */
+#define WM8962_DF1_SHARED_COEFF_SEL_WIDTH 1 /* DF1_SHARED_COEFF_SEL */
+#define WM8962_DF1_ENA 0x0001 /* DF1_ENA */
+#define WM8962_DF1_ENA_MASK 0x0001 /* DF1_ENA */
+#define WM8962_DF1_ENA_SHIFT 0 /* DF1_ENA */
+#define WM8962_DF1_ENA_WIDTH 1 /* DF1_ENA */
+
+/*
+ * R257 (0x101) - DF2
+ */
+#define WM8962_DF1_COEFF_L0_MASK 0xFFFF /* DF1_COEFF_L0 - [15:0] */
+#define WM8962_DF1_COEFF_L0_SHIFT 0 /* DF1_COEFF_L0 - [15:0] */
+#define WM8962_DF1_COEFF_L0_WIDTH 16 /* DF1_COEFF_L0 - [15:0] */
+
+/*
+ * R258 (0x102) - DF3
+ */
+#define WM8962_DF1_COEFF_L1_MASK 0xFFFF /* DF1_COEFF_L1 - [15:0] */
+#define WM8962_DF1_COEFF_L1_SHIFT 0 /* DF1_COEFF_L1 - [15:0] */
+#define WM8962_DF1_COEFF_L1_WIDTH 16 /* DF1_COEFF_L1 - [15:0] */
+
+/*
+ * R259 (0x103) - DF4
+ */
+#define WM8962_DF1_COEFF_L2_MASK 0xFFFF /* DF1_COEFF_L2 - [15:0] */
+#define WM8962_DF1_COEFF_L2_SHIFT 0 /* DF1_COEFF_L2 - [15:0] */
+#define WM8962_DF1_COEFF_L2_WIDTH 16 /* DF1_COEFF_L2 - [15:0] */
+
+/*
+ * R260 (0x104) - DF5
+ */
+#define WM8962_DF1_COEFF_R0_MASK 0xFFFF /* DF1_COEFF_R0 - [15:0] */
+#define WM8962_DF1_COEFF_R0_SHIFT 0 /* DF1_COEFF_R0 - [15:0] */
+#define WM8962_DF1_COEFF_R0_WIDTH 16 /* DF1_COEFF_R0 - [15:0] */
+
+/*
+ * R261 (0x105) - DF6
+ */
+#define WM8962_DF1_COEFF_R1_MASK 0xFFFF /* DF1_COEFF_R1 - [15:0] */
+#define WM8962_DF1_COEFF_R1_SHIFT 0 /* DF1_COEFF_R1 - [15:0] */
+#define WM8962_DF1_COEFF_R1_WIDTH 16 /* DF1_COEFF_R1 - [15:0] */
+
+/*
+ * R262 (0x106) - DF7
+ */
+#define WM8962_DF1_COEFF_R2_MASK 0xFFFF /* DF1_COEFF_R2 - [15:0] */
+#define WM8962_DF1_COEFF_R2_SHIFT 0 /* DF1_COEFF_R2 - [15:0] */
+#define WM8962_DF1_COEFF_R2_WIDTH 16 /* DF1_COEFF_R2 - [15:0] */
+
+/*
+ * R264 (0x108) - LHPF1
+ */
+#define WM8962_LHPF_MODE 0x0002 /* LHPF_MODE */
+#define WM8962_LHPF_MODE_MASK 0x0002 /* LHPF_MODE */
+#define WM8962_LHPF_MODE_SHIFT 1 /* LHPF_MODE */
+#define WM8962_LHPF_MODE_WIDTH 1 /* LHPF_MODE */
+#define WM8962_LHPF_ENA 0x0001 /* LHPF_ENA */
+#define WM8962_LHPF_ENA_MASK 0x0001 /* LHPF_ENA */
+#define WM8962_LHPF_ENA_SHIFT 0 /* LHPF_ENA */
+#define WM8962_LHPF_ENA_WIDTH 1 /* LHPF_ENA */
+
+/*
+ * R265 (0x109) - LHPF2
+ */
+#define WM8962_LHPF_COEFF_MASK 0xFFFF /* LHPF_COEFF - [15:0] */
+#define WM8962_LHPF_COEFF_SHIFT 0 /* LHPF_COEFF - [15:0] */
+#define WM8962_LHPF_COEFF_WIDTH 16 /* LHPF_COEFF - [15:0] */
+
+/*
+ * R268 (0x10C) - THREED1
+ */
+#define WM8962_ADC_MONOMIX 0x0040 /* ADC_MONOMIX */
+#define WM8962_ADC_MONOMIX_MASK 0x0040 /* ADC_MONOMIX */
+#define WM8962_ADC_MONOMIX_SHIFT 6 /* ADC_MONOMIX */
+#define WM8962_ADC_MONOMIX_WIDTH 1 /* ADC_MONOMIX */
+#define WM8962_THREED_SIGN_L 0x0020 /* THREED_SIGN_L */
+#define WM8962_THREED_SIGN_L_MASK 0x0020 /* THREED_SIGN_L */
+#define WM8962_THREED_SIGN_L_SHIFT 5 /* THREED_SIGN_L */
+#define WM8962_THREED_SIGN_L_WIDTH 1 /* THREED_SIGN_L */
+#define WM8962_THREED_SIGN_R 0x0010 /* THREED_SIGN_R */
+#define WM8962_THREED_SIGN_R_MASK 0x0010 /* THREED_SIGN_R */
+#define WM8962_THREED_SIGN_R_SHIFT 4 /* THREED_SIGN_R */
+#define WM8962_THREED_SIGN_R_WIDTH 1 /* THREED_SIGN_R */
+#define WM8962_THREED_LHPF_MODE 0x0004 /* THREED_LHPF_MODE */
+#define WM8962_THREED_LHPF_MODE_MASK 0x0004 /* THREED_LHPF_MODE */
+#define WM8962_THREED_LHPF_MODE_SHIFT 2 /* THREED_LHPF_MODE */
+#define WM8962_THREED_LHPF_MODE_WIDTH 1 /* THREED_LHPF_MODE */
+#define WM8962_THREED_LHPF_ENA 0x0002 /* THREED_LHPF_ENA */
+#define WM8962_THREED_LHPF_ENA_MASK 0x0002 /* THREED_LHPF_ENA */
+#define WM8962_THREED_LHPF_ENA_SHIFT 1 /* THREED_LHPF_ENA */
+#define WM8962_THREED_LHPF_ENA_WIDTH 1 /* THREED_LHPF_ENA */
+#define WM8962_THREED_ENA 0x0001 /* THREED_ENA */
+#define WM8962_THREED_ENA_MASK 0x0001 /* THREED_ENA */
+#define WM8962_THREED_ENA_SHIFT 0 /* THREED_ENA */
+#define WM8962_THREED_ENA_WIDTH 1 /* THREED_ENA */
+
+/*
+ * R269 (0x10D) - THREED2
+ */
+#define WM8962_THREED_FGAINL_MASK 0xF800 /* THREED_FGAINL - [15:11] */
+#define WM8962_THREED_FGAINL_SHIFT 11 /* THREED_FGAINL - [15:11] */
+#define WM8962_THREED_FGAINL_WIDTH 5 /* THREED_FGAINL - [15:11] */
+#define WM8962_THREED_CGAINL_MASK 0x07C0 /* THREED_CGAINL - [10:6] */
+#define WM8962_THREED_CGAINL_SHIFT 6 /* THREED_CGAINL - [10:6] */
+#define WM8962_THREED_CGAINL_WIDTH 5 /* THREED_CGAINL - [10:6] */
+#define WM8962_THREED_DELAYL_MASK 0x003C /* THREED_DELAYL - [5:2] */
+#define WM8962_THREED_DELAYL_SHIFT 2 /* THREED_DELAYL - [5:2] */
+#define WM8962_THREED_DELAYL_WIDTH 4 /* THREED_DELAYL - [5:2] */
+
+/*
+ * R270 (0x10E) - THREED3
+ */
+#define WM8962_THREED_LHPF_COEFF_MASK 0xFFFF /* THREED_LHPF_COEFF - [15:0] */
+#define WM8962_THREED_LHPF_COEFF_SHIFT 0 /* THREED_LHPF_COEFF - [15:0] */
+#define WM8962_THREED_LHPF_COEFF_WIDTH 16 /* THREED_LHPF_COEFF - [15:0] */
+
+/*
+ * R271 (0x10F) - THREED4
+ */
+#define WM8962_THREED_FGAINR_MASK 0xF800 /* THREED_FGAINR - [15:11] */
+#define WM8962_THREED_FGAINR_SHIFT 11 /* THREED_FGAINR - [15:11] */
+#define WM8962_THREED_FGAINR_WIDTH 5 /* THREED_FGAINR - [15:11] */
+#define WM8962_THREED_CGAINR_MASK 0x07C0 /* THREED_CGAINR - [10:6] */
+#define WM8962_THREED_CGAINR_SHIFT 6 /* THREED_CGAINR - [10:6] */
+#define WM8962_THREED_CGAINR_WIDTH 5 /* THREED_CGAINR - [10:6] */
+#define WM8962_THREED_DELAYR_MASK 0x003C /* THREED_DELAYR - [5:2] */
+#define WM8962_THREED_DELAYR_SHIFT 2 /* THREED_DELAYR - [5:2] */
+#define WM8962_THREED_DELAYR_WIDTH 4 /* THREED_DELAYR - [5:2] */
+
+/*
+ * R276 (0x114) - DRC 1
+ */
+#define WM8962_DRC_SIG_DET_RMS_MASK 0x7C00 /* DRC_SIG_DET_RMS - [14:10] */
+#define WM8962_DRC_SIG_DET_RMS_SHIFT 10 /* DRC_SIG_DET_RMS - [14:10] */
+#define WM8962_DRC_SIG_DET_RMS_WIDTH 5 /* DRC_SIG_DET_RMS - [14:10] */
+#define WM8962_DRC_SIG_DET_PK_MASK 0x0300 /* DRC_SIG_DET_PK - [9:8] */
+#define WM8962_DRC_SIG_DET_PK_SHIFT 8 /* DRC_SIG_DET_PK - [9:8] */
+#define WM8962_DRC_SIG_DET_PK_WIDTH 2 /* DRC_SIG_DET_PK - [9:8] */
+#define WM8962_DRC_NG_ENA 0x0080 /* DRC_NG_ENA */
+#define WM8962_DRC_NG_ENA_MASK 0x0080 /* DRC_NG_ENA */
+#define WM8962_DRC_NG_ENA_SHIFT 7 /* DRC_NG_ENA */
+#define WM8962_DRC_NG_ENA_WIDTH 1 /* DRC_NG_ENA */
+#define WM8962_DRC_SIG_DET_MODE 0x0040 /* DRC_SIG_DET_MODE */
+#define WM8962_DRC_SIG_DET_MODE_MASK 0x0040 /* DRC_SIG_DET_MODE */
+#define WM8962_DRC_SIG_DET_MODE_SHIFT 6 /* DRC_SIG_DET_MODE */
+#define WM8962_DRC_SIG_DET_MODE_WIDTH 1 /* DRC_SIG_DET_MODE */
+#define WM8962_DRC_SIG_DET 0x0020 /* DRC_SIG_DET */
+#define WM8962_DRC_SIG_DET_MASK 0x0020 /* DRC_SIG_DET */
+#define WM8962_DRC_SIG_DET_SHIFT 5 /* DRC_SIG_DET */
+#define WM8962_DRC_SIG_DET_WIDTH 1 /* DRC_SIG_DET */
+#define WM8962_DRC_KNEE2_OP_ENA 0x0010 /* DRC_KNEE2_OP_ENA */
+#define WM8962_DRC_KNEE2_OP_ENA_MASK 0x0010 /* DRC_KNEE2_OP_ENA */
+#define WM8962_DRC_KNEE2_OP_ENA_SHIFT 4 /* DRC_KNEE2_OP_ENA */
+#define WM8962_DRC_KNEE2_OP_ENA_WIDTH 1 /* DRC_KNEE2_OP_ENA */
+#define WM8962_DRC_QR 0x0008 /* DRC_QR */
+#define WM8962_DRC_QR_MASK 0x0008 /* DRC_QR */
+#define WM8962_DRC_QR_SHIFT 3 /* DRC_QR */
+#define WM8962_DRC_QR_WIDTH 1 /* DRC_QR */
+#define WM8962_DRC_ANTICLIP 0x0004 /* DRC_ANTICLIP */
+#define WM8962_DRC_ANTICLIP_MASK 0x0004 /* DRC_ANTICLIP */
+#define WM8962_DRC_ANTICLIP_SHIFT 2 /* DRC_ANTICLIP */
+#define WM8962_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */
+#define WM8962_DRC_MODE 0x0002 /* DRC_MODE */
+#define WM8962_DRC_MODE_MASK 0x0002 /* DRC_MODE */
+#define WM8962_DRC_MODE_SHIFT 1 /* DRC_MODE */
+#define WM8962_DRC_MODE_WIDTH 1 /* DRC_MODE */
+#define WM8962_DRC_ENA 0x0001 /* DRC_ENA */
+#define WM8962_DRC_ENA_MASK 0x0001 /* DRC_ENA */
+#define WM8962_DRC_ENA_SHIFT 0 /* DRC_ENA */
+#define WM8962_DRC_ENA_WIDTH 1 /* DRC_ENA */
+
+/*
+ * R277 (0x115) - DRC 2
+ */
+#define WM8962_DRC_ATK_MASK 0x1E00 /* DRC_ATK - [12:9] */
+#define WM8962_DRC_ATK_SHIFT 9 /* DRC_ATK - [12:9] */
+#define WM8962_DRC_ATK_WIDTH 4 /* DRC_ATK - [12:9] */
+#define WM8962_DRC_DCY_MASK 0x01E0 /* DRC_DCY - [8:5] */
+#define WM8962_DRC_DCY_SHIFT 5 /* DRC_DCY - [8:5] */
+#define WM8962_DRC_DCY_WIDTH 4 /* DRC_DCY - [8:5] */
+#define WM8962_DRC_MINGAIN_MASK 0x001C /* DRC_MINGAIN - [4:2] */
+#define WM8962_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [4:2] */
+#define WM8962_DRC_MINGAIN_WIDTH 3 /* DRC_MINGAIN - [4:2] */
+#define WM8962_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
+#define WM8962_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
+#define WM8962_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
+
+/*
+ * R278 (0x116) - DRC 3
+ */
+#define WM8962_DRC_NG_MINGAIN_MASK 0xF000 /* DRC_NG_MINGAIN - [15:12] */
+#define WM8962_DRC_NG_MINGAIN_SHIFT 12 /* DRC_NG_MINGAIN - [15:12] */
+#define WM8962_DRC_NG_MINGAIN_WIDTH 4 /* DRC_NG_MINGAIN - [15:12] */
+#define WM8962_DRC_QR_THR_MASK 0x0C00 /* DRC_QR_THR - [11:10] */
+#define WM8962_DRC_QR_THR_SHIFT 10 /* DRC_QR_THR - [11:10] */
+#define WM8962_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [11:10] */
+#define WM8962_DRC_QR_DCY_MASK 0x0300 /* DRC_QR_DCY - [9:8] */
+#define WM8962_DRC_QR_DCY_SHIFT 8 /* DRC_QR_DCY - [9:8] */
+#define WM8962_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [9:8] */
+#define WM8962_DRC_NG_EXP_MASK 0x00C0 /* DRC_NG_EXP - [7:6] */
+#define WM8962_DRC_NG_EXP_SHIFT 6 /* DRC_NG_EXP - [7:6] */
+#define WM8962_DRC_NG_EXP_WIDTH 2 /* DRC_NG_EXP - [7:6] */
+#define WM8962_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */
+#define WM8962_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */
+#define WM8962_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */
+#define WM8962_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */
+#define WM8962_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */
+#define WM8962_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */
+
+/*
+ * R279 (0x117) - DRC 4
+ */
+#define WM8962_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */
+#define WM8962_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */
+#define WM8962_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */
+#define WM8962_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */
+#define WM8962_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */
+#define WM8962_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */
+
+/*
+ * R280 (0x118) - DRC 5
+ */
+#define WM8962_DRC_KNEE2_IP_MASK 0x03E0 /* DRC_KNEE2_IP - [9:5] */
+#define WM8962_DRC_KNEE2_IP_SHIFT 5 /* DRC_KNEE2_IP - [9:5] */
+#define WM8962_DRC_KNEE2_IP_WIDTH 5 /* DRC_KNEE2_IP - [9:5] */
+#define WM8962_DRC_KNEE2_OP_MASK 0x001F /* DRC_KNEE2_OP - [4:0] */
+#define WM8962_DRC_KNEE2_OP_SHIFT 0 /* DRC_KNEE2_OP - [4:0] */
+#define WM8962_DRC_KNEE2_OP_WIDTH 5 /* DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R285 (0x11D) - Tloopback
+ */
+#define WM8962_TLB_ENA 0x0002 /* TLB_ENA */
+#define WM8962_TLB_ENA_MASK 0x0002 /* TLB_ENA */
+#define WM8962_TLB_ENA_SHIFT 1 /* TLB_ENA */
+#define WM8962_TLB_ENA_WIDTH 1 /* TLB_ENA */
+#define WM8962_TLB_MODE 0x0001 /* TLB_MODE */
+#define WM8962_TLB_MODE_MASK 0x0001 /* TLB_MODE */
+#define WM8962_TLB_MODE_SHIFT 0 /* TLB_MODE */
+#define WM8962_TLB_MODE_WIDTH 1 /* TLB_MODE */
+
+/*
+ * R335 (0x14F) - EQ1
+ */
+#define WM8962_EQ_SHARED_COEFF 0x0004 /* EQ_SHARED_COEFF */
+#define WM8962_EQ_SHARED_COEFF_MASK 0x0004 /* EQ_SHARED_COEFF */
+#define WM8962_EQ_SHARED_COEFF_SHIFT 2 /* EQ_SHARED_COEFF */
+#define WM8962_EQ_SHARED_COEFF_WIDTH 1 /* EQ_SHARED_COEFF */
+#define WM8962_EQ_SHARED_COEFF_SEL 0x0002 /* EQ_SHARED_COEFF_SEL */
+#define WM8962_EQ_SHARED_COEFF_SEL_MASK 0x0002 /* EQ_SHARED_COEFF_SEL */
+#define WM8962_EQ_SHARED_COEFF_SEL_SHIFT 1 /* EQ_SHARED_COEFF_SEL */
+#define WM8962_EQ_SHARED_COEFF_SEL_WIDTH 1 /* EQ_SHARED_COEFF_SEL */
+#define WM8962_EQ_ENA 0x0001 /* EQ_ENA */
+#define WM8962_EQ_ENA_MASK 0x0001 /* EQ_ENA */
+#define WM8962_EQ_ENA_SHIFT 0 /* EQ_ENA */
+#define WM8962_EQ_ENA_WIDTH 1 /* EQ_ENA */
+
+/*
+ * R336 (0x150) - EQ2
+ */
+#define WM8962_EQL_B1_GAIN_MASK 0xF800 /* EQL_B1_GAIN - [15:11] */
+#define WM8962_EQL_B1_GAIN_SHIFT 11 /* EQL_B1_GAIN - [15:11] */
+#define WM8962_EQL_B1_GAIN_WIDTH 5 /* EQL_B1_GAIN - [15:11] */
+#define WM8962_EQL_B2_GAIN_MASK 0x07C0 /* EQL_B2_GAIN - [10:6] */
+#define WM8962_EQL_B2_GAIN_SHIFT 6 /* EQL_B2_GAIN - [10:6] */
+#define WM8962_EQL_B2_GAIN_WIDTH 5 /* EQL_B2_GAIN - [10:6] */
+#define WM8962_EQL_B3_GAIN_MASK 0x003E /* EQL_B3_GAIN - [5:1] */
+#define WM8962_EQL_B3_GAIN_SHIFT 1 /* EQL_B3_GAIN - [5:1] */
+#define WM8962_EQL_B3_GAIN_WIDTH 5 /* EQL_B3_GAIN - [5:1] */
+
+/*
+ * R337 (0x151) - EQ3
+ */
+#define WM8962_EQL_B4_GAIN_MASK 0xF800 /* EQL_B4_GAIN - [15:11] */
+#define WM8962_EQL_B4_GAIN_SHIFT 11 /* EQL_B4_GAIN - [15:11] */
+#define WM8962_EQL_B4_GAIN_WIDTH 5 /* EQL_B4_GAIN - [15:11] */
+#define WM8962_EQL_B5_GAIN_MASK 0x07C0 /* EQL_B5_GAIN - [10:6] */
+#define WM8962_EQL_B5_GAIN_SHIFT 6 /* EQL_B5_GAIN - [10:6] */
+#define WM8962_EQL_B5_GAIN_WIDTH 5 /* EQL_B5_GAIN - [10:6] */
+
+/*
+ * R338 (0x152) - EQ4
+ */
+#define WM8962_EQL_B1_A_MASK 0xFFFF /* EQL_B1_A - [15:0] */
+#define WM8962_EQL_B1_A_SHIFT 0 /* EQL_B1_A - [15:0] */
+#define WM8962_EQL_B1_A_WIDTH 16 /* EQL_B1_A - [15:0] */
+
+/*
+ * R339 (0x153) - EQ5
+ */
+#define WM8962_EQL_B1_B_MASK 0xFFFF /* EQL_B1_B - [15:0] */
+#define WM8962_EQL_B1_B_SHIFT 0 /* EQL_B1_B - [15:0] */
+#define WM8962_EQL_B1_B_WIDTH 16 /* EQL_B1_B - [15:0] */
+
+/*
+ * R340 (0x154) - EQ6
+ */
+#define WM8962_EQL_B1_PG_MASK 0xFFFF /* EQL_B1_PG - [15:0] */
+#define WM8962_EQL_B1_PG_SHIFT 0 /* EQL_B1_PG - [15:0] */
+#define WM8962_EQL_B1_PG_WIDTH 16 /* EQL_B1_PG - [15:0] */
+
+/*
+ * R341 (0x155) - EQ7
+ */
+#define WM8962_EQL_B2_A_MASK 0xFFFF /* EQL_B2_A - [15:0] */
+#define WM8962_EQL_B2_A_SHIFT 0 /* EQL_B2_A - [15:0] */
+#define WM8962_EQL_B2_A_WIDTH 16 /* EQL_B2_A - [15:0] */
+
+/*
+ * R342 (0x156) - EQ8
+ */
+#define WM8962_EQL_B2_B_MASK 0xFFFF /* EQL_B2_B - [15:0] */
+#define WM8962_EQL_B2_B_SHIFT 0 /* EQL_B2_B - [15:0] */
+#define WM8962_EQL_B2_B_WIDTH 16 /* EQL_B2_B - [15:0] */
+
+/*
+ * R343 (0x157) - EQ9
+ */
+#define WM8962_EQL_B2_C_MASK 0xFFFF /* EQL_B2_C - [15:0] */
+#define WM8962_EQL_B2_C_SHIFT 0 /* EQL_B2_C - [15:0] */
+#define WM8962_EQL_B2_C_WIDTH 16 /* EQL_B2_C - [15:0] */
+
+/*
+ * R344 (0x158) - EQ10
+ */
+#define WM8962_EQL_B2_PG_MASK 0xFFFF /* EQL_B2_PG - [15:0] */
+#define WM8962_EQL_B2_PG_SHIFT 0 /* EQL_B2_PG - [15:0] */
+#define WM8962_EQL_B2_PG_WIDTH 16 /* EQL_B2_PG - [15:0] */
+
+/*
+ * R345 (0x159) - EQ11
+ */
+#define WM8962_EQL_B3_A_MASK 0xFFFF /* EQL_B3_A - [15:0] */
+#define WM8962_EQL_B3_A_SHIFT 0 /* EQL_B3_A - [15:0] */
+#define WM8962_EQL_B3_A_WIDTH 16 /* EQL_B3_A - [15:0] */
+
+/*
+ * R346 (0x15A) - EQ12
+ */
+#define WM8962_EQL_B3_B_MASK 0xFFFF /* EQL_B3_B - [15:0] */
+#define WM8962_EQL_B3_B_SHIFT 0 /* EQL_B3_B - [15:0] */
+#define WM8962_EQL_B3_B_WIDTH 16 /* EQL_B3_B - [15:0] */
+
+/*
+ * R347 (0x15B) - EQ13
+ */
+#define WM8962_EQL_B3_C_MASK 0xFFFF /* EQL_B3_C - [15:0] */
+#define WM8962_EQL_B3_C_SHIFT 0 /* EQL_B3_C - [15:0] */
+#define WM8962_EQL_B3_C_WIDTH 16 /* EQL_B3_C - [15:0] */
+
+/*
+ * R348 (0x15C) - EQ14
+ */
+#define WM8962_EQL_B3_PG_MASK 0xFFFF /* EQL_B3_PG - [15:0] */
+#define WM8962_EQL_B3_PG_SHIFT 0 /* EQL_B3_PG - [15:0] */
+#define WM8962_EQL_B3_PG_WIDTH 16 /* EQL_B3_PG - [15:0] */
+
+/*
+ * R349 (0x15D) - EQ15
+ */
+#define WM8962_EQL_B4_A_MASK 0xFFFF /* EQL_B4_A - [15:0] */
+#define WM8962_EQL_B4_A_SHIFT 0 /* EQL_B4_A - [15:0] */
+#define WM8962_EQL_B4_A_WIDTH 16 /* EQL_B4_A - [15:0] */
+
+/*
+ * R350 (0x15E) - EQ16
+ */
+#define WM8962_EQL_B4_B_MASK 0xFFFF /* EQL_B4_B - [15:0] */
+#define WM8962_EQL_B4_B_SHIFT 0 /* EQL_B4_B - [15:0] */
+#define WM8962_EQL_B4_B_WIDTH 16 /* EQL_B4_B - [15:0] */
+
+/*
+ * R351 (0x15F) - EQ17
+ */
+#define WM8962_EQL_B4_C_MASK 0xFFFF /* EQL_B4_C - [15:0] */
+#define WM8962_EQL_B4_C_SHIFT 0 /* EQL_B4_C - [15:0] */
+#define WM8962_EQL_B4_C_WIDTH 16 /* EQL_B4_C - [15:0] */
+
+/*
+ * R352 (0x160) - EQ18
+ */
+#define WM8962_EQL_B4_PG_MASK 0xFFFF /* EQL_B4_PG - [15:0] */
+#define WM8962_EQL_B4_PG_SHIFT 0 /* EQL_B4_PG - [15:0] */
+#define WM8962_EQL_B4_PG_WIDTH 16 /* EQL_B4_PG - [15:0] */
+
+/*
+ * R353 (0x161) - EQ19
+ */
+#define WM8962_EQL_B5_A_MASK 0xFFFF /* EQL_B5_A - [15:0] */
+#define WM8962_EQL_B5_A_SHIFT 0 /* EQL_B5_A - [15:0] */
+#define WM8962_EQL_B5_A_WIDTH 16 /* EQL_B5_A - [15:0] */
+
+/*
+ * R354 (0x162) - EQ20
+ */
+#define WM8962_EQL_B5_B_MASK 0xFFFF /* EQL_B5_B - [15:0] */
+#define WM8962_EQL_B5_B_SHIFT 0 /* EQL_B5_B - [15:0] */
+#define WM8962_EQL_B5_B_WIDTH 16 /* EQL_B5_B - [15:0] */
+
+/*
+ * R355 (0x163) - EQ21
+ */
+#define WM8962_EQL_B5_PG_MASK 0xFFFF /* EQL_B5_PG - [15:0] */
+#define WM8962_EQL_B5_PG_SHIFT 0 /* EQL_B5_PG - [15:0] */
+#define WM8962_EQL_B5_PG_WIDTH 16 /* EQL_B5_PG - [15:0] */
+
+/*
+ * R356 (0x164) - EQ22
+ */
+#define WM8962_EQR_B1_GAIN_MASK 0xF800 /* EQR_B1_GAIN - [15:11] */
+#define WM8962_EQR_B1_GAIN_SHIFT 11 /* EQR_B1_GAIN - [15:11] */
+#define WM8962_EQR_B1_GAIN_WIDTH 5 /* EQR_B1_GAIN - [15:11] */
+#define WM8962_EQR_B2_GAIN_MASK 0x07C0 /* EQR_B2_GAIN - [10:6] */
+#define WM8962_EQR_B2_GAIN_SHIFT 6 /* EQR_B2_GAIN - [10:6] */
+#define WM8962_EQR_B2_GAIN_WIDTH 5 /* EQR_B2_GAIN - [10:6] */
+#define WM8962_EQR_B3_GAIN_MASK 0x003E /* EQR_B3_GAIN - [5:1] */
+#define WM8962_EQR_B3_GAIN_SHIFT 1 /* EQR_B3_GAIN - [5:1] */
+#define WM8962_EQR_B3_GAIN_WIDTH 5 /* EQR_B3_GAIN - [5:1] */
+
+/*
+ * R357 (0x165) - EQ23
+ */
+#define WM8962_EQR_B4_GAIN_MASK 0xF800 /* EQR_B4_GAIN - [15:11] */
+#define WM8962_EQR_B4_GAIN_SHIFT 11 /* EQR_B4_GAIN - [15:11] */
+#define WM8962_EQR_B4_GAIN_WIDTH 5 /* EQR_B4_GAIN - [15:11] */
+#define WM8962_EQR_B5_GAIN_MASK 0x07C0 /* EQR_B5_GAIN - [10:6] */
+#define WM8962_EQR_B5_GAIN_SHIFT 6 /* EQR_B5_GAIN - [10:6] */
+#define WM8962_EQR_B5_GAIN_WIDTH 5 /* EQR_B5_GAIN - [10:6] */
+
+/*
+ * R358 (0x166) - EQ24
+ */
+#define WM8962_EQR_B1_A_MASK 0xFFFF /* EQR_B1_A - [15:0] */
+#define WM8962_EQR_B1_A_SHIFT 0 /* EQR_B1_A - [15:0] */
+#define WM8962_EQR_B1_A_WIDTH 16 /* EQR_B1_A - [15:0] */
+
+/*
+ * R359 (0x167) - EQ25
+ */
+#define WM8962_EQR_B1_B_MASK 0xFFFF /* EQR_B1_B - [15:0] */
+#define WM8962_EQR_B1_B_SHIFT 0 /* EQR_B1_B - [15:0] */
+#define WM8962_EQR_B1_B_WIDTH 16 /* EQR_B1_B - [15:0] */
+
+/*
+ * R360 (0x168) - EQ26
+ */
+#define WM8962_EQR_B1_PG_MASK 0xFFFF /* EQR_B1_PG - [15:0] */
+#define WM8962_EQR_B1_PG_SHIFT 0 /* EQR_B1_PG - [15:0] */
+#define WM8962_EQR_B1_PG_WIDTH 16 /* EQR_B1_PG - [15:0] */
+
+/*
+ * R361 (0x169) - EQ27
+ */
+#define WM8962_EQR_B2_A_MASK 0xFFFF /* EQR_B2_A - [15:0] */
+#define WM8962_EQR_B2_A_SHIFT 0 /* EQR_B2_A - [15:0] */
+#define WM8962_EQR_B2_A_WIDTH 16 /* EQR_B2_A - [15:0] */
+
+/*
+ * R362 (0x16A) - EQ28
+ */
+#define WM8962_EQR_B2_B_MASK 0xFFFF /* EQR_B2_B - [15:0] */
+#define WM8962_EQR_B2_B_SHIFT 0 /* EQR_B2_B - [15:0] */
+#define WM8962_EQR_B2_B_WIDTH 16 /* EQR_B2_B - [15:0] */
+
+/*
+ * R363 (0x16B) - EQ29
+ */
+#define WM8962_EQR_B2_C_MASK 0xFFFF /* EQR_B2_C - [15:0] */
+#define WM8962_EQR_B2_C_SHIFT 0 /* EQR_B2_C - [15:0] */
+#define WM8962_EQR_B2_C_WIDTH 16 /* EQR_B2_C - [15:0] */
+
+/*
+ * R364 (0x16C) - EQ30
+ */
+#define WM8962_EQR_B2_PG_MASK 0xFFFF /* EQR_B2_PG - [15:0] */
+#define WM8962_EQR_B2_PG_SHIFT 0 /* EQR_B2_PG - [15:0] */
+#define WM8962_EQR_B2_PG_WIDTH 16 /* EQR_B2_PG - [15:0] */
+
+/*
+ * R365 (0x16D) - EQ31
+ */
+#define WM8962_EQR_B3_A_MASK 0xFFFF /* EQR_B3_A - [15:0] */
+#define WM8962_EQR_B3_A_SHIFT 0 /* EQR_B3_A - [15:0] */
+#define WM8962_EQR_B3_A_WIDTH 16 /* EQR_B3_A - [15:0] */
+
+/*
+ * R366 (0x16E) - EQ32
+ */
+#define WM8962_EQR_B3_B_MASK 0xFFFF /* EQR_B3_B - [15:0] */
+#define WM8962_EQR_B3_B_SHIFT 0 /* EQR_B3_B - [15:0] */
+#define WM8962_EQR_B3_B_WIDTH 16 /* EQR_B3_B - [15:0] */
+
+/*
+ * R367 (0x16F) - EQ33
+ */
+#define WM8962_EQR_B3_C_MASK 0xFFFF /* EQR_B3_C - [15:0] */
+#define WM8962_EQR_B3_C_SHIFT 0 /* EQR_B3_C - [15:0] */
+#define WM8962_EQR_B3_C_WIDTH 16 /* EQR_B3_C - [15:0] */
+
+/*
+ * R368 (0x170) - EQ34
+ */
+#define WM8962_EQR_B3_PG_MASK 0xFFFF /* EQR_B3_PG - [15:0] */
+#define WM8962_EQR_B3_PG_SHIFT 0 /* EQR_B3_PG - [15:0] */
+#define WM8962_EQR_B3_PG_WIDTH 16 /* EQR_B3_PG - [15:0] */
+
+/*
+ * R369 (0x171) - EQ35
+ */
+#define WM8962_EQR_B4_A_MASK 0xFFFF /* EQR_B4_A - [15:0] */
+#define WM8962_EQR_B4_A_SHIFT 0 /* EQR_B4_A - [15:0] */
+#define WM8962_EQR_B4_A_WIDTH 16 /* EQR_B4_A - [15:0] */
+
+/*
+ * R370 (0x172) - EQ36
+ */
+#define WM8962_EQR_B4_B_MASK 0xFFFF /* EQR_B4_B - [15:0] */
+#define WM8962_EQR_B4_B_SHIFT 0 /* EQR_B4_B - [15:0] */
+#define WM8962_EQR_B4_B_WIDTH 16 /* EQR_B4_B - [15:0] */
+
+/*
+ * R371 (0x173) - EQ37
+ */
+#define WM8962_EQR_B4_C_MASK 0xFFFF /* EQR_B4_C - [15:0] */
+#define WM8962_EQR_B4_C_SHIFT 0 /* EQR_B4_C - [15:0] */
+#define WM8962_EQR_B4_C_WIDTH 16 /* EQR_B4_C - [15:0] */
+
+/*
+ * R372 (0x174) - EQ38
+ */
+#define WM8962_EQR_B4_PG_MASK 0xFFFF /* EQR_B4_PG - [15:0] */
+#define WM8962_EQR_B4_PG_SHIFT 0 /* EQR_B4_PG - [15:0] */
+#define WM8962_EQR_B4_PG_WIDTH 16 /* EQR_B4_PG - [15:0] */
+
+/*
+ * R373 (0x175) - EQ39
+ */
+#define WM8962_EQR_B5_A_MASK 0xFFFF /* EQR_B5_A - [15:0] */
+#define WM8962_EQR_B5_A_SHIFT 0 /* EQR_B5_A - [15:0] */
+#define WM8962_EQR_B5_A_WIDTH 16 /* EQR_B5_A - [15:0] */
+
+/*
+ * R374 (0x176) - EQ40
+ */
+#define WM8962_EQR_B5_B_MASK 0xFFFF /* EQR_B5_B - [15:0] */
+#define WM8962_EQR_B5_B_SHIFT 0 /* EQR_B5_B - [15:0] */
+#define WM8962_EQR_B5_B_WIDTH 16 /* EQR_B5_B - [15:0] */
+
+/*
+ * R375 (0x177) - EQ41
+ */
+#define WM8962_EQR_B5_PG_MASK 0xFFFF /* EQR_B5_PG - [15:0] */
+#define WM8962_EQR_B5_PG_SHIFT 0 /* EQR_B5_PG - [15:0] */
+#define WM8962_EQR_B5_PG_WIDTH 16 /* EQR_B5_PG - [15:0] */
+
+/*
+ * R513 (0x201) - GPIO 2
+ */
+#define WM8962_GP2_POL 0x0400 /* GP2_POL */
+#define WM8962_GP2_POL_MASK 0x0400 /* GP2_POL */
+#define WM8962_GP2_POL_SHIFT 10 /* GP2_POL */
+#define WM8962_GP2_POL_WIDTH 1 /* GP2_POL */
+#define WM8962_GP2_LVL 0x0040 /* GP2_LVL */
+#define WM8962_GP2_LVL_MASK 0x0040 /* GP2_LVL */
+#define WM8962_GP2_LVL_SHIFT 6 /* GP2_LVL */
+#define WM8962_GP2_LVL_WIDTH 1 /* GP2_LVL */
+#define WM8962_GP2_FN_MASK 0x001F /* GP2_FN - [4:0] */
+#define WM8962_GP2_FN_SHIFT 0 /* GP2_FN - [4:0] */
+#define WM8962_GP2_FN_WIDTH 5 /* GP2_FN - [4:0] */
+
+/*
+ * R514 (0x202) - GPIO 3
+ */
+#define WM8962_GP3_POL 0x0400 /* GP3_POL */
+#define WM8962_GP3_POL_MASK 0x0400 /* GP3_POL */
+#define WM8962_GP3_POL_SHIFT 10 /* GP3_POL */
+#define WM8962_GP3_POL_WIDTH 1 /* GP3_POL */
+#define WM8962_GP3_LVL 0x0040 /* GP3_LVL */
+#define WM8962_GP3_LVL_MASK 0x0040 /* GP3_LVL */
+#define WM8962_GP3_LVL_SHIFT 6 /* GP3_LVL */
+#define WM8962_GP3_LVL_WIDTH 1 /* GP3_LVL */
+#define WM8962_GP3_FN_MASK 0x001F /* GP3_FN - [4:0] */
+#define WM8962_GP3_FN_SHIFT 0 /* GP3_FN - [4:0] */
+#define WM8962_GP3_FN_WIDTH 5 /* GP3_FN - [4:0] */
+
+/*
+ * R516 (0x204) - GPIO 5
+ */
+#define WM8962_GP5_DIR 0x8000 /* GP5_DIR */
+#define WM8962_GP5_DIR_MASK 0x8000 /* GP5_DIR */
+#define WM8962_GP5_DIR_SHIFT 15 /* GP5_DIR */
+#define WM8962_GP5_DIR_WIDTH 1 /* GP5_DIR */
+#define WM8962_GP5_PU 0x4000 /* GP5_PU */
+#define WM8962_GP5_PU_MASK 0x4000 /* GP5_PU */
+#define WM8962_GP5_PU_SHIFT 14 /* GP5_PU */
+#define WM8962_GP5_PU_WIDTH 1 /* GP5_PU */
+#define WM8962_GP5_PD 0x2000 /* GP5_PD */
+#define WM8962_GP5_PD_MASK 0x2000 /* GP5_PD */
+#define WM8962_GP5_PD_SHIFT 13 /* GP5_PD */
+#define WM8962_GP5_PD_WIDTH 1 /* GP5_PD */
+#define WM8962_GP5_POL 0x0400 /* GP5_POL */
+#define WM8962_GP5_POL_MASK 0x0400 /* GP5_POL */
+#define WM8962_GP5_POL_SHIFT 10 /* GP5_POL */
+#define WM8962_GP5_POL_WIDTH 1 /* GP5_POL */
+#define WM8962_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */
+#define WM8962_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */
+#define WM8962_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */
+#define WM8962_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */
+#define WM8962_GP5_DB 0x0100 /* GP5_DB */
+#define WM8962_GP5_DB_MASK 0x0100 /* GP5_DB */
+#define WM8962_GP5_DB_SHIFT 8 /* GP5_DB */
+#define WM8962_GP5_DB_WIDTH 1 /* GP5_DB */
+#define WM8962_GP5_LVL 0x0040 /* GP5_LVL */
+#define WM8962_GP5_LVL_MASK 0x0040 /* GP5_LVL */
+#define WM8962_GP5_LVL_SHIFT 6 /* GP5_LVL */
+#define WM8962_GP5_LVL_WIDTH 1 /* GP5_LVL */
+#define WM8962_GP5_FN_MASK 0x001F /* GP5_FN - [4:0] */
+#define WM8962_GP5_FN_SHIFT 0 /* GP5_FN - [4:0] */
+#define WM8962_GP5_FN_WIDTH 5 /* GP5_FN - [4:0] */
+
+/*
+ * R517 (0x205) - GPIO 6
+ */
+#define WM8962_GP6_DIR 0x8000 /* GP6_DIR */
+#define WM8962_GP6_DIR_MASK 0x8000 /* GP6_DIR */
+#define WM8962_GP6_DIR_SHIFT 15 /* GP6_DIR */
+#define WM8962_GP6_DIR_WIDTH 1 /* GP6_DIR */
+#define WM8962_GP6_PU 0x4000 /* GP6_PU */
+#define WM8962_GP6_PU_MASK 0x4000 /* GP6_PU */
+#define WM8962_GP6_PU_SHIFT 14 /* GP6_PU */
+#define WM8962_GP6_PU_WIDTH 1 /* GP6_PU */
+#define WM8962_GP6_PD 0x2000 /* GP6_PD */
+#define WM8962_GP6_PD_MASK 0x2000 /* GP6_PD */
+#define WM8962_GP6_PD_SHIFT 13 /* GP6_PD */
+#define WM8962_GP6_PD_WIDTH 1 /* GP6_PD */
+#define WM8962_GP6_POL 0x0400 /* GP6_POL */
+#define WM8962_GP6_POL_MASK 0x0400 /* GP6_POL */
+#define WM8962_GP6_POL_SHIFT 10 /* GP6_POL */
+#define WM8962_GP6_POL_WIDTH 1 /* GP6_POL */
+#define WM8962_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */
+#define WM8962_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */
+#define WM8962_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */
+#define WM8962_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */
+#define WM8962_GP6_DB 0x0100 /* GP6_DB */
+#define WM8962_GP6_DB_MASK 0x0100 /* GP6_DB */
+#define WM8962_GP6_DB_SHIFT 8 /* GP6_DB */
+#define WM8962_GP6_DB_WIDTH 1 /* GP6_DB */
+#define WM8962_GP6_LVL 0x0040 /* GP6_LVL */
+#define WM8962_GP6_LVL_MASK 0x0040 /* GP6_LVL */
+#define WM8962_GP6_LVL_SHIFT 6 /* GP6_LVL */
+#define WM8962_GP6_LVL_WIDTH 1 /* GP6_LVL */
+#define WM8962_GP6_FN_MASK 0x001F /* GP6_FN - [4:0] */
+#define WM8962_GP6_FN_SHIFT 0 /* GP6_FN - [4:0] */
+#define WM8962_GP6_FN_WIDTH 5 /* GP6_FN - [4:0] */
+
+/*
+ * R560 (0x230) - Interrupt Status 1
+ */
+#define WM8962_GP6_EINT 0x0020 /* GP6_EINT */
+#define WM8962_GP6_EINT_MASK 0x0020 /* GP6_EINT */
+#define WM8962_GP6_EINT_SHIFT 5 /* GP6_EINT */
+#define WM8962_GP6_EINT_WIDTH 1 /* GP6_EINT */
+#define WM8962_GP5_EINT 0x0010 /* GP5_EINT */
+#define WM8962_GP5_EINT_MASK 0x0010 /* GP5_EINT */
+#define WM8962_GP5_EINT_SHIFT 4 /* GP5_EINT */
+#define WM8962_GP5_EINT_WIDTH 1 /* GP5_EINT */
+
+/*
+ * R561 (0x231) - Interrupt Status 2
+ */
+#define WM8962_MICSCD_EINT 0x8000 /* MICSCD_EINT */
+#define WM8962_MICSCD_EINT_MASK 0x8000 /* MICSCD_EINT */
+#define WM8962_MICSCD_EINT_SHIFT 15 /* MICSCD_EINT */
+#define WM8962_MICSCD_EINT_WIDTH 1 /* MICSCD_EINT */
+#define WM8962_MICD_EINT 0x4000 /* MICD_EINT */
+#define WM8962_MICD_EINT_MASK 0x4000 /* MICD_EINT */
+#define WM8962_MICD_EINT_SHIFT 14 /* MICD_EINT */
+#define WM8962_MICD_EINT_WIDTH 1 /* MICD_EINT */
+#define WM8962_FIFOS_ERR_EINT 0x2000 /* FIFOS_ERR_EINT */
+#define WM8962_FIFOS_ERR_EINT_MASK 0x2000 /* FIFOS_ERR_EINT */
+#define WM8962_FIFOS_ERR_EINT_SHIFT 13 /* FIFOS_ERR_EINT */
+#define WM8962_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */
+#define WM8962_ALC_LOCK_EINT 0x1000 /* ALC_LOCK_EINT */
+#define WM8962_ALC_LOCK_EINT_MASK 0x1000 /* ALC_LOCK_EINT */
+#define WM8962_ALC_LOCK_EINT_SHIFT 12 /* ALC_LOCK_EINT */
+#define WM8962_ALC_LOCK_EINT_WIDTH 1 /* ALC_LOCK_EINT */
+#define WM8962_ALC_THRESH_EINT 0x0800 /* ALC_THRESH_EINT */
+#define WM8962_ALC_THRESH_EINT_MASK 0x0800 /* ALC_THRESH_EINT */
+#define WM8962_ALC_THRESH_EINT_SHIFT 11 /* ALC_THRESH_EINT */
+#define WM8962_ALC_THRESH_EINT_WIDTH 1 /* ALC_THRESH_EINT */
+#define WM8962_ALC_SAT_EINT 0x0400 /* ALC_SAT_EINT */
+#define WM8962_ALC_SAT_EINT_MASK 0x0400 /* ALC_SAT_EINT */
+#define WM8962_ALC_SAT_EINT_SHIFT 10 /* ALC_SAT_EINT */
+#define WM8962_ALC_SAT_EINT_WIDTH 1 /* ALC_SAT_EINT */
+#define WM8962_ALC_PKOVR_EINT 0x0200 /* ALC_PKOVR_EINT */
+#define WM8962_ALC_PKOVR_EINT_MASK 0x0200 /* ALC_PKOVR_EINT */
+#define WM8962_ALC_PKOVR_EINT_SHIFT 9 /* ALC_PKOVR_EINT */
+#define WM8962_ALC_PKOVR_EINT_WIDTH 1 /* ALC_PKOVR_EINT */
+#define WM8962_ALC_NGATE_EINT 0x0100 /* ALC_NGATE_EINT */
+#define WM8962_ALC_NGATE_EINT_MASK 0x0100 /* ALC_NGATE_EINT */
+#define WM8962_ALC_NGATE_EINT_SHIFT 8 /* ALC_NGATE_EINT */
+#define WM8962_ALC_NGATE_EINT_WIDTH 1 /* ALC_NGATE_EINT */
+#define WM8962_WSEQ_DONE_EINT 0x0080 /* WSEQ_DONE_EINT */
+#define WM8962_WSEQ_DONE_EINT_MASK 0x0080 /* WSEQ_DONE_EINT */
+#define WM8962_WSEQ_DONE_EINT_SHIFT 7 /* WSEQ_DONE_EINT */
+#define WM8962_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */
+#define WM8962_DRC_ACTDET_EINT 0x0040 /* DRC_ACTDET_EINT */
+#define WM8962_DRC_ACTDET_EINT_MASK 0x0040 /* DRC_ACTDET_EINT */
+#define WM8962_DRC_ACTDET_EINT_SHIFT 6 /* DRC_ACTDET_EINT */
+#define WM8962_DRC_ACTDET_EINT_WIDTH 1 /* DRC_ACTDET_EINT */
+#define WM8962_FLL_LOCK_EINT 0x0020 /* FLL_LOCK_EINT */
+#define WM8962_FLL_LOCK_EINT_MASK 0x0020 /* FLL_LOCK_EINT */
+#define WM8962_FLL_LOCK_EINT_SHIFT 5 /* FLL_LOCK_EINT */
+#define WM8962_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */
+#define WM8962_PLL3_LOCK_EINT 0x0008 /* PLL3_LOCK_EINT */
+#define WM8962_PLL3_LOCK_EINT_MASK 0x0008 /* PLL3_LOCK_EINT */
+#define WM8962_PLL3_LOCK_EINT_SHIFT 3 /* PLL3_LOCK_EINT */
+#define WM8962_PLL3_LOCK_EINT_WIDTH 1 /* PLL3_LOCK_EINT */
+#define WM8962_PLL2_LOCK_EINT 0x0004 /* PLL2_LOCK_EINT */
+#define WM8962_PLL2_LOCK_EINT_MASK 0x0004 /* PLL2_LOCK_EINT */
+#define WM8962_PLL2_LOCK_EINT_SHIFT 2 /* PLL2_LOCK_EINT */
+#define WM8962_PLL2_LOCK_EINT_WIDTH 1 /* PLL2_LOCK_EINT */
+#define WM8962_TEMP_SHUT_EINT 0x0001 /* TEMP_SHUT_EINT */
+#define WM8962_TEMP_SHUT_EINT_MASK 0x0001 /* TEMP_SHUT_EINT */
+#define WM8962_TEMP_SHUT_EINT_SHIFT 0 /* TEMP_SHUT_EINT */
+#define WM8962_TEMP_SHUT_EINT_WIDTH 1 /* TEMP_SHUT_EINT */
+
+/*
+ * R568 (0x238) - Interrupt Status 1 Mask
+ */
+#define WM8962_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */
+#define WM8962_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */
+#define WM8962_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */
+#define WM8962_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */
+#define WM8962_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */
+#define WM8962_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */
+#define WM8962_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */
+#define WM8962_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */
+
+/*
+ * R569 (0x239) - Interrupt Status 2 Mask
+ */
+#define WM8962_IM_MICSCD_EINT 0x8000 /* IM_MICSCD_EINT */
+#define WM8962_IM_MICSCD_EINT_MASK 0x8000 /* IM_MICSCD_EINT */
+#define WM8962_IM_MICSCD_EINT_SHIFT 15 /* IM_MICSCD_EINT */
+#define WM8962_IM_MICSCD_EINT_WIDTH 1 /* IM_MICSCD_EINT */
+#define WM8962_IM_MICD_EINT 0x4000 /* IM_MICD_EINT */
+#define WM8962_IM_MICD_EINT_MASK 0x4000 /* IM_MICD_EINT */
+#define WM8962_IM_MICD_EINT_SHIFT 14 /* IM_MICD_EINT */
+#define WM8962_IM_MICD_EINT_WIDTH 1 /* IM_MICD_EINT */
+#define WM8962_IM_FIFOS_ERR_EINT 0x2000 /* IM_FIFOS_ERR_EINT */
+#define WM8962_IM_FIFOS_ERR_EINT_MASK 0x2000 /* IM_FIFOS_ERR_EINT */
+#define WM8962_IM_FIFOS_ERR_EINT_SHIFT 13 /* IM_FIFOS_ERR_EINT */
+#define WM8962_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */
+#define WM8962_IM_ALC_LOCK_EINT 0x1000 /* IM_ALC_LOCK_EINT */
+#define WM8962_IM_ALC_LOCK_EINT_MASK 0x1000 /* IM_ALC_LOCK_EINT */
+#define WM8962_IM_ALC_LOCK_EINT_SHIFT 12 /* IM_ALC_LOCK_EINT */
+#define WM8962_IM_ALC_LOCK_EINT_WIDTH 1 /* IM_ALC_LOCK_EINT */
+#define WM8962_IM_ALC_THRESH_EINT 0x0800 /* IM_ALC_THRESH_EINT */
+#define WM8962_IM_ALC_THRESH_EINT_MASK 0x0800 /* IM_ALC_THRESH_EINT */
+#define WM8962_IM_ALC_THRESH_EINT_SHIFT 11 /* IM_ALC_THRESH_EINT */
+#define WM8962_IM_ALC_THRESH_EINT_WIDTH 1 /* IM_ALC_THRESH_EINT */
+#define WM8962_IM_ALC_SAT_EINT 0x0400 /* IM_ALC_SAT_EINT */
+#define WM8962_IM_ALC_SAT_EINT_MASK 0x0400 /* IM_ALC_SAT_EINT */
+#define WM8962_IM_ALC_SAT_EINT_SHIFT 10 /* IM_ALC_SAT_EINT */
+#define WM8962_IM_ALC_SAT_EINT_WIDTH 1 /* IM_ALC_SAT_EINT */
+#define WM8962_IM_ALC_PKOVR_EINT 0x0200 /* IM_ALC_PKOVR_EINT */
+#define WM8962_IM_ALC_PKOVR_EINT_MASK 0x0200 /* IM_ALC_PKOVR_EINT */
+#define WM8962_IM_ALC_PKOVR_EINT_SHIFT 9 /* IM_ALC_PKOVR_EINT */
+#define WM8962_IM_ALC_PKOVR_EINT_WIDTH 1 /* IM_ALC_PKOVR_EINT */
+#define WM8962_IM_ALC_NGATE_EINT 0x0100 /* IM_ALC_NGATE_EINT */
+#define WM8962_IM_ALC_NGATE_EINT_MASK 0x0100 /* IM_ALC_NGATE_EINT */
+#define WM8962_IM_ALC_NGATE_EINT_SHIFT 8 /* IM_ALC_NGATE_EINT */
+#define WM8962_IM_ALC_NGATE_EINT_WIDTH 1 /* IM_ALC_NGATE_EINT */
+#define WM8962_IM_WSEQ_DONE_EINT 0x0080 /* IM_WSEQ_DONE_EINT */
+#define WM8962_IM_WSEQ_DONE_EINT_MASK 0x0080 /* IM_WSEQ_DONE_EINT */
+#define WM8962_IM_WSEQ_DONE_EINT_SHIFT 7 /* IM_WSEQ_DONE_EINT */
+#define WM8962_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */
+#define WM8962_IM_DRC_ACTDET_EINT 0x0040 /* IM_DRC_ACTDET_EINT */
+#define WM8962_IM_DRC_ACTDET_EINT_MASK 0x0040 /* IM_DRC_ACTDET_EINT */
+#define WM8962_IM_DRC_ACTDET_EINT_SHIFT 6 /* IM_DRC_ACTDET_EINT */
+#define WM8962_IM_DRC_ACTDET_EINT_WIDTH 1 /* IM_DRC_ACTDET_EINT */
+#define WM8962_IM_FLL_LOCK_EINT 0x0020 /* IM_FLL_LOCK_EINT */
+#define WM8962_IM_FLL_LOCK_EINT_MASK 0x0020 /* IM_FLL_LOCK_EINT */
+#define WM8962_IM_FLL_LOCK_EINT_SHIFT 5 /* IM_FLL_LOCK_EINT */
+#define WM8962_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */
+#define WM8962_IM_PLL3_LOCK_EINT 0x0008 /* IM_PLL3_LOCK_EINT */
+#define WM8962_IM_PLL3_LOCK_EINT_MASK 0x0008 /* IM_PLL3_LOCK_EINT */
+#define WM8962_IM_PLL3_LOCK_EINT_SHIFT 3 /* IM_PLL3_LOCK_EINT */
+#define WM8962_IM_PLL3_LOCK_EINT_WIDTH 1 /* IM_PLL3_LOCK_EINT */
+#define WM8962_IM_PLL2_LOCK_EINT 0x0004 /* IM_PLL2_LOCK_EINT */
+#define WM8962_IM_PLL2_LOCK_EINT_MASK 0x0004 /* IM_PLL2_LOCK_EINT */
+#define WM8962_IM_PLL2_LOCK_EINT_SHIFT 2 /* IM_PLL2_LOCK_EINT */
+#define WM8962_IM_PLL2_LOCK_EINT_WIDTH 1 /* IM_PLL2_LOCK_EINT */
+#define WM8962_IM_TEMP_SHUT_EINT 0x0001 /* IM_TEMP_SHUT_EINT */
+#define WM8962_IM_TEMP_SHUT_EINT_MASK 0x0001 /* IM_TEMP_SHUT_EINT */
+#define WM8962_IM_TEMP_SHUT_EINT_SHIFT 0 /* IM_TEMP_SHUT_EINT */
+#define WM8962_IM_TEMP_SHUT_EINT_WIDTH 1 /* IM_TEMP_SHUT_EINT */
+
+/*
+ * R576 (0x240) - Interrupt Control
+ */
+#define WM8962_IRQ_POL 0x0001 /* IRQ_POL */
+#define WM8962_IRQ_POL_MASK 0x0001 /* IRQ_POL */
+#define WM8962_IRQ_POL_SHIFT 0 /* IRQ_POL */
+#define WM8962_IRQ_POL_WIDTH 1 /* IRQ_POL */
+
+/*
+ * R584 (0x248) - IRQ Debounce
+ */
+#define WM8962_FLL_LOCK_DB 0x0020 /* FLL_LOCK_DB */
+#define WM8962_FLL_LOCK_DB_MASK 0x0020 /* FLL_LOCK_DB */
+#define WM8962_FLL_LOCK_DB_SHIFT 5 /* FLL_LOCK_DB */
+#define WM8962_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */
+#define WM8962_PLL3_LOCK_DB 0x0008 /* PLL3_LOCK_DB */
+#define WM8962_PLL3_LOCK_DB_MASK 0x0008 /* PLL3_LOCK_DB */
+#define WM8962_PLL3_LOCK_DB_SHIFT 3 /* PLL3_LOCK_DB */
+#define WM8962_PLL3_LOCK_DB_WIDTH 1 /* PLL3_LOCK_DB */
+#define WM8962_PLL2_LOCK_DB 0x0004 /* PLL2_LOCK_DB */
+#define WM8962_PLL2_LOCK_DB_MASK 0x0004 /* PLL2_LOCK_DB */
+#define WM8962_PLL2_LOCK_DB_SHIFT 2 /* PLL2_LOCK_DB */
+#define WM8962_PLL2_LOCK_DB_WIDTH 1 /* PLL2_LOCK_DB */
+#define WM8962_TEMP_SHUT_DB 0x0001 /* TEMP_SHUT_DB */
+#define WM8962_TEMP_SHUT_DB_MASK 0x0001 /* TEMP_SHUT_DB */
+#define WM8962_TEMP_SHUT_DB_SHIFT 0 /* TEMP_SHUT_DB */
+#define WM8962_TEMP_SHUT_DB_WIDTH 1 /* TEMP_SHUT_DB */
+
+/*
+ * R586 (0x24A) - MICINT Source Pol
+ */
+#define WM8962_MICSCD_IRQ_POL 0x8000 /* MICSCD_IRQ_POL */
+#define WM8962_MICSCD_IRQ_POL_MASK 0x8000 /* MICSCD_IRQ_POL */
+#define WM8962_MICSCD_IRQ_POL_SHIFT 15 /* MICSCD_IRQ_POL */
+#define WM8962_MICSCD_IRQ_POL_WIDTH 1 /* MICSCD_IRQ_POL */
+#define WM8962_MICD_IRQ_POL 0x4000 /* MICD_IRQ_POL */
+#define WM8962_MICD_IRQ_POL_MASK 0x4000 /* MICD_IRQ_POL */
+#define WM8962_MICD_IRQ_POL_SHIFT 14 /* MICD_IRQ_POL */
+#define WM8962_MICD_IRQ_POL_WIDTH 1 /* MICD_IRQ_POL */
+
+/*
+ * R768 (0x300) - DSP2 Power Management
+ */
+#define WM8962_DSP2_ENA 0x0001 /* DSP2_ENA */
+#define WM8962_DSP2_ENA_MASK 0x0001 /* DSP2_ENA */
+#define WM8962_DSP2_ENA_SHIFT 0 /* DSP2_ENA */
+#define WM8962_DSP2_ENA_WIDTH 1 /* DSP2_ENA */
+
+/*
+ * R1037 (0x40D) - DSP2_ExecControl
+ */
+#define WM8962_DSP2_STOPC 0x0020 /* DSP2_STOPC */
+#define WM8962_DSP2_STOPC_MASK 0x0020 /* DSP2_STOPC */
+#define WM8962_DSP2_STOPC_SHIFT 5 /* DSP2_STOPC */
+#define WM8962_DSP2_STOPC_WIDTH 1 /* DSP2_STOPC */
+#define WM8962_DSP2_STOPS 0x0010 /* DSP2_STOPS */
+#define WM8962_DSP2_STOPS_MASK 0x0010 /* DSP2_STOPS */
+#define WM8962_DSP2_STOPS_SHIFT 4 /* DSP2_STOPS */
+#define WM8962_DSP2_STOPS_WIDTH 1 /* DSP2_STOPS */
+#define WM8962_DSP2_STOPI 0x0008 /* DSP2_STOPI */
+#define WM8962_DSP2_STOPI_MASK 0x0008 /* DSP2_STOPI */
+#define WM8962_DSP2_STOPI_SHIFT 3 /* DSP2_STOPI */
+#define WM8962_DSP2_STOPI_WIDTH 1 /* DSP2_STOPI */
+#define WM8962_DSP2_STOP 0x0004 /* DSP2_STOP */
+#define WM8962_DSP2_STOP_MASK 0x0004 /* DSP2_STOP */
+#define WM8962_DSP2_STOP_SHIFT 2 /* DSP2_STOP */
+#define WM8962_DSP2_STOP_WIDTH 1 /* DSP2_STOP */
+#define WM8962_DSP2_RUNR 0x0002 /* DSP2_RUNR */
+#define WM8962_DSP2_RUNR_MASK 0x0002 /* DSP2_RUNR */
+#define WM8962_DSP2_RUNR_SHIFT 1 /* DSP2_RUNR */
+#define WM8962_DSP2_RUNR_WIDTH 1 /* DSP2_RUNR */
+#define WM8962_DSP2_RUN 0x0001 /* DSP2_RUN */
+#define WM8962_DSP2_RUN_MASK 0x0001 /* DSP2_RUN */
+#define WM8962_DSP2_RUN_SHIFT 0 /* DSP2_RUN */
+#define WM8962_DSP2_RUN_WIDTH 1 /* DSP2_RUN */
+
+/*
+ * R8192 (0x2000) - DSP2 Instruction RAM 0
+ */
+#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_MASK 0x03FF /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
+#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_SHIFT 0 /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
+#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_WIDTH 10 /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
+
+/*
+ * R9216 (0x2400) - DSP2 Address RAM 2
+ */
+#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_MASK 0x003F /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_WIDTH 6 /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
+
+/*
+ * R9217 (0x2401) - DSP2 Address RAM 1
+ */
+#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_MASK 0xFFFF /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_WIDTH 16 /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
+
+/*
+ * R9218 (0x2402) - DSP2 Address RAM 0
+ */
+#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_MASK 0xFFFF /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_WIDTH 16 /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
+
+/*
+ * R12288 (0x3000) - DSP2 Data1 RAM 1
+ */
+#define WM8962_DSP2_DATA1_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA1_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA1_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
+
+/*
+ * R12289 (0x3001) - DSP2 Data1 RAM 0
+ */
+#define WM8962_DSP2_DATA1_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA1_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA1_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
+
+/*
+ * R13312 (0x3400) - DSP2 Data2 RAM 1
+ */
+#define WM8962_DSP2_DATA2_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA2_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA2_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
+
+/*
+ * R13313 (0x3401) - DSP2 Data2 RAM 0
+ */
+#define WM8962_DSP2_DATA2_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA2_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA2_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
+
+/*
+ * R14336 (0x3800) - DSP2 Data3 RAM 1
+ */
+#define WM8962_DSP2_DATA3_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA3_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA3_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
+
+/*
+ * R14337 (0x3801) - DSP2 Data3 RAM 0
+ */
+#define WM8962_DSP2_DATA3_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA3_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA3_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
+
+/*
+ * R15360 (0x3C00) - DSP2 Coeff RAM 0
+ */
+#define WM8962_DSP2_CMAP_RAM_384_11_10_0_MASK 0x07FF /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
+#define WM8962_DSP2_CMAP_RAM_384_11_10_0_SHIFT 0 /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
+#define WM8962_DSP2_CMAP_RAM_384_11_10_0_WIDTH 11 /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
+
+/*
+ * R16384 (0x4000) - RETUNEADC_SHARED_COEFF_1
+ */
+#define WM8962_ADC_RETUNE_SCV 0x0080 /* ADC_RETUNE_SCV */
+#define WM8962_ADC_RETUNE_SCV_MASK 0x0080 /* ADC_RETUNE_SCV */
+#define WM8962_ADC_RETUNE_SCV_SHIFT 7 /* ADC_RETUNE_SCV */
+#define WM8962_ADC_RETUNE_SCV_WIDTH 1 /* ADC_RETUNE_SCV */
+#define WM8962_RETUNEADC_SHARED_COEFF_22_16_MASK 0x007F /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
+#define WM8962_RETUNEADC_SHARED_COEFF_22_16_SHIFT 0 /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
+#define WM8962_RETUNEADC_SHARED_COEFF_22_16_WIDTH 7 /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
+
+/*
+ * R16385 (0x4001) - RETUNEADC_SHARED_COEFF_0
+ */
+#define WM8962_RETUNEADC_SHARED_COEFF_15_00_MASK 0xFFFF /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
+#define WM8962_RETUNEADC_SHARED_COEFF_15_00_SHIFT 0 /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
+#define WM8962_RETUNEADC_SHARED_COEFF_15_00_WIDTH 16 /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
+
+/*
+ * R16386 (0x4002) - RETUNEDAC_SHARED_COEFF_1
+ */
+#define WM8962_DAC_RETUNE_SCV 0x0080 /* DAC_RETUNE_SCV */
+#define WM8962_DAC_RETUNE_SCV_MASK 0x0080 /* DAC_RETUNE_SCV */
+#define WM8962_DAC_RETUNE_SCV_SHIFT 7 /* DAC_RETUNE_SCV */
+#define WM8962_DAC_RETUNE_SCV_WIDTH 1 /* DAC_RETUNE_SCV */
+#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_MASK 0x007F /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
+#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_SHIFT 0 /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
+#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_WIDTH 7 /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
+
+/*
+ * R16387 (0x4003) - RETUNEDAC_SHARED_COEFF_0
+ */
+#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_MASK 0xFFFF /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
+#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_SHIFT 0 /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
+#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_WIDTH 16 /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
+
+/*
+ * R16388 (0x4004) - SOUNDSTAGE_ENABLES_1
+ */
+#define WM8962_SOUNDSTAGE_ENABLES_23_16_MASK 0x00FF /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
+#define WM8962_SOUNDSTAGE_ENABLES_23_16_SHIFT 0 /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
+#define WM8962_SOUNDSTAGE_ENABLES_23_16_WIDTH 8 /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
+
+/*
+ * R16389 (0x4005) - SOUNDSTAGE_ENABLES_0
+ */
+#define WM8962_SOUNDSTAGE_ENABLES_15_06_MASK 0xFFC0 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
+#define WM8962_SOUNDSTAGE_ENABLES_15_06_SHIFT 6 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
+#define WM8962_SOUNDSTAGE_ENABLES_15_06_WIDTH 10 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
+#define WM8962_RTN_ADC_ENA 0x0020 /* RTN_ADC_ENA */
+#define WM8962_RTN_ADC_ENA_MASK 0x0020 /* RTN_ADC_ENA */
+#define WM8962_RTN_ADC_ENA_SHIFT 5 /* RTN_ADC_ENA */
+#define WM8962_RTN_ADC_ENA_WIDTH 1 /* RTN_ADC_ENA */
+#define WM8962_RTN_DAC_ENA 0x0010 /* RTN_DAC_ENA */
+#define WM8962_RTN_DAC_ENA_MASK 0x0010 /* RTN_DAC_ENA */
+#define WM8962_RTN_DAC_ENA_SHIFT 4 /* RTN_DAC_ENA */
+#define WM8962_RTN_DAC_ENA_WIDTH 1 /* RTN_DAC_ENA */
+#define WM8962_HDBASS_ENA 0x0008 /* HDBASS_ENA */
+#define WM8962_HDBASS_ENA_MASK 0x0008 /* HDBASS_ENA */
+#define WM8962_HDBASS_ENA_SHIFT 3 /* HDBASS_ENA */
+#define WM8962_HDBASS_ENA_WIDTH 1 /* HDBASS_ENA */
+#define WM8962_HPF2_ENA 0x0004 /* HPF2_ENA */
+#define WM8962_HPF2_ENA_MASK 0x0004 /* HPF2_ENA */
+#define WM8962_HPF2_ENA_SHIFT 2 /* HPF2_ENA */
+#define WM8962_HPF2_ENA_WIDTH 1 /* HPF2_ENA */
+#define WM8962_HPF1_ENA 0x0002 /* HPF1_ENA */
+#define WM8962_HPF1_ENA_MASK 0x0002 /* HPF1_ENA */
+#define WM8962_HPF1_ENA_SHIFT 1 /* HPF1_ENA */
+#define WM8962_HPF1_ENA_WIDTH 1 /* HPF1_ENA */
+#define WM8962_VSS_ENA 0x0001 /* VSS_ENA */
+#define WM8962_VSS_ENA_MASK 0x0001 /* VSS_ENA */
+#define WM8962_VSS_ENA_SHIFT 0 /* VSS_ENA */
+#define WM8962_VSS_ENA_WIDTH 1 /* VSS_ENA */
+
+int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
+
+#endif
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index a99620f335d2..63f6dbf5d070 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -30,14 +30,13 @@
#include "wm8971.h"
-#define WM8971_VERSION "0.9"
-
#define WM8971_REG_COUNT 43
static struct workqueue_struct *wm8971_workq = NULL;
/* codec private data */
struct wm8971_priv {
+ enum snd_soc_control_type control_type;
unsigned int sysclk;
};
@@ -492,8 +491,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
@@ -573,8 +571,8 @@ static struct snd_soc_dai_ops wm8971_dai_ops = {
.set_sysclk = wm8971_set_dai_sysclk,
};
-struct snd_soc_dai wm8971_dai = {
- .name = "WM8971",
+static struct snd_soc_dai_driver wm8971_dai = {
+ .name = "wm8971-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -589,7 +587,6 @@ struct snd_soc_dai wm8971_dai = {
.formats = WM8971_FORMATS,},
.ops = &wm8971_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8971_dai);
static void wm8971_work(struct work_struct *work)
{
@@ -598,19 +595,14 @@ static void wm8971_work(struct work_struct *work)
wm8971_set_bias_level(codec, codec->bias_level);
}
-static int wm8971_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8971_resume(struct platform_device *pdev)
+static int wm8971_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -639,37 +631,24 @@ static int wm8971_resume(struct platform_device *pdev)
return 0;
}
-static int wm8971_init(struct snd_soc_device *socdev,
- enum snd_soc_control_type control)
+static int wm8971_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = socdev->card->codec;
- int reg, ret = 0;
-
- codec->name = "WM8971";
- codec->owner = THIS_MODULE;
- codec->set_bias_level = wm8971_set_bias_level;
- codec->dai = &wm8971_dai;
- codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
- codec->num_dai = 1;
- codec->reg_cache = kmemdup(wm8971_reg, sizeof(wm8971_reg), GFP_KERNEL);
-
- if (codec->reg_cache == NULL)
- return -ENOMEM;
+ struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0;
+ u16 reg;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);
if (ret < 0) {
printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
- wm8971_reset(codec);
+ INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work);
+ wm8971_workq = create_workqueue("wm8971");
+ if (wm8971_workq == NULL)
+ return -ENOMEM;
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "wm8971: failed to create pcms\n");
- goto err;
- }
+ wm8971_reset(codec);
/* charge output caps - set vmid to 5k for quick power up */
reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
@@ -704,40 +683,54 @@ static int wm8971_init(struct snd_soc_device *socdev,
wm8971_add_widgets(codec);
return ret;
-
-err:
- kfree(codec->reg_cache);
- return ret;
}
-/* If the i2c layer weren't so broken, we could pass this kind of data
- around */
-static struct snd_soc_device *wm8971_socdev;
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+/* power down chip */
+static int wm8971_remove(struct snd_soc_codec *codec)
+{
+ wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ if (wm8971_workq)
+ destroy_workqueue(wm8971_workq);
+ return 0;
+}
-static int wm8971_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
+ .probe = wm8971_probe,
+ .remove = wm8971_remove,
+ .suspend = wm8971_suspend,
+ .resume = wm8971_resume,
+ .set_bias_level = wm8971_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8971_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8971_reg,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_device *socdev = wm8971_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct wm8971_priv *wm8971;
int ret;
- i2c_set_clientdata(i2c, codec);
+ wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
+ if (wm8971 == NULL)
+ return -ENOMEM;
- codec->control_data = i2c;
+ i2c_set_clientdata(i2c, wm8971);
- ret = wm8971_init(socdev, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8971, &wm8971_dai, 1);
if (ret < 0)
- pr_err("failed to initialise WM8971\n");
-
+ kfree(wm8971);
return ret;
}
-static int wm8971_i2c_remove(struct i2c_client *client)
+static __devexit int wm8971_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -749,148 +742,34 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);
static struct i2c_driver wm8971_i2c_driver = {
.driver = {
- .name = "WM8971 I2C Codec",
+ .name = "wm8971-codec",
.owner = THIS_MODULE,
},
- .probe = wm8971_i2c_probe,
- .remove = wm8971_i2c_remove,
+ .probe = wm8971_i2c_probe,
+ .remove = __devexit_p(wm8971_i2c_remove),
.id_table = wm8971_i2c_id,
};
-
-static int wm8971_add_i2c_device(struct platform_device *pdev,
- const struct wm8971_setup_data *setup)
-{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- int ret;
-
- ret = i2c_add_driver(&wm8971_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = setup->i2c_address;
- strlcpy(info.type, "wm8971", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n",
- setup->i2c_bus);
- goto err_driver;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
-
- return 0;
-
-err_driver:
- i2c_del_driver(&wm8971_i2c_driver);
- return -ENODEV;
-}
-
#endif
-static int wm8971_probe(struct platform_device *pdev)
+static int __init wm8971_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8971_setup_data *setup;
- struct snd_soc_codec *codec;
- struct wm8971_priv *wm8971;
int ret = 0;
-
- pr_info("WM8971 Audio Codec %s", WM8971_VERSION);
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
- if (wm8971 == NULL) {
- kfree(codec);
- return -ENOMEM;
- }
-
- snd_soc_codec_set_drvdata(codec, wm8971);
- socdev->card->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
- wm8971_socdev = socdev;
-
- INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work);
- wm8971_workq = create_workqueue("wm8971");
- if (wm8971_workq == NULL) {
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec);
- return -ENOMEM;
- }
-
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- ret = wm8971_add_i2c_device(pdev, setup);
- }
-#endif
- /* Add other interfaces here */
-
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8971_i2c_driver);
if (ret != 0) {
- destroy_workqueue(wm8971_workq);
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec);
+ printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n",
+ ret);
}
-
- return ret;
-}
-
-/* power down chip */
-static int wm8971_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec->control_data)
- wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
- if (wm8971_workq)
- destroy_workqueue(wm8971_workq);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
- i2c_unregister_device(codec->control_data);
- i2c_del_driver(&wm8971_i2c_driver);
#endif
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8971 = {
- .probe = wm8971_probe,
- .remove = wm8971_remove,
- .suspend = wm8971_suspend,
- .resume = wm8971_resume,
-};
-
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
-
-static int __init wm8971_modinit(void)
-{
- return snd_soc_register_dai(&wm8971_dai);
+ return ret;
}
module_init(wm8971_modinit);
static void __exit wm8971_exit(void)
{
- snd_soc_unregister_dai(&wm8971_dai);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8971_i2c_driver);
+#endif
}
module_exit(wm8971_exit);
diff --git a/sound/soc/codecs/wm8971.h b/sound/soc/codecs/wm8971.h
index ef4f08f9f344..f31c38fddfc4 100644
--- a/sound/soc/codecs/wm8971.h
+++ b/sound/soc/codecs/wm8971.h
@@ -53,12 +53,4 @@
#define WM8971_SYSCLK 0
-struct wm8971_setup_data {
- int i2c_bus;
- unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai wm8971_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8971;
-
#endif
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 1468fe10cbbe..b4363f6d19b3 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -51,12 +51,10 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
#define WM8974_POWER1_BUFIOEN 0x04
struct wm8974_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
u16 reg_cache[WM8974_CACHEREGNUM];
};
-static struct snd_soc_codec *wm8974_codec;
-
#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0)
static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
@@ -566,8 +564,8 @@ static struct snd_soc_dai_ops wm8974_ops = {
.set_pll = wm8974_set_dai_pll,
};
-struct snd_soc_dai wm8974_dai = {
- .name = "WM8974 HiFi",
+static struct snd_soc_dai_driver wm8974_dai = {
+ .name = "wm8974-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -583,21 +581,15 @@ struct snd_soc_dai wm8974_dai = {
.ops = &wm8974_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8974_dai);
-static int wm8974_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8974_resume(struct platform_device *pdev)
+static int wm8974_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -613,156 +605,72 @@ static int wm8974_resume(struct platform_device *pdev)
return 0;
}
-static int wm8974_probe(struct platform_device *pdev)
+static int wm8974_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
int ret = 0;
- if (wm8974_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
- socdev->card->codec = wm8974_codec;
- codec = wm8974_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ ret = wm8974_reset(codec);
if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
+ dev_err(codec->dev, "Failed to issue reset\n");
+ return ret;
}
+ wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
snd_soc_add_controls(codec, wm8974_snd_controls,
ARRAY_SIZE(wm8974_snd_controls));
wm8974_add_widgets(codec);
return ret;
-
-pcm_err:
- return ret;
}
/* power down chip */
-static int wm8974_remove(struct platform_device *pdev)
+static int wm8974_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
+ wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_wm8974 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
.probe = wm8974_probe,
.remove = wm8974_remove,
.suspend = wm8974_suspend,
.resume = wm8974_resume,
+ .set_bias_level = wm8974_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8974_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8974_reg,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974);
-
-static __devinit int wm8974_register(struct wm8974_priv *wm8974)
-{
- int ret;
- struct snd_soc_codec *codec = &wm8974->codec;
-
- if (wm8974_codec) {
- dev_err(codec->dev, "Another WM8974 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8974);
- codec->name = "WM8974";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8974_set_bias_level;
- codec->dai = &wm8974_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8974_CACHEREGNUM;
- codec->reg_cache = &wm8974->reg_cache;
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
-
- memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg));
-
- ret = wm8974_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- goto err;
- }
-
- wm8974_dai.dev = codec->dev;
-
- wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- wm8974_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&wm8974_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
- return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8974);
- return ret;
-}
-
-static __devexit void wm8974_unregister(struct wm8974_priv *wm8974)
-{
- wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm8974_dai);
- snd_soc_unregister_codec(&wm8974->codec);
- kfree(wm8974);
- wm8974_codec = NULL;
-}
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8974_priv *wm8974;
- struct snd_soc_codec *codec;
+ int ret;
wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);
if (wm8974 == NULL)
return -ENOMEM;
- codec = &wm8974->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
i2c_set_clientdata(i2c, wm8974);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
- return wm8974_register(wm8974);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8974, &wm8974_dai, 1);
+ if (ret < 0)
+ kfree(wm8974);
+ return ret;
}
static __devexit int wm8974_i2c_remove(struct i2c_client *client)
{
- struct wm8974_priv *wm8974 = i2c_get_clientdata(client);
- wm8974_unregister(wm8974);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -774,23 +682,34 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
static struct i2c_driver wm8974_i2c_driver = {
.driver = {
- .name = "WM8974",
+ .name = "wm8974-codec",
.owner = THIS_MODULE,
},
.probe = wm8974_i2c_probe,
.remove = __devexit_p(wm8974_i2c_remove),
.id_table = wm8974_i2c_id,
};
+#endif
static int __init wm8974_modinit(void)
{
- return i2c_add_driver(&wm8974_i2c_driver);
+ int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8974_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n",
+ ret);
+ }
+#endif
+ return ret;
}
module_init(wm8974_modinit);
static void __exit wm8974_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8974_i2c_driver);
+#endif
}
module_exit(wm8974_exit);
diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h
index 896a7f0f3fc4..3c94e7bb55a6 100644
--- a/sound/soc/codecs/wm8974.h
+++ b/sound/soc/codecs/wm8974.h
@@ -83,7 +83,4 @@
#define WM8974_MCLKDIV_8 (6 << 5)
#define WM8974_MCLKDIV_12 (7 << 5)
-extern struct snd_soc_dai wm8974_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8974;
-
#endif
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 8a1ad778e7e3..13b979a71a7c 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -31,8 +31,6 @@
#include "wm8978.h"
-static struct snd_soc_codec *wm8978_codec;
-
/* wm8978 register cache. Note that register 0 is not included in the cache. */
static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */
@@ -54,7 +52,8 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
/* codec private data */
struct wm8978_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
unsigned int f_pllout;
unsigned int f_mclk;
unsigned int f_256fs;
@@ -374,8 +373,8 @@ struct wm8978_pll_div {
#define FIXED_PLL_SIZE (1 << 24)
-static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target,
- unsigned int source)
+static void pll_factors(struct snd_soc_codec *codec,
+ struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source)
{
u64 k_part;
unsigned int k, n_div, n_mod;
@@ -390,7 +389,7 @@ static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target,
}
if (n_div < 6 || n_div > 12)
- dev_warn(wm8978_codec->dev,
+ dev_warn(codec->dev,
"WM8978 N value exceeds recommended range! N = %u\n",
n_div);
@@ -505,7 +504,7 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__,
wm8978->f_mclk, wm8978->f_pllout);
- pll_factors(&pll_div, f2, wm8978->f_mclk);
+ pll_factors(codec, &pll_div, f2, wm8978->f_mclk);
dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n",
__func__, pll_div.n, pll_div.k, pll_div.div2);
@@ -690,8 +689,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
/* Word length mask = 0x60 */
u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60;
@@ -875,9 +873,8 @@ static struct snd_soc_dai_ops wm8978_dai_ops = {
};
/* Also supports 12kHz */
-struct snd_soc_dai wm8978_dai = {
- .name = "WM8978 HiFi",
- .id = 1,
+static struct snd_soc_dai_driver wm8978_dai = {
+ .name = "wm8978-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -894,13 +891,9 @@ struct snd_soc_dai wm8978_dai = {
},
.ops = &wm8978_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8978_dai);
-static int wm8978_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
/* Also switch PLL off */
snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0);
@@ -908,10 +901,8 @@ static int wm8978_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int wm8978_resume(struct platform_device *pdev)
+static int wm8978_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
int i;
u16 *cache = codec->reg_cache;
@@ -933,54 +924,6 @@ static int wm8978_resume(struct platform_device *pdev)
return 0;
}
-static int wm8978_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8978_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8978_codec;
- codec = wm8978_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8978_snd_controls,
- ARRAY_SIZE(wm8978_snd_controls));
- wm8978_add_widgets(codec);
-
-pcm_err:
- return ret;
-}
-
-/* power down chip */
-static int wm8978_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8978 = {
- .probe = wm8978_probe,
- .remove = wm8978_remove,
- .suspend = wm8978_suspend,
- .resume = wm8978_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8978);
-
/*
* These registers contain an "update" bit - bit 8. This means, for example,
* that one can write new DAC digital volume for both channels, but only when
@@ -1000,44 +943,23 @@ static const int update_reg[] = {
WM8978_ROUT2_SPK_CONTROL,
};
-static __devinit int wm8978_register(struct wm8978_priv *wm8978)
+static int wm8978_probe(struct snd_soc_codec *codec)
{
- int ret, i;
- struct snd_soc_codec *codec = &wm8978->codec;
-
- if (wm8978_codec) {
- dev_err(codec->dev, "Another WM8978 is registered\n");
- return -EINVAL;
- }
+ struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
+ int ret = 0, i;
/*
* Set default system clock to PLL, it is more precise, this is also the
* default hardware setting
*/
wm8978->sysclk = WM8978_PLL;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8978);
- codec->name = "WM8978";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8978_set_bias_level;
- codec->dai = &wm8978_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = WM8978_CACHEREGNUM;
- codec->reg_cache = &wm8978->reg_cache;
-
+ codec->control_data = wm8978->control_data;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
- memcpy(codec->reg_cache, wm8978_reg, sizeof(wm8978_reg));
-
/*
* Set the update bit in all registers, that have one. This way all
* writes to those registers will also cause the update bit to be
@@ -1050,74 +972,61 @@ static __devinit int wm8978_register(struct wm8978_priv *wm8978)
ret = snd_soc_write(codec, WM8978_RESET, 0);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
- goto err;
+ return ret;
}
- wm8978_dai.dev = codec->dev;
-
wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- wm8978_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&wm8978_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
+ snd_soc_add_controls(codec, wm8978_snd_controls,
+ ARRAY_SIZE(wm8978_snd_controls));
+ wm8978_add_widgets(codec);
return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- return ret;
}
-static __devexit void wm8978_unregister(struct wm8978_priv *wm8978)
+/* power down chip */
+static int wm8978_remove(struct snd_soc_codec *codec)
{
- wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm8978_dai);
- snd_soc_unregister_codec(&wm8978->codec);
- wm8978_codec = NULL;
+ wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
+ .probe = wm8978_probe,
+ .remove = wm8978_remove,
+ .suspend = wm8978_suspend,
+ .resume = wm8978_resume,
+ .set_bias_level = wm8978_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8978_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8978_reg,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
- int ret;
struct wm8978_priv *wm8978;
- struct snd_soc_codec *codec;
+ int ret;
wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL);
if (wm8978 == NULL)
return -ENOMEM;
- codec = &wm8978->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
i2c_set_clientdata(i2c, wm8978);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
+ wm8978->control_data = i2c;
- ret = wm8978_register(wm8978);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8978, &wm8978_dai, 1);
if (ret < 0)
kfree(wm8978);
-
return ret;
}
static __devexit int wm8978_i2c_remove(struct i2c_client *client)
{
- struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
- wm8978_unregister(wm8978);
- kfree(wm8978);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1129,23 +1038,34 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id);
static struct i2c_driver wm8978_i2c_driver = {
.driver = {
- .name = "WM8978",
+ .name = "wm8978",
.owner = THIS_MODULE,
},
.probe = wm8978_i2c_probe,
.remove = __devexit_p(wm8978_i2c_remove),
.id_table = wm8978_i2c_id,
};
+#endif
static int __init wm8978_modinit(void)
{
- return i2c_add_driver(&wm8978_i2c_driver);
+ int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8978_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n",
+ ret);
+ }
+#endif
+ return ret;
}
module_init(wm8978_modinit);
static void __exit wm8978_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8978_i2c_driver);
+#endif
}
module_exit(wm8978_exit);
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h
index 56ec83270917..c75525b7f154 100644
--- a/sound/soc/codecs/wm8978.h
+++ b/sound/soc/codecs/wm8978.h
@@ -80,7 +80,4 @@ enum wm8978_sysclk_src {
WM8978_MCLK
};
-extern struct snd_soc_dai wm8978_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8978;
-
#endif /* __WM8978_H__ */
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
new file mode 100644
index 000000000000..fd2e7cca1228
--- /dev/null
+++ b/sound/soc/codecs/wm8985.c
@@ -0,0 +1,1192 @@
+/*
+ * wm8985.c -- WM8985 ALSA SoC Audio driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * TODO:
+ * o Add OUT3/OUT4 mixer controls.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8985.h"
+
+#define WM8985_NUM_SUPPLIES 4
+static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = {
+ "DCVDD",
+ "DBVDD",
+ "AVDD1",
+ "AVDD2"
+};
+
+static const u16 wm8985_reg_defs[] = {
+ 0x0000, /* R0 - Software Reset */
+ 0x0000, /* R1 - Power management 1 */
+ 0x0000, /* R2 - Power management 2 */
+ 0x0000, /* R3 - Power management 3 */
+ 0x0050, /* R4 - Audio Interface */
+ 0x0000, /* R5 - Companding control */
+ 0x0140, /* R6 - Clock Gen control */
+ 0x0000, /* R7 - Additional control */
+ 0x0000, /* R8 - GPIO Control */
+ 0x0000, /* R9 - Jack Detect Control 1 */
+ 0x0000, /* R10 - DAC Control */
+ 0x00FF, /* R11 - Left DAC digital Vol */
+ 0x00FF, /* R12 - Right DAC digital vol */
+ 0x0000, /* R13 - Jack Detect Control 2 */
+ 0x0100, /* R14 - ADC Control */
+ 0x00FF, /* R15 - Left ADC Digital Vol */
+ 0x00FF, /* R16 - Right ADC Digital Vol */
+ 0x0000, /* R17 */
+ 0x012C, /* R18 - EQ1 - low shelf */
+ 0x002C, /* R19 - EQ2 - peak 1 */
+ 0x002C, /* R20 - EQ3 - peak 2 */
+ 0x002C, /* R21 - EQ4 - peak 3 */
+ 0x002C, /* R22 - EQ5 - high shelf */
+ 0x0000, /* R23 */
+ 0x0032, /* R24 - DAC Limiter 1 */
+ 0x0000, /* R25 - DAC Limiter 2 */
+ 0x0000, /* R26 */
+ 0x0000, /* R27 - Notch Filter 1 */
+ 0x0000, /* R28 - Notch Filter 2 */
+ 0x0000, /* R29 - Notch Filter 3 */
+ 0x0000, /* R30 - Notch Filter 4 */
+ 0x0000, /* R31 */
+ 0x0038, /* R32 - ALC control 1 */
+ 0x000B, /* R33 - ALC control 2 */
+ 0x0032, /* R34 - ALC control 3 */
+ 0x0000, /* R35 - Noise Gate */
+ 0x0008, /* R36 - PLL N */
+ 0x000C, /* R37 - PLL K 1 */
+ 0x0093, /* R38 - PLL K 2 */
+ 0x00E9, /* R39 - PLL K 3 */
+ 0x0000, /* R40 */
+ 0x0000, /* R41 - 3D control */
+ 0x0000, /* R42 - OUT4 to ADC */
+ 0x0000, /* R43 - Beep control */
+ 0x0033, /* R44 - Input ctrl */
+ 0x0010, /* R45 - Left INP PGA gain ctrl */
+ 0x0010, /* R46 - Right INP PGA gain ctrl */
+ 0x0100, /* R47 - Left ADC BOOST ctrl */
+ 0x0100, /* R48 - Right ADC BOOST ctrl */
+ 0x0002, /* R49 - Output ctrl */
+ 0x0001, /* R50 - Left mixer ctrl */
+ 0x0001, /* R51 - Right mixer ctrl */
+ 0x0039, /* R52 - LOUT1 (HP) volume ctrl */
+ 0x0039, /* R53 - ROUT1 (HP) volume ctrl */
+ 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */
+ 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */
+ 0x0001, /* R56 - OUT3 mixer ctrl */
+ 0x0001, /* R57 - OUT4 (MONO) mix ctrl */
+ 0x0001, /* R58 */
+ 0x0000, /* R59 */
+ 0x0004, /* R60 - OUTPUT ctrl */
+ 0x0000, /* R61 - BIAS CTRL */
+ 0x0180, /* R62 */
+ 0x0000 /* R63 */
+};
+
+/*
+ * latch bit 8 of these registers to ensure instant
+ * volume updates
+ */
+static const int volume_update_regs[] = {
+ WM8985_LEFT_DAC_DIGITAL_VOL,
+ WM8985_RIGHT_DAC_DIGITAL_VOL,
+ WM8985_LEFT_ADC_DIGITAL_VOL,
+ WM8985_RIGHT_ADC_DIGITAL_VOL,
+ WM8985_LOUT2_SPK_VOLUME_CTRL,
+ WM8985_ROUT2_SPK_VOLUME_CTRL,
+ WM8985_LOUT1_HP_VOLUME_CTRL,
+ WM8985_ROUT1_HP_VOLUME_CTRL,
+ WM8985_LEFT_INP_PGA_GAIN_CTRL,
+ WM8985_RIGHT_INP_PGA_GAIN_CTRL
+};
+
+struct wm8985_priv {
+ enum snd_soc_control_type control_type;
+ struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES];
+ unsigned int sysclk;
+ unsigned int bclk;
+};
+
+static const struct {
+ int div;
+ int ratio;
+} fs_ratios[] = {
+ { 10, 128 },
+ { 15, 192 },
+ { 20, 256 },
+ { 30, 384 },
+ { 40, 512 },
+ { 60, 768 },
+ { 80, 1024 },
+ { 120, 1536 }
+};
+
+static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 };
+
+static const int bclk_divs[] = {
+ 1, 2, 4, 8, 16, 32
+};
+
+static int eqmode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+static int eqmode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
+static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0);
+static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0);
+static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0);
+static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);
+static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0);
+
+static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" };
+static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7,
+ alc_sel_text);
+
+static const char *alc_mode_text[] = { "ALC", "Limiter" };
+static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8,
+ alc_mode_text);
+
+static const char *filter_mode_text[] = { "Audio", "Application" };
+static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7,
+ filter_mode_text);
+
+static const char *eq_bw_text[] = { "Narrow", "Wide" };
+static const char *eqmode_text[] = { "Capture", "Playback" };
+static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);
+
+static const char *eq1_cutoff_text[] = {
+ "80Hz", "105Hz", "135Hz", "175Hz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5,
+ eq1_cutoff_text);
+static const char *eq2_cutoff_text[] = {
+ "230Hz", "300Hz", "385Hz", "500Hz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5,
+ eq2_cutoff_text);
+static const char *eq3_cutoff_text[] = {
+ "650Hz", "850Hz", "1.1kHz", "1.4kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5,
+ eq3_cutoff_text);
+static const char *eq4_cutoff_text[] = {
+ "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5,
+ eq4_cutoff_text);
+static const char *eq5_cutoff_text[] = {
+ "5.3kHz", "6.9kHz", "9kHz", "11.7kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5,
+ eq5_cutoff_text);
+
+static const char *speaker_mode_text[] = { "Class A/B", "Class D" };
+static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
+
+static const char *depth_3d_text[] = {
+ "Off",
+ "6.67%",
+ "13.3%",
+ "20%",
+ "26.7%",
+ "33.3%",
+ "40%",
+ "46.6%",
+ "53.3%",
+ "60%",
+ "66.7%",
+ "73.3%",
+ "80%",
+ "86.7%",
+ "93.3%",
+ "100%"
+};
+static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0,
+ depth_3d_text);
+
+static const struct snd_kcontrol_new wm8985_snd_controls[] = {
+ SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL,
+ 0, 1, 0),
+
+ SOC_ENUM("ALC Capture Function", alc_sel),
+ SOC_SINGLE_TLV("ALC Capture Max Volume", WM8985_ALC_CONTROL_1,
+ 3, 7, 0, alc_max_tlv),
+ SOC_SINGLE_TLV("ALC Capture Min Volume", WM8985_ALC_CONTROL_1,
+ 0, 7, 0, alc_min_tlv),
+ SOC_SINGLE_TLV("ALC Capture Target Volume", WM8985_ALC_CONTROL_2,
+ 0, 15, 0, alc_tar_tlv),
+ SOC_SINGLE("ALC Capture Attack", WM8985_ALC_CONTROL_3, 0, 10, 0),
+ SOC_SINGLE("ALC Capture Hold", WM8985_ALC_CONTROL_2, 4, 10, 0),
+ SOC_SINGLE("ALC Capture Decay", WM8985_ALC_CONTROL_3, 4, 10, 0),
+ SOC_ENUM("ALC Mode", alc_mode),
+ SOC_SINGLE("ALC Capture NG Switch", WM8985_NOISE_GATE,
+ 3, 1, 0),
+ SOC_SINGLE("ALC Capture NG Threshold", WM8985_NOISE_GATE,
+ 0, 7, 1),
+
+ SOC_DOUBLE_R_TLV("Capture Volume", WM8985_LEFT_ADC_DIGITAL_VOL,
+ WM8985_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv),
+ SOC_DOUBLE_R("Capture PGA ZC Switch", WM8985_LEFT_INP_PGA_GAIN_CTRL,
+ WM8985_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0),
+ SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8985_LEFT_INP_PGA_GAIN_CTRL,
+ WM8985_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv),
+
+ SOC_DOUBLE_R_TLV("Capture PGA Boost Volume",
+ WM8985_LEFT_ADC_BOOST_CTRL, WM8985_RIGHT_ADC_BOOST_CTRL,
+ 8, 1, 0, pga_boost_tlv),
+
+ SOC_DOUBLE("ADC Inversion Switch", WM8985_ADC_CONTROL, 0, 1, 1, 0),
+ SOC_SINGLE("ADC 128x Oversampling Switch", WM8985_ADC_CONTROL, 8, 1, 0),
+
+ SOC_DOUBLE_R_TLV("Playback Volume", WM8985_LEFT_DAC_DIGITAL_VOL,
+ WM8985_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv),
+
+ SOC_SINGLE("DAC Playback Limiter Switch", WM8985_DAC_LIMITER_1, 8, 1, 0),
+ SOC_SINGLE("DAC Playback Limiter Decay", WM8985_DAC_LIMITER_1, 4, 10, 0),
+ SOC_SINGLE("DAC Playback Limiter Attack", WM8985_DAC_LIMITER_1, 0, 11, 0),
+ SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8985_DAC_LIMITER_2,
+ 4, 7, 1, lim_thresh_tlv),
+ SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8985_DAC_LIMITER_2,
+ 0, 12, 0, lim_boost_tlv),
+ SOC_DOUBLE("DAC Inversion Switch", WM8985_DAC_CONTROL, 0, 1, 1, 0),
+ SOC_SINGLE("DAC Auto Mute Switch", WM8985_DAC_CONTROL, 2, 1, 0),
+ SOC_SINGLE("DAC 128x Oversampling Switch", WM8985_DAC_CONTROL, 3, 1, 0),
+
+ SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8985_LOUT1_HP_VOLUME_CTRL,
+ WM8985_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv),
+ SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8985_LOUT1_HP_VOLUME_CTRL,
+ WM8985_ROUT1_HP_VOLUME_CTRL, 7, 1, 0),
+ SOC_DOUBLE_R("Headphone Switch", WM8985_LOUT1_HP_VOLUME_CTRL,
+ WM8985_ROUT1_HP_VOLUME_CTRL, 6, 1, 1),
+
+ SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8985_LOUT2_SPK_VOLUME_CTRL,
+ WM8985_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv),
+ SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8985_LOUT2_SPK_VOLUME_CTRL,
+ WM8985_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0),
+ SOC_DOUBLE_R("Speaker Switch", WM8985_LOUT2_SPK_VOLUME_CTRL,
+ WM8985_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1),
+
+ SOC_SINGLE("High Pass Filter Switch", WM8985_ADC_CONTROL, 8, 1, 0),
+ SOC_ENUM("High Pass Filter Mode", filter_mode),
+ SOC_SINGLE("High Pass Filter Cutoff", WM8985_ADC_CONTROL, 4, 7, 0),
+
+ SOC_DOUBLE_R_TLV("Aux Bypass Volume",
+ WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 6, 7, 0,
+ aux_tlv),
+
+ SOC_DOUBLE_R_TLV("Input PGA Bypass Volume",
+ WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 2, 7, 0,
+ bypass_tlv),
+
+ SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put),
+ SOC_ENUM("EQ1 Cutoff", eq1_cutoff),
+ SOC_SINGLE_TLV("EQ1 Volume", WM8985_EQ1_LOW_SHELF, 0, 24, 1, eq_tlv),
+ SOC_ENUM("EQ2 Bandwith", eq2_bw),
+ SOC_ENUM("EQ2 Cutoff", eq2_cutoff),
+ SOC_SINGLE_TLV("EQ2 Volume", WM8985_EQ2_PEAK_1, 0, 24, 1, eq_tlv),
+ SOC_ENUM("EQ3 Bandwith", eq3_bw),
+ SOC_ENUM("EQ3 Cutoff", eq3_cutoff),
+ SOC_SINGLE_TLV("EQ3 Volume", WM8985_EQ3_PEAK_2, 0, 24, 1, eq_tlv),
+ SOC_ENUM("EQ4 Bandwith", eq4_bw),
+ SOC_ENUM("EQ4 Cutoff", eq4_cutoff),
+ SOC_SINGLE_TLV("EQ4 Volume", WM8985_EQ4_PEAK_3, 0, 24, 1, eq_tlv),
+ SOC_ENUM("EQ5 Cutoff", eq5_cutoff),
+ SOC_SINGLE_TLV("EQ5 Volume", WM8985_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),
+
+ SOC_ENUM("3D Depth", depth_3d),
+
+ SOC_ENUM("Speaker Mode", speaker_mode)
+};
+
+static const struct snd_kcontrol_new left_out_mixer[] = {
+ SOC_DAPM_SINGLE("Line Switch", WM8985_LEFT_MIXER_CTRL, 1, 1, 0),
+ SOC_DAPM_SINGLE("Aux Switch", WM8985_LEFT_MIXER_CTRL, 5, 1, 0),
+ SOC_DAPM_SINGLE("PCM Switch", WM8985_LEFT_MIXER_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_out_mixer[] = {
+ SOC_DAPM_SINGLE("Line Switch", WM8985_RIGHT_MIXER_CTRL, 1, 1, 0),
+ SOC_DAPM_SINGLE("Aux Switch", WM8985_RIGHT_MIXER_CTRL, 5, 1, 0),
+ SOC_DAPM_SINGLE("PCM Switch", WM8985_RIGHT_MIXER_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_input_mixer[] = {
+ SOC_DAPM_SINGLE("L2 Switch", WM8985_INPUT_CTRL, 2, 1, 0),
+ SOC_DAPM_SINGLE("MicN Switch", WM8985_INPUT_CTRL, 1, 1, 0),
+ SOC_DAPM_SINGLE("MicP Switch", WM8985_INPUT_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_input_mixer[] = {
+ SOC_DAPM_SINGLE("R2 Switch", WM8985_INPUT_CTRL, 6, 1, 0),
+ SOC_DAPM_SINGLE("MicN Switch", WM8985_INPUT_CTRL, 5, 1, 0),
+ SOC_DAPM_SINGLE("MicP Switch", WM8985_INPUT_CTRL, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_boost_mixer[] = {
+ SOC_DAPM_SINGLE_TLV("L2 Volume", WM8985_LEFT_ADC_BOOST_CTRL,
+ 4, 7, 0, boost_tlv),
+ SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8985_LEFT_ADC_BOOST_CTRL,
+ 0, 7, 0, boost_tlv)
+};
+
+static const struct snd_kcontrol_new right_boost_mixer[] = {
+ SOC_DAPM_SINGLE_TLV("R2 Volume", WM8985_RIGHT_ADC_BOOST_CTRL,
+ 4, 7, 0, boost_tlv),
+ SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8985_RIGHT_ADC_BOOST_CTRL,
+ 0, 7, 0, boost_tlv)
+};
+
+static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8985_POWER_MANAGEMENT_3,
+ 0, 0),
+ SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8985_POWER_MANAGEMENT_3,
+ 1, 0),
+ SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8985_POWER_MANAGEMENT_2,
+ 0, 0),
+ SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8985_POWER_MANAGEMENT_2,
+ 1, 0),
+
+ SND_SOC_DAPM_MIXER("Left Output Mixer", WM8985_POWER_MANAGEMENT_3,
+ 2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)),
+ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8985_POWER_MANAGEMENT_3,
+ 3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)),
+
+ SND_SOC_DAPM_MIXER("Left Input Mixer", WM8985_POWER_MANAGEMENT_2,
+ 2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)),
+ SND_SOC_DAPM_MIXER("Right Input Mixer", WM8985_POWER_MANAGEMENT_2,
+ 3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)),
+
+ SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8985_POWER_MANAGEMENT_2,
+ 4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)),
+ SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8985_POWER_MANAGEMENT_2,
+ 5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)),
+
+ SND_SOC_DAPM_PGA("Left Capture PGA", WM8985_LEFT_INP_PGA_GAIN_CTRL,
+ 6, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Right Capture PGA", WM8985_RIGHT_INP_PGA_GAIN_CTRL,
+ 6, 1, NULL, 0),
+
+ SND_SOC_DAPM_PGA("Left Headphone Out", WM8985_POWER_MANAGEMENT_2,
+ 7, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Right Headphone Out", WM8985_POWER_MANAGEMENT_2,
+ 8, 0, NULL, 0),
+
+ SND_SOC_DAPM_PGA("Left Speaker Out", WM8985_POWER_MANAGEMENT_3,
+ 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Right Speaker Out", WM8985_POWER_MANAGEMENT_3,
+ 6, 0, NULL, 0),
+
+ SND_SOC_DAPM_MICBIAS("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0),
+
+ SND_SOC_DAPM_INPUT("LIN"),
+ SND_SOC_DAPM_INPUT("LIP"),
+ SND_SOC_DAPM_INPUT("RIN"),
+ SND_SOC_DAPM_INPUT("RIP"),
+ SND_SOC_DAPM_INPUT("AUXL"),
+ SND_SOC_DAPM_INPUT("AUXR"),
+ SND_SOC_DAPM_INPUT("L2"),
+ SND_SOC_DAPM_INPUT("R2"),
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+ SND_SOC_DAPM_OUTPUT("SPKL"),
+ SND_SOC_DAPM_OUTPUT("SPKR")
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ { "Right Output Mixer", "PCM Switch", "Right DAC" },
+ { "Right Output Mixer", "Aux Switch", "AUXR" },
+ { "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
+
+ { "Left Output Mixer", "PCM Switch", "Left DAC" },
+ { "Left Output Mixer", "Aux Switch", "AUXL" },
+ { "Left Output Mixer", "Line Switch", "Left Boost Mixer" },
+
+ { "Right Headphone Out", NULL, "Right Output Mixer" },
+ { "HPR", NULL, "Right Headphone Out" },
+
+ { "Left Headphone Out", NULL, "Left Output Mixer" },
+ { "HPL", NULL, "Left Headphone Out" },
+
+ { "Right Speaker Out", NULL, "Right Output Mixer" },
+ { "SPKR", NULL, "Right Speaker Out" },
+
+ { "Left Speaker Out", NULL, "Left Output Mixer" },
+ { "SPKL", NULL, "Left Speaker Out" },
+
+ { "Right ADC", NULL, "Right Boost Mixer" },
+
+ { "Right Boost Mixer", "AUXR Volume", "AUXR" },
+ { "Right Boost Mixer", NULL, "Right Capture PGA" },
+ { "Right Boost Mixer", "R2 Volume", "R2" },
+
+ { "Left ADC", NULL, "Left Boost Mixer" },
+
+ { "Left Boost Mixer", "AUXL Volume", "AUXL" },
+ { "Left Boost Mixer", NULL, "Left Capture PGA" },
+ { "Left Boost Mixer", "L2 Volume", "L2" },
+
+ { "Right Capture PGA", NULL, "Right Input Mixer" },
+ { "Left Capture PGA", NULL, "Left Input Mixer" },
+
+ { "Right Input Mixer", "R2 Switch", "R2" },
+ { "Right Input Mixer", "MicN Switch", "RIN" },
+ { "Right Input Mixer", "MicP Switch", "RIP" },
+
+ { "Left Input Mixer", "L2 Switch", "L2" },
+ { "Left Input Mixer", "MicN Switch", "LIN" },
+ { "Left Input Mixer", "MicP Switch", "LIP" },
+};
+
+static int eqmode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int reg;
+
+ reg = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
+ if (reg & WM8985_EQ3DMODE)
+ ucontrol->value.integer.value[0] = 1;
+ else
+ ucontrol->value.integer.value[0] = 0;
+
+ return 0;
+}
+
+static int eqmode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int regpwr2, regpwr3;
+ unsigned int reg_eq;
+
+ if (ucontrol->value.integer.value[0] != 0
+ && ucontrol->value.integer.value[0] != 1)
+ return -EINVAL;
+
+ reg_eq = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
+ switch ((reg_eq & WM8985_EQ3DMODE) >> WM8985_EQ3DMODE_SHIFT) {
+ case 0:
+ if (!ucontrol->value.integer.value[0])
+ return 0;
+ break;
+ case 1:
+ if (ucontrol->value.integer.value[0])
+ return 0;
+ break;
+ }
+
+ regpwr2 = snd_soc_read(codec, WM8985_POWER_MANAGEMENT_2);
+ regpwr3 = snd_soc_read(codec, WM8985_POWER_MANAGEMENT_3);
+ /* disable the DACs and ADCs */
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_2,
+ WM8985_ADCENR_MASK | WM8985_ADCENL_MASK, 0);
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_3,
+ WM8985_DACENR_MASK | WM8985_DACENL_MASK, 0);
+ snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL,
+ WM8985_M128ENB_MASK, WM8985_M128ENB);
+ /* set the desired eqmode */
+ snd_soc_update_bits(codec, WM8985_EQ1_LOW_SHELF,
+ WM8985_EQ3DMODE_MASK,
+ ucontrol->value.integer.value[0]
+ << WM8985_EQ3DMODE_SHIFT);
+ /* restore DAC/ADC configuration */
+ snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, regpwr2);
+ snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, regpwr3);
+ return 0;
+}
+
+static int wm8985_add_widgets(struct snd_soc_codec *codec)
+{
+ snd_soc_dapm_new_controls(codec, wm8985_dapm_widgets,
+ ARRAY_SIZE(wm8985_dapm_widgets));
+
+ snd_soc_dapm_add_routes(codec, audio_map,
+ ARRAY_SIZE(audio_map));
+ return 0;
+}
+
+static int wm8985_reset(struct snd_soc_codec *codec)
+{
+ return snd_soc_write(codec, WM8985_SOFTWARE_RESET, 0x0);
+}
+
+static int wm8985_dac_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ return snd_soc_update_bits(codec, WM8985_DAC_CONTROL,
+ WM8985_SOFTMUTE_MASK,
+ !!mute << WM8985_SOFTMUTE_SHIFT);
+}
+
+static int wm8985_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec;
+ u16 format, master, bcp, lrp;
+
+ codec = dai->codec;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ format = 0x2;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ format = 0x0;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ format = 0x1;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ format = 0x3;
+ break;
+ default:
+ dev_err(dai->dev, "Unknown dai format\n");
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
+ WM8985_FMT_MASK, format << WM8985_FMT_SHIFT);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ master = 0;
+ break;
+ default:
+ dev_err(dai->dev, "Unknown master/slave configuration\n");
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+ WM8985_MS_MASK, master << WM8985_MS_SHIFT);
+
+ /* frame inversion is not valid for dsp modes */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_IB_IF:
+ case SND_SOC_DAIFMT_NB_IF:
+ return -EINVAL;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ bcp = lrp = 0;
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ bcp = lrp = 1;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ bcp = 1;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ lrp = 1;
+ break;
+ default:
+ dev_err(dai->dev, "Unknown polarity configuration\n");
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
+ WM8985_LRP_MASK, lrp << WM8985_LRP_SHIFT);
+ snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
+ WM8985_BCP_MASK, bcp << WM8985_BCP_SHIFT);
+ return 0;
+}
+
+static int wm8985_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ int i;
+ struct snd_soc_codec *codec;
+ struct wm8985_priv *wm8985;
+ u16 blen, srate_idx;
+ unsigned int tmp;
+ int srate_best;
+
+ codec = dai->codec;
+ wm8985 = snd_soc_codec_get_drvdata(codec);
+
+ wm8985->bclk = snd_soc_params_to_bclk(params);
+ if ((int)wm8985->bclk < 0)
+ return wm8985->bclk;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ blen = 0x0;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ blen = 0x1;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ blen = 0x2;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ blen = 0x3;
+ break;
+ default:
+ dev_err(dai->dev, "Unsupported word length %u\n",
+ params_format(params));
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
+ WM8985_WL_MASK, blen << WM8985_WL_SHIFT);
+
+ /*
+ * match to the nearest possible sample rate and rely
+ * on the array index to configure the SR register
+ */
+ srate_idx = 0;
+ srate_best = abs(srates[0] - params_rate(params));
+ for (i = 1; i < ARRAY_SIZE(srates); ++i) {
+ if (abs(srates[i] - params_rate(params)) >= srate_best)
+ continue;
+ srate_idx = i;
+ srate_best = abs(srates[i] - params_rate(params));
+ }
+
+ dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]);
+ snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL,
+ WM8985_SR_MASK, srate_idx << WM8985_SR_SHIFT);
+
+ dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8985->bclk);
+ dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8985->sysclk);
+
+ for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) {
+ if (wm8985->sysclk / params_rate(params)
+ == fs_ratios[i].ratio)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(fs_ratios)) {
+ dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n",
+ wm8985->sysclk, params_rate(params));
+ return -EINVAL;
+ }
+
+ dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio);
+ snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+ WM8985_MCLKDIV_MASK, i << WM8985_MCLKDIV_SHIFT);
+
+ /* select the appropriate bclk divider */
+ tmp = (wm8985->sysclk / fs_ratios[i].div) * 10;
+ for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) {
+ if (wm8985->bclk == tmp / bclk_divs[i])
+ break;
+ }
+
+ if (i == ARRAY_SIZE(bclk_divs)) {
+ dev_err(dai->dev, "No matching BCLK divider found\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(dai->dev, "BCLK div = %d\n", i);
+ snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+ WM8985_BCLKDIV_MASK, i << WM8985_BCLKDIV_SHIFT);
+ return 0;
+}
+
+struct pll_div {
+ u32 div2:1;
+ u32 n:4;
+ u32 k:24;
+};
+
+#define FIXED_PLL_SIZE ((1ULL << 24) * 10)
+static int pll_factors(struct pll_div *pll_div, unsigned int target,
+ unsigned int source)
+{
+ u64 Kpart;
+ unsigned long int K, Ndiv, Nmod;
+
+ pll_div->div2 = 0;
+ Ndiv = target / source;
+ if (Ndiv < 6) {
+ source >>= 1;
+ pll_div->div2 = 1;
+ Ndiv = target / source;
+ }
+
+ if (Ndiv < 6 || Ndiv > 12) {
+ printk(KERN_ERR "%s: WM8985 N value is not within"
+ " the recommended range: %lu\n", __func__, Ndiv);
+ return -EINVAL;
+ }
+ pll_div->n = Ndiv;
+
+ Nmod = target % source;
+ Kpart = FIXED_PLL_SIZE * (u64)Nmod;
+
+ do_div(Kpart, source);
+
+ K = Kpart & 0xffffffff;
+ if ((K % 10) >= 5)
+ K += 5;
+ K /= 10;
+ pll_div->k = K;
+
+ return 0;
+}
+
+static int wm8985_set_pll(struct snd_soc_dai *dai, int pll_id,
+ int source, unsigned int freq_in,
+ unsigned int freq_out)
+{
+ int ret;
+ struct snd_soc_codec *codec;
+ struct pll_div pll_div;
+
+ codec = dai->codec;
+ if (freq_in && freq_out) {
+ ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in);
+ if (ret)
+ return ret;
+ }
+
+ /* disable the PLL before reprogramming it */
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+ WM8985_PLLEN_MASK, 0);
+
+ if (!freq_in || !freq_out)
+ return 0;
+
+ /* set PLLN and PRESCALE */
+ snd_soc_write(codec, WM8985_PLL_N,
+ (pll_div.div2 << WM8985_PLL_PRESCALE_SHIFT)
+ | pll_div.n);
+ /* set PLLK */
+ snd_soc_write(codec, WM8985_PLL_K_3, pll_div.k & 0x1ff);
+ snd_soc_write(codec, WM8985_PLL_K_2, (pll_div.k >> 9) & 0x1ff);
+ snd_soc_write(codec, WM8985_PLL_K_1, (pll_div.k >> 18));
+ /* set the source of the clock to be the PLL */
+ snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+ WM8985_CLKSEL_MASK, WM8985_CLKSEL);
+ /* enable the PLL */
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+ WM8985_PLLEN_MASK, WM8985_PLLEN);
+ return 0;
+}
+
+static int wm8985_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec;
+ struct wm8985_priv *wm8985;
+
+ codec = dai->codec;
+ wm8985 = snd_soc_codec_get_drvdata(codec);
+
+ switch (clk_id) {
+ case WM8985_CLKSRC_MCLK:
+ snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+ WM8985_CLKSEL_MASK, 0);
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+ WM8985_PLLEN_MASK, 0);
+ break;
+ case WM8985_CLKSRC_PLL:
+ snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+ WM8985_CLKSEL_MASK, WM8985_CLKSEL);
+ break;
+ default:
+ dev_err(dai->dev, "Unknown clock source %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ wm8985->sysclk = freq;
+ return 0;
+}
+
+static void wm8985_sync_cache(struct snd_soc_codec *codec)
+{
+ short i;
+ u16 *cache;
+
+ if (!codec->cache_sync)
+ return;
+ codec->cache_only = 0;
+ /* restore cache */
+ cache = codec->reg_cache;
+ for (i = 0; i < codec->driver->reg_cache_size; i++) {
+ if (i == WM8985_SOFTWARE_RESET
+ || cache[i] == wm8985_reg_defs[i])
+ continue;
+ snd_soc_write(codec, i, cache[i]);
+ }
+ codec->cache_sync = 0;
+}
+
+static int wm8985_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ int ret;
+ struct wm8985_priv *wm8985;
+
+ wm8985 = snd_soc_codec_get_drvdata(codec);
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ /* VMID at 75k */
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+ WM8985_VMIDSEL_MASK,
+ 1 << WM8985_VMIDSEL_SHIFT);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies),
+ wm8985->supplies);
+ if (ret) {
+ dev_err(codec->dev,
+ "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+
+ wm8985_sync_cache(codec);
+
+ /* enable anti-pop features */
+ snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
+ WM8985_POBCTRL_MASK,
+ WM8985_POBCTRL);
+ /* enable thermal shutdown */
+ snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
+ WM8985_TSDEN_MASK, WM8985_TSDEN);
+ snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
+ WM8985_TSOPCTRL_MASK,
+ WM8985_TSOPCTRL);
+ /* enable BIASEN */
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+ WM8985_BIASEN_MASK, WM8985_BIASEN);
+ /* VMID at 75k */
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+ WM8985_VMIDSEL_MASK,
+ 1 << WM8985_VMIDSEL_SHIFT);
+ msleep(500);
+ /* disable anti-pop features */
+ snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
+ WM8985_POBCTRL_MASK, 0);
+ }
+ /* VMID at 300k */
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+ WM8985_VMIDSEL_MASK,
+ 2 << WM8985_VMIDSEL_SHIFT);
+ break;
+ case SND_SOC_BIAS_OFF:
+ /* disable thermal shutdown */
+ snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
+ WM8985_TSOPCTRL_MASK, 0);
+ snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
+ WM8985_TSDEN_MASK, 0);
+ /* disable VMIDSEL and BIASEN */
+ snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+ WM8985_VMIDSEL_MASK | WM8985_BIASEN_MASK,
+ 0);
+ snd_soc_write(codec, WM8985_POWER_MANAGEMENT_1, 0);
+ snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, 0);
+ snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, 0);
+
+ codec->cache_sync = 1;
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies),
+ wm8985->supplies);
+ break;
+ }
+
+ codec->bias_level = level;
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8985_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+ wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int wm8985_resume(struct snd_soc_codec *codec)
+{
+ wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+#else
+#define wm8985_suspend NULL
+#define wm8985_resume NULL
+#endif
+
+static int wm8985_remove(struct snd_soc_codec *codec)
+{
+ struct wm8985_priv *wm8985;
+
+ wm8985 = snd_soc_codec_get_drvdata(codec);
+ wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
+ return 0;
+}
+
+static int wm8985_probe(struct snd_soc_codec *codec)
+{
+ size_t i;
+ struct wm8985_priv *wm8985;
+ int ret;
+ u16 *cache;
+
+ wm8985 = snd_soc_codec_get_drvdata(codec);
+
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8985->control_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++)
+ wm8985->supplies[i].supply = wm8985_supply_names[i];
+
+ ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8985->supplies),
+ wm8985->supplies);
+ if (ret) {
+ dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies),
+ wm8985->supplies);
+ if (ret) {
+ dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_reg_get;
+ }
+
+ ret = wm8985_reset(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+ goto err_reg_enable;
+ }
+
+ cache = codec->reg_cache;
+ /* latch volume update bits */
+ for (i = 0; i < ARRAY_SIZE(volume_update_regs); ++i)
+ cache[volume_update_regs[i]] |= 0x100;
+ /* enable BIASCUT */
+ cache[WM8985_BIAS_CTRL] |= WM8985_BIASCUT;
+ codec->cache_sync = 1;
+
+ snd_soc_add_controls(codec, wm8985_snd_controls,
+ ARRAY_SIZE(wm8985_snd_controls));
+ wm8985_add_widgets(codec);
+
+ wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+
+err_reg_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
+err_reg_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
+ return ret;
+}
+
+static struct snd_soc_dai_ops wm8985_dai_ops = {
+ .digital_mute = wm8985_dac_mute,
+ .hw_params = wm8985_hw_params,
+ .set_fmt = wm8985_set_fmt,
+ .set_sysclk = wm8985_set_sysclk,
+ .set_pll = wm8985_set_pll
+};
+
+#define WM8985_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm8985_dai = {
+ .name = "wm8985-hifi",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = WM8985_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = WM8985_FORMATS,
+ },
+ .ops = &wm8985_dai_ops,
+ .symmetric_rates = 1
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8985 = {
+ .probe = wm8985_probe,
+ .remove = wm8985_remove,
+ .suspend = wm8985_suspend,
+ .resume = wm8985_resume,
+ .set_bias_level = wm8985_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8985_reg_defs),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8985_reg_defs
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8985_spi_probe(struct spi_device *spi)
+{
+ struct wm8985_priv *wm8985;
+ int ret;
+
+ wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+ if (!wm8985)
+ return -ENOMEM;
+
+ wm8985->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8985);
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8985, &wm8985_dai, 1);
+ if (ret < 0)
+ kfree(wm8985);
+ return ret;
+}
+
+static int __devexit wm8985_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
+ return 0;
+}
+
+static struct spi_driver wm8985_spi_driver = {
+ .driver = {
+ .name = "wm8985",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8985_spi_probe,
+ .remove = __devexit_p(wm8985_spi_remove)
+};
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8985_priv *wm8985;
+ int ret;
+
+ wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+ if (!wm8985)
+ return -ENOMEM;
+
+ wm8985->control_type = SND_SOC_I2C;
+ i2c_set_clientdata(i2c, wm8985);
+
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8985, &wm8985_dai, 1);
+ if (ret < 0)
+ kfree(wm8985);
+ return ret;
+}
+
+static __devexit int wm8985_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+static const struct i2c_device_id wm8985_i2c_id[] = {
+ { "wm8985", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id);
+
+static struct i2c_driver wm8985_i2c_driver = {
+ .driver = {
+ .name = "wm8985",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8985_i2c_probe,
+ .remove = __devexit_p(wm8985_i2c_remove),
+ .id_table = wm8985_i2c_id
+};
+#endif
+
+static int __init wm8985_modinit(void)
+{
+ int ret = 0;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&wm8985_i2c_driver);
+ if (ret) {
+ printk(KERN_ERR "Failed to register wm8985 I2C driver: %d\n",
+ ret);
+ }
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ ret = spi_register_driver(&wm8985_spi_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8985 SPI driver: %d\n",
+ ret);
+ }
+#endif
+ return ret;
+}
+module_init(wm8985_modinit);
+
+static void __exit wm8985_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8985_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8985_spi_driver);
+#endif
+}
+module_exit(wm8985_exit);
+
+MODULE_DESCRIPTION("ASoC WM8985 driver");
+MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8985.h b/sound/soc/codecs/wm8985.h
new file mode 100644
index 000000000000..2e71ff507638
--- /dev/null
+++ b/sound/soc/codecs/wm8985.h
@@ -0,0 +1,1045 @@
+/*
+ * wm8985.h -- WM8985 ASoC driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8985_H
+#define _WM8985_H
+
+#define WM8985_SOFTWARE_RESET 0x00
+#define WM8985_POWER_MANAGEMENT_1 0x01
+#define WM8985_POWER_MANAGEMENT_2 0x02
+#define WM8985_POWER_MANAGEMENT_3 0x03
+#define WM8985_AUDIO_INTERFACE 0x04
+#define WM8985_COMPANDING_CONTROL 0x05
+#define WM8985_CLOCK_GEN_CONTROL 0x06
+#define WM8985_ADDITIONAL_CONTROL 0x07
+#define WM8985_GPIO_CONTROL 0x08
+#define WM8985_JACK_DETECT_CONTROL_1 0x09
+#define WM8985_DAC_CONTROL 0x0A
+#define WM8985_LEFT_DAC_DIGITAL_VOL 0x0B
+#define WM8985_RIGHT_DAC_DIGITAL_VOL 0x0C
+#define WM8985_JACK_DETECT_CONTROL_2 0x0D
+#define WM8985_ADC_CONTROL 0x0E
+#define WM8985_LEFT_ADC_DIGITAL_VOL 0x0F
+#define WM8985_RIGHT_ADC_DIGITAL_VOL 0x10
+#define WM8985_EQ1_LOW_SHELF 0x12
+#define WM8985_EQ2_PEAK_1 0x13
+#define WM8985_EQ3_PEAK_2 0x14
+#define WM8985_EQ4_PEAK_3 0x15
+#define WM8985_EQ5_HIGH_SHELF 0x16
+#define WM8985_DAC_LIMITER_1 0x18
+#define WM8985_DAC_LIMITER_2 0x19
+#define WM8985_NOTCH_FILTER_1 0x1B
+#define WM8985_NOTCH_FILTER_2 0x1C
+#define WM8985_NOTCH_FILTER_3 0x1D
+#define WM8985_NOTCH_FILTER_4 0x1E
+#define WM8985_ALC_CONTROL_1 0x20
+#define WM8985_ALC_CONTROL_2 0x21
+#define WM8985_ALC_CONTROL_3 0x22
+#define WM8985_NOISE_GATE 0x23
+#define WM8985_PLL_N 0x24
+#define WM8985_PLL_K_1 0x25
+#define WM8985_PLL_K_2 0x26
+#define WM8985_PLL_K_3 0x27
+#define WM8985_3D_CONTROL 0x29
+#define WM8985_OUT4_TO_ADC 0x2A
+#define WM8985_BEEP_CONTROL 0x2B
+#define WM8985_INPUT_CTRL 0x2C
+#define WM8985_LEFT_INP_PGA_GAIN_CTRL 0x2D
+#define WM8985_RIGHT_INP_PGA_GAIN_CTRL 0x2E
+#define WM8985_LEFT_ADC_BOOST_CTRL 0x2F
+#define WM8985_RIGHT_ADC_BOOST_CTRL 0x30
+#define WM8985_OUTPUT_CTRL0 0x31
+#define WM8985_LEFT_MIXER_CTRL 0x32
+#define WM8985_RIGHT_MIXER_CTRL 0x33
+#define WM8985_LOUT1_HP_VOLUME_CTRL 0x34
+#define WM8985_ROUT1_HP_VOLUME_CTRL 0x35
+#define WM8985_LOUT2_SPK_VOLUME_CTRL 0x36
+#define WM8985_ROUT2_SPK_VOLUME_CTRL 0x37
+#define WM8985_OUT3_MIXER_CTRL 0x38
+#define WM8985_OUT4_MONO_MIX_CTRL 0x39
+#define WM8985_OUTPUT_CTRL1 0x3C
+#define WM8985_BIAS_CTRL 0x3D
+
+#define WM8985_REGISTER_COUNT 59
+#define WM8985_MAX_REGISTER 0x3F
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+#define WM8985_SOFTWARE_RESET_MASK 0x01FF /* SOFTWARE_RESET - [8:0] */
+#define WM8985_SOFTWARE_RESET_SHIFT 0 /* SOFTWARE_RESET - [8:0] */
+#define WM8985_SOFTWARE_RESET_WIDTH 9 /* SOFTWARE_RESET - [8:0] */
+
+/*
+ * R1 (0x01) - Power management 1
+ */
+#define WM8985_OUT4MIXEN 0x0080 /* OUT4MIXEN */
+#define WM8985_OUT4MIXEN_MASK 0x0080 /* OUT4MIXEN */
+#define WM8985_OUT4MIXEN_SHIFT 7 /* OUT4MIXEN */
+#define WM8985_OUT4MIXEN_WIDTH 1 /* OUT4MIXEN */
+#define WM8985_OUT3MIXEN 0x0040 /* OUT3MIXEN */
+#define WM8985_OUT3MIXEN_MASK 0x0040 /* OUT3MIXEN */
+#define WM8985_OUT3MIXEN_SHIFT 6 /* OUT3MIXEN */
+#define WM8985_OUT3MIXEN_WIDTH 1 /* OUT3MIXEN */
+#define WM8985_PLLEN 0x0020 /* PLLEN */
+#define WM8985_PLLEN_MASK 0x0020 /* PLLEN */
+#define WM8985_PLLEN_SHIFT 5 /* PLLEN */
+#define WM8985_PLLEN_WIDTH 1 /* PLLEN */
+#define WM8985_MICBEN 0x0010 /* MICBEN */
+#define WM8985_MICBEN_MASK 0x0010 /* MICBEN */
+#define WM8985_MICBEN_SHIFT 4 /* MICBEN */
+#define WM8985_MICBEN_WIDTH 1 /* MICBEN */
+#define WM8985_BIASEN 0x0008 /* BIASEN */
+#define WM8985_BIASEN_MASK 0x0008 /* BIASEN */
+#define WM8985_BIASEN_SHIFT 3 /* BIASEN */
+#define WM8985_BIASEN_WIDTH 1 /* BIASEN */
+#define WM8985_BUFIOEN 0x0004 /* BUFIOEN */
+#define WM8985_BUFIOEN_MASK 0x0004 /* BUFIOEN */
+#define WM8985_BUFIOEN_SHIFT 2 /* BUFIOEN */
+#define WM8985_BUFIOEN_WIDTH 1 /* BUFIOEN */
+#define WM8985_VMIDSEL 0x0003 /* VMIDSEL */
+#define WM8985_VMIDSEL_MASK 0x0003 /* VMIDSEL - [1:0] */
+#define WM8985_VMIDSEL_SHIFT 0 /* VMIDSEL - [1:0] */
+#define WM8985_VMIDSEL_WIDTH 2 /* VMIDSEL - [1:0] */
+
+/*
+ * R2 (0x02) - Power management 2
+ */
+#define WM8985_ROUT1EN 0x0100 /* ROUT1EN */
+#define WM8985_ROUT1EN_MASK 0x0100 /* ROUT1EN */
+#define WM8985_ROUT1EN_SHIFT 8 /* ROUT1EN */
+#define WM8985_ROUT1EN_WIDTH 1 /* ROUT1EN */
+#define WM8985_LOUT1EN 0x0080 /* LOUT1EN */
+#define WM8985_LOUT1EN_MASK 0x0080 /* LOUT1EN */
+#define WM8985_LOUT1EN_SHIFT 7 /* LOUT1EN */
+#define WM8985_LOUT1EN_WIDTH 1 /* LOUT1EN */
+#define WM8985_SLEEP 0x0040 /* SLEEP */
+#define WM8985_SLEEP_MASK 0x0040 /* SLEEP */
+#define WM8985_SLEEP_SHIFT 6 /* SLEEP */
+#define WM8985_SLEEP_WIDTH 1 /* SLEEP */
+#define WM8985_BOOSTENR 0x0020 /* BOOSTENR */
+#define WM8985_BOOSTENR_MASK 0x0020 /* BOOSTENR */
+#define WM8985_BOOSTENR_SHIFT 5 /* BOOSTENR */
+#define WM8985_BOOSTENR_WIDTH 1 /* BOOSTENR */
+#define WM8985_BOOSTENL 0x0010 /* BOOSTENL */
+#define WM8985_BOOSTENL_MASK 0x0010 /* BOOSTENL */
+#define WM8985_BOOSTENL_SHIFT 4 /* BOOSTENL */
+#define WM8985_BOOSTENL_WIDTH 1 /* BOOSTENL */
+#define WM8985_INPGAENR 0x0008 /* INPGAENR */
+#define WM8985_INPGAENR_MASK 0x0008 /* INPGAENR */
+#define WM8985_INPGAENR_SHIFT 3 /* INPGAENR */
+#define WM8985_INPGAENR_WIDTH 1 /* INPGAENR */
+#define WM8985_INPPGAENL 0x0004 /* INPPGAENL */
+#define WM8985_INPPGAENL_MASK 0x0004 /* INPPGAENL */
+#define WM8985_INPPGAENL_SHIFT 2 /* INPPGAENL */
+#define WM8985_INPPGAENL_WIDTH 1 /* INPPGAENL */
+#define WM8985_ADCENR 0x0002 /* ADCENR */
+#define WM8985_ADCENR_MASK 0x0002 /* ADCENR */
+#define WM8985_ADCENR_SHIFT 1 /* ADCENR */
+#define WM8985_ADCENR_WIDTH 1 /* ADCENR */
+#define WM8985_ADCENL 0x0001 /* ADCENL */
+#define WM8985_ADCENL_MASK 0x0001 /* ADCENL */
+#define WM8985_ADCENL_SHIFT 0 /* ADCENL */
+#define WM8985_ADCENL_WIDTH 1 /* ADCENL */
+
+/*
+ * R3 (0x03) - Power management 3
+ */
+#define WM8985_OUT4EN 0x0100 /* OUT4EN */
+#define WM8985_OUT4EN_MASK 0x0100 /* OUT4EN */
+#define WM8985_OUT4EN_SHIFT 8 /* OUT4EN */
+#define WM8985_OUT4EN_WIDTH 1 /* OUT4EN */
+#define WM8985_OUT3EN 0x0080 /* OUT3EN */
+#define WM8985_OUT3EN_MASK 0x0080 /* OUT3EN */
+#define WM8985_OUT3EN_SHIFT 7 /* OUT3EN */
+#define WM8985_OUT3EN_WIDTH 1 /* OUT3EN */
+#define WM8985_ROUT2EN 0x0040 /* ROUT2EN */
+#define WM8985_ROUT2EN_MASK 0x0040 /* ROUT2EN */
+#define WM8985_ROUT2EN_SHIFT 6 /* ROUT2EN */
+#define WM8985_ROUT2EN_WIDTH 1 /* ROUT2EN */
+#define WM8985_LOUT2EN 0x0020 /* LOUT2EN */
+#define WM8985_LOUT2EN_MASK 0x0020 /* LOUT2EN */
+#define WM8985_LOUT2EN_SHIFT 5 /* LOUT2EN */
+#define WM8985_LOUT2EN_WIDTH 1 /* LOUT2EN */
+#define WM8985_RMIXEN 0x0008 /* RMIXEN */
+#define WM8985_RMIXEN_MASK 0x0008 /* RMIXEN */
+#define WM8985_RMIXEN_SHIFT 3 /* RMIXEN */
+#define WM8985_RMIXEN_WIDTH 1 /* RMIXEN */
+#define WM8985_LMIXEN 0x0004 /* LMIXEN */
+#define WM8985_LMIXEN_MASK 0x0004 /* LMIXEN */
+#define WM8985_LMIXEN_SHIFT 2 /* LMIXEN */
+#define WM8985_LMIXEN_WIDTH 1 /* LMIXEN */
+#define WM8985_DACENR 0x0002 /* DACENR */
+#define WM8985_DACENR_MASK 0x0002 /* DACENR */
+#define WM8985_DACENR_SHIFT 1 /* DACENR */
+#define WM8985_DACENR_WIDTH 1 /* DACENR */
+#define WM8985_DACENL 0x0001 /* DACENL */
+#define WM8985_DACENL_MASK 0x0001 /* DACENL */
+#define WM8985_DACENL_SHIFT 0 /* DACENL */
+#define WM8985_DACENL_WIDTH 1 /* DACENL */
+
+/*
+ * R4 (0x04) - Audio Interface
+ */
+#define WM8985_BCP 0x0100 /* BCP */
+#define WM8985_BCP_MASK 0x0100 /* BCP */
+#define WM8985_BCP_SHIFT 8 /* BCP */
+#define WM8985_BCP_WIDTH 1 /* BCP */
+#define WM8985_LRP 0x0080 /* LRP */
+#define WM8985_LRP_MASK 0x0080 /* LRP */
+#define WM8985_LRP_SHIFT 7 /* LRP */
+#define WM8985_LRP_WIDTH 1 /* LRP */
+#define WM8985_WL_MASK 0x0060 /* WL - [6:5] */
+#define WM8985_WL_SHIFT 5 /* WL - [6:5] */
+#define WM8985_WL_WIDTH 2 /* WL - [6:5] */
+#define WM8985_FMT_MASK 0x0018 /* FMT - [4:3] */
+#define WM8985_FMT_SHIFT 3 /* FMT - [4:3] */
+#define WM8985_FMT_WIDTH 2 /* FMT - [4:3] */
+#define WM8985_DLRSWAP 0x0004 /* DLRSWAP */
+#define WM8985_DLRSWAP_MASK 0x0004 /* DLRSWAP */
+#define WM8985_DLRSWAP_SHIFT 2 /* DLRSWAP */
+#define WM8985_DLRSWAP_WIDTH 1 /* DLRSWAP */
+#define WM8985_ALRSWAP 0x0002 /* ALRSWAP */
+#define WM8985_ALRSWAP_MASK 0x0002 /* ALRSWAP */
+#define WM8985_ALRSWAP_SHIFT 1 /* ALRSWAP */
+#define WM8985_ALRSWAP_WIDTH 1 /* ALRSWAP */
+#define WM8985_MONO 0x0001 /* MONO */
+#define WM8985_MONO_MASK 0x0001 /* MONO */
+#define WM8985_MONO_SHIFT 0 /* MONO */
+#define WM8985_MONO_WIDTH 1 /* MONO */
+
+/*
+ * R5 (0x05) - Companding control
+ */
+#define WM8985_WL8 0x0020 /* WL8 */
+#define WM8985_WL8_MASK 0x0020 /* WL8 */
+#define WM8985_WL8_SHIFT 5 /* WL8 */
+#define WM8985_WL8_WIDTH 1 /* WL8 */
+#define WM8985_DAC_COMP_MASK 0x0018 /* DAC_COMP - [4:3] */
+#define WM8985_DAC_COMP_SHIFT 3 /* DAC_COMP - [4:3] */
+#define WM8985_DAC_COMP_WIDTH 2 /* DAC_COMP - [4:3] */
+#define WM8985_ADC_COMP_MASK 0x0006 /* ADC_COMP - [2:1] */
+#define WM8985_ADC_COMP_SHIFT 1 /* ADC_COMP - [2:1] */
+#define WM8985_ADC_COMP_WIDTH 2 /* ADC_COMP - [2:1] */
+#define WM8985_LOOPBACK 0x0001 /* LOOPBACK */
+#define WM8985_LOOPBACK_MASK 0x0001 /* LOOPBACK */
+#define WM8985_LOOPBACK_SHIFT 0 /* LOOPBACK */
+#define WM8985_LOOPBACK_WIDTH 1 /* LOOPBACK */
+
+/*
+ * R6 (0x06) - Clock Gen control
+ */
+#define WM8985_CLKSEL 0x0100 /* CLKSEL */
+#define WM8985_CLKSEL_MASK 0x0100 /* CLKSEL */
+#define WM8985_CLKSEL_SHIFT 8 /* CLKSEL */
+#define WM8985_CLKSEL_WIDTH 1 /* CLKSEL */
+#define WM8985_MCLKDIV_MASK 0x00E0 /* MCLKDIV - [7:5] */
+#define WM8985_MCLKDIV_SHIFT 5 /* MCLKDIV - [7:5] */
+#define WM8985_MCLKDIV_WIDTH 3 /* MCLKDIV - [7:5] */
+#define WM8985_BCLKDIV_MASK 0x001C /* BCLKDIV - [4:2] */
+#define WM8985_BCLKDIV_SHIFT 2 /* BCLKDIV - [4:2] */
+#define WM8985_BCLKDIV_WIDTH 3 /* BCLKDIV - [4:2] */
+#define WM8985_MS 0x0001 /* MS */
+#define WM8985_MS_MASK 0x0001 /* MS */
+#define WM8985_MS_SHIFT 0 /* MS */
+#define WM8985_MS_WIDTH 1 /* MS */
+
+/*
+ * R7 (0x07) - Additional control
+ */
+#define WM8985_M128ENB 0x0100 /* M128ENB */
+#define WM8985_M128ENB_MASK 0x0100 /* M128ENB */
+#define WM8985_M128ENB_SHIFT 8 /* M128ENB */
+#define WM8985_M128ENB_WIDTH 1 /* M128ENB */
+#define WM8985_DCLKDIV_MASK 0x00F0 /* DCLKDIV - [7:4] */
+#define WM8985_DCLKDIV_SHIFT 4 /* DCLKDIV - [7:4] */
+#define WM8985_DCLKDIV_WIDTH 4 /* DCLKDIV - [7:4] */
+#define WM8985_SR_MASK 0x000E /* SR - [3:1] */
+#define WM8985_SR_SHIFT 1 /* SR - [3:1] */
+#define WM8985_SR_WIDTH 3 /* SR - [3:1] */
+#define WM8985_SLOWCLKEN 0x0001 /* SLOWCLKEN */
+#define WM8985_SLOWCLKEN_MASK 0x0001 /* SLOWCLKEN */
+#define WM8985_SLOWCLKEN_SHIFT 0 /* SLOWCLKEN */
+#define WM8985_SLOWCLKEN_WIDTH 1 /* SLOWCLKEN */
+
+/*
+ * R8 (0x08) - GPIO Control
+ */
+#define WM8985_GPIO1GP 0x0100 /* GPIO1GP */
+#define WM8985_GPIO1GP_MASK 0x0100 /* GPIO1GP */
+#define WM8985_GPIO1GP_SHIFT 8 /* GPIO1GP */
+#define WM8985_GPIO1GP_WIDTH 1 /* GPIO1GP */
+#define WM8985_GPIO1GPU 0x0080 /* GPIO1GPU */
+#define WM8985_GPIO1GPU_MASK 0x0080 /* GPIO1GPU */
+#define WM8985_GPIO1GPU_SHIFT 7 /* GPIO1GPU */
+#define WM8985_GPIO1GPU_WIDTH 1 /* GPIO1GPU */
+#define WM8985_GPIO1GPD 0x0040 /* GPIO1GPD */
+#define WM8985_GPIO1GPD_MASK 0x0040 /* GPIO1GPD */
+#define WM8985_GPIO1GPD_SHIFT 6 /* GPIO1GPD */
+#define WM8985_GPIO1GPD_WIDTH 1 /* GPIO1GPD */
+#define WM8985_GPIO1POL 0x0008 /* GPIO1POL */
+#define WM8985_GPIO1POL_MASK 0x0008 /* GPIO1POL */
+#define WM8985_GPIO1POL_SHIFT 3 /* GPIO1POL */
+#define WM8985_GPIO1POL_WIDTH 1 /* GPIO1POL */
+#define WM8985_GPIO1SEL_MASK 0x0007 /* GPIO1SEL - [2:0] */
+#define WM8985_GPIO1SEL_SHIFT 0 /* GPIO1SEL - [2:0] */
+#define WM8985_GPIO1SEL_WIDTH 3 /* GPIO1SEL - [2:0] */
+
+/*
+ * R9 (0x09) - Jack Detect Control 1
+ */
+#define WM8985_JD_EN 0x0040 /* JD_EN */
+#define WM8985_JD_EN_MASK 0x0040 /* JD_EN */
+#define WM8985_JD_EN_SHIFT 6 /* JD_EN */
+#define WM8985_JD_EN_WIDTH 1 /* JD_EN */
+#define WM8985_JD_SEL_MASK 0x0030 /* JD_SEL - [5:4] */
+#define WM8985_JD_SEL_SHIFT 4 /* JD_SEL - [5:4] */
+#define WM8985_JD_SEL_WIDTH 2 /* JD_SEL - [5:4] */
+
+/*
+ * R10 (0x0A) - DAC Control
+ */
+#define WM8985_SOFTMUTE 0x0040 /* SOFTMUTE */
+#define WM8985_SOFTMUTE_MASK 0x0040 /* SOFTMUTE */
+#define WM8985_SOFTMUTE_SHIFT 6 /* SOFTMUTE */
+#define WM8985_SOFTMUTE_WIDTH 1 /* SOFTMUTE */
+#define WM8985_DACOSR128 0x0008 /* DACOSR128 */
+#define WM8985_DACOSR128_MASK 0x0008 /* DACOSR128 */
+#define WM8985_DACOSR128_SHIFT 3 /* DACOSR128 */
+#define WM8985_DACOSR128_WIDTH 1 /* DACOSR128 */
+#define WM8985_AMUTE 0x0004 /* AMUTE */
+#define WM8985_AMUTE_MASK 0x0004 /* AMUTE */
+#define WM8985_AMUTE_SHIFT 2 /* AMUTE */
+#define WM8985_AMUTE_WIDTH 1 /* AMUTE */
+#define WM8985_DACPOLR 0x0002 /* DACPOLR */
+#define WM8985_DACPOLR_MASK 0x0002 /* DACPOLR */
+#define WM8985_DACPOLR_SHIFT 1 /* DACPOLR */
+#define WM8985_DACPOLR_WIDTH 1 /* DACPOLR */
+#define WM8985_DACPOLL 0x0001 /* DACPOLL */
+#define WM8985_DACPOLL_MASK 0x0001 /* DACPOLL */
+#define WM8985_DACPOLL_SHIFT 0 /* DACPOLL */
+#define WM8985_DACPOLL_WIDTH 1 /* DACPOLL */
+
+/*
+ * R11 (0x0B) - Left DAC digital Vol
+ */
+#define WM8985_DACVU 0x0100 /* DACVU */
+#define WM8985_DACVU_MASK 0x0100 /* DACVU */
+#define WM8985_DACVU_SHIFT 8 /* DACVU */
+#define WM8985_DACVU_WIDTH 1 /* DACVU */
+#define WM8985_DACVOLL_MASK 0x00FF /* DACVOLL - [7:0] */
+#define WM8985_DACVOLL_SHIFT 0 /* DACVOLL - [7:0] */
+#define WM8985_DACVOLL_WIDTH 8 /* DACVOLL - [7:0] */
+
+/*
+ * R12 (0x0C) - Right DAC digital vol
+ */
+#define WM8985_DACVU 0x0100 /* DACVU */
+#define WM8985_DACVU_MASK 0x0100 /* DACVU */
+#define WM8985_DACVU_SHIFT 8 /* DACVU */
+#define WM8985_DACVU_WIDTH 1 /* DACVU */
+#define WM8985_DACVOLR_MASK 0x00FF /* DACVOLR - [7:0] */
+#define WM8985_DACVOLR_SHIFT 0 /* DACVOLR - [7:0] */
+#define WM8985_DACVOLR_WIDTH 8 /* DACVOLR - [7:0] */
+
+/*
+ * R13 (0x0D) - Jack Detect Control 2
+ */
+#define WM8985_JD_EN1_MASK 0x00F0 /* JD_EN1 - [7:4] */
+#define WM8985_JD_EN1_SHIFT 4 /* JD_EN1 - [7:4] */
+#define WM8985_JD_EN1_WIDTH 4 /* JD_EN1 - [7:4] */
+#define WM8985_JD_EN0_MASK 0x000F /* JD_EN0 - [3:0] */
+#define WM8985_JD_EN0_SHIFT 0 /* JD_EN0 - [3:0] */
+#define WM8985_JD_EN0_WIDTH 4 /* JD_EN0 - [3:0] */
+
+/*
+ * R14 (0x0E) - ADC Control
+ */
+#define WM8985_HPFEN 0x0100 /* HPFEN */
+#define WM8985_HPFEN_MASK 0x0100 /* HPFEN */
+#define WM8985_HPFEN_SHIFT 8 /* HPFEN */
+#define WM8985_HPFEN_WIDTH 1 /* HPFEN */
+#define WM8985_HPFAPP 0x0080 /* HPFAPP */
+#define WM8985_HPFAPP_MASK 0x0080 /* HPFAPP */
+#define WM8985_HPFAPP_SHIFT 7 /* HPFAPP */
+#define WM8985_HPFAPP_WIDTH 1 /* HPFAPP */
+#define WM8985_HPFCUT_MASK 0x0070 /* HPFCUT - [6:4] */
+#define WM8985_HPFCUT_SHIFT 4 /* HPFCUT - [6:4] */
+#define WM8985_HPFCUT_WIDTH 3 /* HPFCUT - [6:4] */
+#define WM8985_ADCOSR128 0x0008 /* ADCOSR128 */
+#define WM8985_ADCOSR128_MASK 0x0008 /* ADCOSR128 */
+#define WM8985_ADCOSR128_SHIFT 3 /* ADCOSR128 */
+#define WM8985_ADCOSR128_WIDTH 1 /* ADCOSR128 */
+#define WM8985_ADCRPOL 0x0002 /* ADCRPOL */
+#define WM8985_ADCRPOL_MASK 0x0002 /* ADCRPOL */
+#define WM8985_ADCRPOL_SHIFT 1 /* ADCRPOL */
+#define WM8985_ADCRPOL_WIDTH 1 /* ADCRPOL */
+#define WM8985_ADCLPOL 0x0001 /* ADCLPOL */
+#define WM8985_ADCLPOL_MASK 0x0001 /* ADCLPOL */
+#define WM8985_ADCLPOL_SHIFT 0 /* ADCLPOL */
+#define WM8985_ADCLPOL_WIDTH 1 /* ADCLPOL */
+
+/*
+ * R15 (0x0F) - Left ADC Digital Vol
+ */
+#define WM8985_ADCVU 0x0100 /* ADCVU */
+#define WM8985_ADCVU_MASK 0x0100 /* ADCVU */
+#define WM8985_ADCVU_SHIFT 8 /* ADCVU */
+#define WM8985_ADCVU_WIDTH 1 /* ADCVU */
+#define WM8985_ADCVOLL_MASK 0x00FF /* ADCVOLL - [7:0] */
+#define WM8985_ADCVOLL_SHIFT 0 /* ADCVOLL - [7:0] */
+#define WM8985_ADCVOLL_WIDTH 8 /* ADCVOLL - [7:0] */
+
+/*
+ * R16 (0x10) - Right ADC Digital Vol
+ */
+#define WM8985_ADCVU 0x0100 /* ADCVU */
+#define WM8985_ADCVU_MASK 0x0100 /* ADCVU */
+#define WM8985_ADCVU_SHIFT 8 /* ADCVU */
+#define WM8985_ADCVU_WIDTH 1 /* ADCVU */
+#define WM8985_ADCVOLR_MASK 0x00FF /* ADCVOLR - [7:0] */
+#define WM8985_ADCVOLR_SHIFT 0 /* ADCVOLR - [7:0] */
+#define WM8985_ADCVOLR_WIDTH 8 /* ADCVOLR - [7:0] */
+
+/*
+ * R18 (0x12) - EQ1 - low shelf
+ */
+#define WM8985_EQ3DMODE 0x0100 /* EQ3DMODE */
+#define WM8985_EQ3DMODE_MASK 0x0100 /* EQ3DMODE */
+#define WM8985_EQ3DMODE_SHIFT 8 /* EQ3DMODE */
+#define WM8985_EQ3DMODE_WIDTH 1 /* EQ3DMODE */
+#define WM8985_EQ1C_MASK 0x0060 /* EQ1C - [6:5] */
+#define WM8985_EQ1C_SHIFT 5 /* EQ1C - [6:5] */
+#define WM8985_EQ1C_WIDTH 2 /* EQ1C - [6:5] */
+#define WM8985_EQ1G_MASK 0x001F /* EQ1G - [4:0] */
+#define WM8985_EQ1G_SHIFT 0 /* EQ1G - [4:0] */
+#define WM8985_EQ1G_WIDTH 5 /* EQ1G - [4:0] */
+
+/*
+ * R19 (0x13) - EQ2 - peak 1
+ */
+#define WM8985_EQ2BW 0x0100 /* EQ2BW */
+#define WM8985_EQ2BW_MASK 0x0100 /* EQ2BW */
+#define WM8985_EQ2BW_SHIFT 8 /* EQ2BW */
+#define WM8985_EQ2BW_WIDTH 1 /* EQ2BW */
+#define WM8985_EQ2C_MASK 0x0060 /* EQ2C - [6:5] */
+#define WM8985_EQ2C_SHIFT 5 /* EQ2C - [6:5] */
+#define WM8985_EQ2C_WIDTH 2 /* EQ2C - [6:5] */
+#define WM8985_EQ2G_MASK 0x001F /* EQ2G - [4:0] */
+#define WM8985_EQ2G_SHIFT 0 /* EQ2G - [4:0] */
+#define WM8985_EQ2G_WIDTH 5 /* EQ2G - [4:0] */
+
+/*
+ * R20 (0x14) - EQ3 - peak 2
+ */
+#define WM8985_EQ3BW 0x0100 /* EQ3BW */
+#define WM8985_EQ3BW_MASK 0x0100 /* EQ3BW */
+#define WM8985_EQ3BW_SHIFT 8 /* EQ3BW */
+#define WM8985_EQ3BW_WIDTH 1 /* EQ3BW */
+#define WM8985_EQ3C_MASK 0x0060 /* EQ3C - [6:5] */
+#define WM8985_EQ3C_SHIFT 5 /* EQ3C - [6:5] */
+#define WM8985_EQ3C_WIDTH 2 /* EQ3C - [6:5] */
+#define WM8985_EQ3G_MASK 0x001F /* EQ3G - [4:0] */
+#define WM8985_EQ3G_SHIFT 0 /* EQ3G - [4:0] */
+#define WM8985_EQ3G_WIDTH 5 /* EQ3G - [4:0] */
+
+/*
+ * R21 (0x15) - EQ4 - peak 3
+ */
+#define WM8985_EQ4BW 0x0100 /* EQ4BW */
+#define WM8985_EQ4BW_MASK 0x0100 /* EQ4BW */
+#define WM8985_EQ4BW_SHIFT 8 /* EQ4BW */
+#define WM8985_EQ4BW_WIDTH 1 /* EQ4BW */
+#define WM8985_EQ4C_MASK 0x0060 /* EQ4C - [6:5] */
+#define WM8985_EQ4C_SHIFT 5 /* EQ4C - [6:5] */
+#define WM8985_EQ4C_WIDTH 2 /* EQ4C - [6:5] */
+#define WM8985_EQ4G_MASK 0x001F /* EQ4G - [4:0] */
+#define WM8985_EQ4G_SHIFT 0 /* EQ4G - [4:0] */
+#define WM8985_EQ4G_WIDTH 5 /* EQ4G - [4:0] */
+
+/*
+ * R22 (0x16) - EQ5 - high shelf
+ */
+#define WM8985_EQ5C_MASK 0x0060 /* EQ5C - [6:5] */
+#define WM8985_EQ5C_SHIFT 5 /* EQ5C - [6:5] */
+#define WM8985_EQ5C_WIDTH 2 /* EQ5C - [6:5] */
+#define WM8985_EQ5G_MASK 0x001F /* EQ5G - [4:0] */
+#define WM8985_EQ5G_SHIFT 0 /* EQ5G - [4:0] */
+#define WM8985_EQ5G_WIDTH 5 /* EQ5G - [4:0] */
+
+/*
+ * R24 (0x18) - DAC Limiter 1
+ */
+#define WM8985_LIMEN 0x0100 /* LIMEN */
+#define WM8985_LIMEN_MASK 0x0100 /* LIMEN */
+#define WM8985_LIMEN_SHIFT 8 /* LIMEN */
+#define WM8985_LIMEN_WIDTH 1 /* LIMEN */
+#define WM8985_LIMDCY_MASK 0x00F0 /* LIMDCY - [7:4] */
+#define WM8985_LIMDCY_SHIFT 4 /* LIMDCY - [7:4] */
+#define WM8985_LIMDCY_WIDTH 4 /* LIMDCY - [7:4] */
+#define WM8985_LIMATK_MASK 0x000F /* LIMATK - [3:0] */
+#define WM8985_LIMATK_SHIFT 0 /* LIMATK - [3:0] */
+#define WM8985_LIMATK_WIDTH 4 /* LIMATK - [3:0] */
+
+/*
+ * R25 (0x19) - DAC Limiter 2
+ */
+#define WM8985_LIMLVL_MASK 0x0070 /* LIMLVL - [6:4] */
+#define WM8985_LIMLVL_SHIFT 4 /* LIMLVL - [6:4] */
+#define WM8985_LIMLVL_WIDTH 3 /* LIMLVL - [6:4] */
+#define WM8985_LIMBOOST_MASK 0x000F /* LIMBOOST - [3:0] */
+#define WM8985_LIMBOOST_SHIFT 0 /* LIMBOOST - [3:0] */
+#define WM8985_LIMBOOST_WIDTH 4 /* LIMBOOST - [3:0] */
+
+/*
+ * R27 (0x1B) - Notch Filter 1
+ */
+#define WM8985_NFU 0x0100 /* NFU */
+#define WM8985_NFU_MASK 0x0100 /* NFU */
+#define WM8985_NFU_SHIFT 8 /* NFU */
+#define WM8985_NFU_WIDTH 1 /* NFU */
+#define WM8985_NFEN 0x0080 /* NFEN */
+#define WM8985_NFEN_MASK 0x0080 /* NFEN */
+#define WM8985_NFEN_SHIFT 7 /* NFEN */
+#define WM8985_NFEN_WIDTH 1 /* NFEN */
+#define WM8985_NFA0_13_7_MASK 0x007F /* NFA0(13:7) - [6:0] */
+#define WM8985_NFA0_13_7_SHIFT 0 /* NFA0(13:7) - [6:0] */
+#define WM8985_NFA0_13_7_WIDTH 7 /* NFA0(13:7) - [6:0] */
+
+/*
+ * R28 (0x1C) - Notch Filter 2
+ */
+#define WM8985_NFU 0x0100 /* NFU */
+#define WM8985_NFU_MASK 0x0100 /* NFU */
+#define WM8985_NFU_SHIFT 8 /* NFU */
+#define WM8985_NFU_WIDTH 1 /* NFU */
+#define WM8985_NFA0_6_0_MASK 0x007F /* NFA0(6:0) - [6:0] */
+#define WM8985_NFA0_6_0_SHIFT 0 /* NFA0(6:0) - [6:0] */
+#define WM8985_NFA0_6_0_WIDTH 7 /* NFA0(6:0) - [6:0] */
+
+/*
+ * R29 (0x1D) - Notch Filter 3
+ */
+#define WM8985_NFU 0x0100 /* NFU */
+#define WM8985_NFU_MASK 0x0100 /* NFU */
+#define WM8985_NFU_SHIFT 8 /* NFU */
+#define WM8985_NFU_WIDTH 1 /* NFU */
+#define WM8985_NFA1_13_7_MASK 0x007F /* NFA1(13:7) - [6:0] */
+#define WM8985_NFA1_13_7_SHIFT 0 /* NFA1(13:7) - [6:0] */
+#define WM8985_NFA1_13_7_WIDTH 7 /* NFA1(13:7) - [6:0] */
+
+/*
+ * R30 (0x1E) - Notch Filter 4
+ */
+#define WM8985_NFU 0x0100 /* NFU */
+#define WM8985_NFU_MASK 0x0100 /* NFU */
+#define WM8985_NFU_SHIFT 8 /* NFU */
+#define WM8985_NFU_WIDTH 1 /* NFU */
+#define WM8985_NFA1_6_0_MASK 0x007F /* NFA1(6:0) - [6:0] */
+#define WM8985_NFA1_6_0_SHIFT 0 /* NFA1(6:0) - [6:0] */
+#define WM8985_NFA1_6_0_WIDTH 7 /* NFA1(6:0) - [6:0] */
+
+/*
+ * R32 (0x20) - ALC control 1
+ */
+#define WM8985_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */
+#define WM8985_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */
+#define WM8985_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */
+#define WM8985_ALCMAX_MASK 0x0038 /* ALCMAX - [5:3] */
+#define WM8985_ALCMAX_SHIFT 3 /* ALCMAX - [5:3] */
+#define WM8985_ALCMAX_WIDTH 3 /* ALCMAX - [5:3] */
+#define WM8985_ALCMIN_MASK 0x0007 /* ALCMIN - [2:0] */
+#define WM8985_ALCMIN_SHIFT 0 /* ALCMIN - [2:0] */
+#define WM8985_ALCMIN_WIDTH 3 /* ALCMIN - [2:0] */
+
+/*
+ * R33 (0x21) - ALC control 2
+ */
+#define WM8985_ALCHLD_MASK 0x00F0 /* ALCHLD - [7:4] */
+#define WM8985_ALCHLD_SHIFT 4 /* ALCHLD - [7:4] */
+#define WM8985_ALCHLD_WIDTH 4 /* ALCHLD - [7:4] */
+#define WM8985_ALCLVL_MASK 0x000F /* ALCLVL - [3:0] */
+#define WM8985_ALCLVL_SHIFT 0 /* ALCLVL - [3:0] */
+#define WM8985_ALCLVL_WIDTH 4 /* ALCLVL - [3:0] */
+
+/*
+ * R34 (0x22) - ALC control 3
+ */
+#define WM8985_ALCMODE 0x0100 /* ALCMODE */
+#define WM8985_ALCMODE_MASK 0x0100 /* ALCMODE */
+#define WM8985_ALCMODE_SHIFT 8 /* ALCMODE */
+#define WM8985_ALCMODE_WIDTH 1 /* ALCMODE */
+#define WM8985_ALCDCY_MASK 0x00F0 /* ALCDCY - [7:4] */
+#define WM8985_ALCDCY_SHIFT 4 /* ALCDCY - [7:4] */
+#define WM8985_ALCDCY_WIDTH 4 /* ALCDCY - [7:4] */
+#define WM8985_ALCATK_MASK 0x000F /* ALCATK - [3:0] */
+#define WM8985_ALCATK_SHIFT 0 /* ALCATK - [3:0] */
+#define WM8985_ALCATK_WIDTH 4 /* ALCATK - [3:0] */
+
+/*
+ * R35 (0x23) - Noise Gate
+ */
+#define WM8985_NGEN 0x0008 /* NGEN */
+#define WM8985_NGEN_MASK 0x0008 /* NGEN */
+#define WM8985_NGEN_SHIFT 3 /* NGEN */
+#define WM8985_NGEN_WIDTH 1 /* NGEN */
+#define WM8985_NGTH_MASK 0x0007 /* NGTH - [2:0] */
+#define WM8985_NGTH_SHIFT 0 /* NGTH - [2:0] */
+#define WM8985_NGTH_WIDTH 3 /* NGTH - [2:0] */
+
+/*
+ * R36 (0x24) - PLL N
+ */
+#define WM8985_PLL_PRESCALE 0x0010 /* PLL_PRESCALE */
+#define WM8985_PLL_PRESCALE_MASK 0x0010 /* PLL_PRESCALE */
+#define WM8985_PLL_PRESCALE_SHIFT 4 /* PLL_PRESCALE */
+#define WM8985_PLL_PRESCALE_WIDTH 1 /* PLL_PRESCALE */
+#define WM8985_PLLN_MASK 0x000F /* PLLN - [3:0] */
+#define WM8985_PLLN_SHIFT 0 /* PLLN - [3:0] */
+#define WM8985_PLLN_WIDTH 4 /* PLLN - [3:0] */
+
+/*
+ * R37 (0x25) - PLL K 1
+ */
+#define WM8985_PLLK_23_18_MASK 0x003F /* PLLK(23:18) - [5:0] */
+#define WM8985_PLLK_23_18_SHIFT 0 /* PLLK(23:18) - [5:0] */
+#define WM8985_PLLK_23_18_WIDTH 6 /* PLLK(23:18) - [5:0] */
+
+/*
+ * R38 (0x26) - PLL K 2
+ */
+#define WM8985_PLLK_17_9_MASK 0x01FF /* PLLK(17:9) - [8:0] */
+#define WM8985_PLLK_17_9_SHIFT 0 /* PLLK(17:9) - [8:0] */
+#define WM8985_PLLK_17_9_WIDTH 9 /* PLLK(17:9) - [8:0] */
+
+/*
+ * R39 (0x27) - PLL K 3
+ */
+#define WM8985_PLLK_8_0_MASK 0x01FF /* PLLK(8:0) - [8:0] */
+#define WM8985_PLLK_8_0_SHIFT 0 /* PLLK(8:0) - [8:0] */
+#define WM8985_PLLK_8_0_WIDTH 9 /* PLLK(8:0) - [8:0] */
+
+/*
+ * R41 (0x29) - 3D control
+ */
+#define WM8985_DEPTH3D_MASK 0x000F /* DEPTH3D - [3:0] */
+#define WM8985_DEPTH3D_SHIFT 0 /* DEPTH3D - [3:0] */
+#define WM8985_DEPTH3D_WIDTH 4 /* DEPTH3D - [3:0] */
+
+/*
+ * R42 (0x2A) - OUT4 to ADC
+ */
+#define WM8985_OUT4_2ADCVOL_MASK 0x01C0 /* OUT4_2ADCVOL - [8:6] */
+#define WM8985_OUT4_2ADCVOL_SHIFT 6 /* OUT4_2ADCVOL - [8:6] */
+#define WM8985_OUT4_2ADCVOL_WIDTH 3 /* OUT4_2ADCVOL - [8:6] */
+#define WM8985_OUT4_2LNR 0x0020 /* OUT4_2LNR */
+#define WM8985_OUT4_2LNR_MASK 0x0020 /* OUT4_2LNR */
+#define WM8985_OUT4_2LNR_SHIFT 5 /* OUT4_2LNR */
+#define WM8985_OUT4_2LNR_WIDTH 1 /* OUT4_2LNR */
+#define WM8985_POBCTRL 0x0004 /* POBCTRL */
+#define WM8985_POBCTRL_MASK 0x0004 /* POBCTRL */
+#define WM8985_POBCTRL_SHIFT 2 /* POBCTRL */
+#define WM8985_POBCTRL_WIDTH 1 /* POBCTRL */
+#define WM8985_DELEN 0x0002 /* DELEN */
+#define WM8985_DELEN_MASK 0x0002 /* DELEN */
+#define WM8985_DELEN_SHIFT 1 /* DELEN */
+#define WM8985_DELEN_WIDTH 1 /* DELEN */
+#define WM8985_OUT1DEL 0x0001 /* OUT1DEL */
+#define WM8985_OUT1DEL_MASK 0x0001 /* OUT1DEL */
+#define WM8985_OUT1DEL_SHIFT 0 /* OUT1DEL */
+#define WM8985_OUT1DEL_WIDTH 1 /* OUT1DEL */
+
+/*
+ * R43 (0x2B) - Beep control
+ */
+#define WM8985_BYPL2RMIX 0x0100 /* BYPL2RMIX */
+#define WM8985_BYPL2RMIX_MASK 0x0100 /* BYPL2RMIX */
+#define WM8985_BYPL2RMIX_SHIFT 8 /* BYPL2RMIX */
+#define WM8985_BYPL2RMIX_WIDTH 1 /* BYPL2RMIX */
+#define WM8985_BYPR2LMIX 0x0080 /* BYPR2LMIX */
+#define WM8985_BYPR2LMIX_MASK 0x0080 /* BYPR2LMIX */
+#define WM8985_BYPR2LMIX_SHIFT 7 /* BYPR2LMIX */
+#define WM8985_BYPR2LMIX_WIDTH 1 /* BYPR2LMIX */
+#define WM8985_MUTERPGA2INV 0x0020 /* MUTERPGA2INV */
+#define WM8985_MUTERPGA2INV_MASK 0x0020 /* MUTERPGA2INV */
+#define WM8985_MUTERPGA2INV_SHIFT 5 /* MUTERPGA2INV */
+#define WM8985_MUTERPGA2INV_WIDTH 1 /* MUTERPGA2INV */
+#define WM8985_INVROUT2 0x0010 /* INVROUT2 */
+#define WM8985_INVROUT2_MASK 0x0010 /* INVROUT2 */
+#define WM8985_INVROUT2_SHIFT 4 /* INVROUT2 */
+#define WM8985_INVROUT2_WIDTH 1 /* INVROUT2 */
+#define WM8985_BEEPVOL_MASK 0x000E /* BEEPVOL - [3:1] */
+#define WM8985_BEEPVOL_SHIFT 1 /* BEEPVOL - [3:1] */
+#define WM8985_BEEPVOL_WIDTH 3 /* BEEPVOL - [3:1] */
+#define WM8985_BEEPEN 0x0001 /* BEEPEN */
+#define WM8985_BEEPEN_MASK 0x0001 /* BEEPEN */
+#define WM8985_BEEPEN_SHIFT 0 /* BEEPEN */
+#define WM8985_BEEPEN_WIDTH 1 /* BEEPEN */
+
+/*
+ * R44 (0x2C) - Input ctrl
+ */
+#define WM8985_MBVSEL 0x0100 /* MBVSEL */
+#define WM8985_MBVSEL_MASK 0x0100 /* MBVSEL */
+#define WM8985_MBVSEL_SHIFT 8 /* MBVSEL */
+#define WM8985_MBVSEL_WIDTH 1 /* MBVSEL */
+#define WM8985_R2_2INPPGA 0x0040 /* R2_2INPPGA */
+#define WM8985_R2_2INPPGA_MASK 0x0040 /* R2_2INPPGA */
+#define WM8985_R2_2INPPGA_SHIFT 6 /* R2_2INPPGA */
+#define WM8985_R2_2INPPGA_WIDTH 1 /* R2_2INPPGA */
+#define WM8985_RIN2INPPGA 0x0020 /* RIN2INPPGA */
+#define WM8985_RIN2INPPGA_MASK 0x0020 /* RIN2INPPGA */
+#define WM8985_RIN2INPPGA_SHIFT 5 /* RIN2INPPGA */
+#define WM8985_RIN2INPPGA_WIDTH 1 /* RIN2INPPGA */
+#define WM8985_RIP2INPPGA 0x0010 /* RIP2INPPGA */
+#define WM8985_RIP2INPPGA_MASK 0x0010 /* RIP2INPPGA */
+#define WM8985_RIP2INPPGA_SHIFT 4 /* RIP2INPPGA */
+#define WM8985_RIP2INPPGA_WIDTH 1 /* RIP2INPPGA */
+#define WM8985_L2_2INPPGA 0x0004 /* L2_2INPPGA */
+#define WM8985_L2_2INPPGA_MASK 0x0004 /* L2_2INPPGA */
+#define WM8985_L2_2INPPGA_SHIFT 2 /* L2_2INPPGA */
+#define WM8985_L2_2INPPGA_WIDTH 1 /* L2_2INPPGA */
+#define WM8985_LIN2INPPGA 0x0002 /* LIN2INPPGA */
+#define WM8985_LIN2INPPGA_MASK 0x0002 /* LIN2INPPGA */
+#define WM8985_LIN2INPPGA_SHIFT 1 /* LIN2INPPGA */
+#define WM8985_LIN2INPPGA_WIDTH 1 /* LIN2INPPGA */
+#define WM8985_LIP2INPPGA 0x0001 /* LIP2INPPGA */
+#define WM8985_LIP2INPPGA_MASK 0x0001 /* LIP2INPPGA */
+#define WM8985_LIP2INPPGA_SHIFT 0 /* LIP2INPPGA */
+#define WM8985_LIP2INPPGA_WIDTH 1 /* LIP2INPPGA */
+
+/*
+ * R45 (0x2D) - Left INP PGA gain ctrl
+ */
+#define WM8985_INPGAVU 0x0100 /* INPGAVU */
+#define WM8985_INPGAVU_MASK 0x0100 /* INPGAVU */
+#define WM8985_INPGAVU_SHIFT 8 /* INPGAVU */
+#define WM8985_INPGAVU_WIDTH 1 /* INPGAVU */
+#define WM8985_INPPGAZCL 0x0080 /* INPPGAZCL */
+#define WM8985_INPPGAZCL_MASK 0x0080 /* INPPGAZCL */
+#define WM8985_INPPGAZCL_SHIFT 7 /* INPPGAZCL */
+#define WM8985_INPPGAZCL_WIDTH 1 /* INPPGAZCL */
+#define WM8985_INPPGAMUTEL 0x0040 /* INPPGAMUTEL */
+#define WM8985_INPPGAMUTEL_MASK 0x0040 /* INPPGAMUTEL */
+#define WM8985_INPPGAMUTEL_SHIFT 6 /* INPPGAMUTEL */
+#define WM8985_INPPGAMUTEL_WIDTH 1 /* INPPGAMUTEL */
+#define WM8985_INPPGAVOLL_MASK 0x003F /* INPPGAVOLL - [5:0] */
+#define WM8985_INPPGAVOLL_SHIFT 0 /* INPPGAVOLL - [5:0] */
+#define WM8985_INPPGAVOLL_WIDTH 6 /* INPPGAVOLL - [5:0] */
+
+/*
+ * R46 (0x2E) - Right INP PGA gain ctrl
+ */
+#define WM8985_INPGAVU 0x0100 /* INPGAVU */
+#define WM8985_INPGAVU_MASK 0x0100 /* INPGAVU */
+#define WM8985_INPGAVU_SHIFT 8 /* INPGAVU */
+#define WM8985_INPGAVU_WIDTH 1 /* INPGAVU */
+#define WM8985_INPPGAZCR 0x0080 /* INPPGAZCR */
+#define WM8985_INPPGAZCR_MASK 0x0080 /* INPPGAZCR */
+#define WM8985_INPPGAZCR_SHIFT 7 /* INPPGAZCR */
+#define WM8985_INPPGAZCR_WIDTH 1 /* INPPGAZCR */
+#define WM8985_INPPGAMUTER 0x0040 /* INPPGAMUTER */
+#define WM8985_INPPGAMUTER_MASK 0x0040 /* INPPGAMUTER */
+#define WM8985_INPPGAMUTER_SHIFT 6 /* INPPGAMUTER */
+#define WM8985_INPPGAMUTER_WIDTH 1 /* INPPGAMUTER */
+#define WM8985_INPPGAVOLR_MASK 0x003F /* INPPGAVOLR - [5:0] */
+#define WM8985_INPPGAVOLR_SHIFT 0 /* INPPGAVOLR - [5:0] */
+#define WM8985_INPPGAVOLR_WIDTH 6 /* INPPGAVOLR - [5:0] */
+
+/*
+ * R47 (0x2F) - Left ADC BOOST ctrl
+ */
+#define WM8985_PGABOOSTL 0x0100 /* PGABOOSTL */
+#define WM8985_PGABOOSTL_MASK 0x0100 /* PGABOOSTL */
+#define WM8985_PGABOOSTL_SHIFT 8 /* PGABOOSTL */
+#define WM8985_PGABOOSTL_WIDTH 1 /* PGABOOSTL */
+#define WM8985_L2_2BOOSTVOL_MASK 0x0070 /* L2_2BOOSTVOL - [6:4] */
+#define WM8985_L2_2BOOSTVOL_SHIFT 4 /* L2_2BOOSTVOL - [6:4] */
+#define WM8985_L2_2BOOSTVOL_WIDTH 3 /* L2_2BOOSTVOL - [6:4] */
+#define WM8985_AUXL2BOOSTVOL_MASK 0x0007 /* AUXL2BOOSTVOL - [2:0] */
+#define WM8985_AUXL2BOOSTVOL_SHIFT 0 /* AUXL2BOOSTVOL - [2:0] */
+#define WM8985_AUXL2BOOSTVOL_WIDTH 3 /* AUXL2BOOSTVOL - [2:0] */
+
+/*
+ * R48 (0x30) - Right ADC BOOST ctrl
+ */
+#define WM8985_PGABOOSTR 0x0100 /* PGABOOSTR */
+#define WM8985_PGABOOSTR_MASK 0x0100 /* PGABOOSTR */
+#define WM8985_PGABOOSTR_SHIFT 8 /* PGABOOSTR */
+#define WM8985_PGABOOSTR_WIDTH 1 /* PGABOOSTR */
+#define WM8985_R2_2BOOSTVOL_MASK 0x0070 /* R2_2BOOSTVOL - [6:4] */
+#define WM8985_R2_2BOOSTVOL_SHIFT 4 /* R2_2BOOSTVOL - [6:4] */
+#define WM8985_R2_2BOOSTVOL_WIDTH 3 /* R2_2BOOSTVOL - [6:4] */
+#define WM8985_AUXR2BOOSTVOL_MASK 0x0007 /* AUXR2BOOSTVOL - [2:0] */
+#define WM8985_AUXR2BOOSTVOL_SHIFT 0 /* AUXR2BOOSTVOL - [2:0] */
+#define WM8985_AUXR2BOOSTVOL_WIDTH 3 /* AUXR2BOOSTVOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output ctrl
+ */
+#define WM8985_DACL2RMIX 0x0040 /* DACL2RMIX */
+#define WM8985_DACL2RMIX_MASK 0x0040 /* DACL2RMIX */
+#define WM8985_DACL2RMIX_SHIFT 6 /* DACL2RMIX */
+#define WM8985_DACL2RMIX_WIDTH 1 /* DACL2RMIX */
+#define WM8985_DACR2LMIX 0x0020 /* DACR2LMIX */
+#define WM8985_DACR2LMIX_MASK 0x0020 /* DACR2LMIX */
+#define WM8985_DACR2LMIX_SHIFT 5 /* DACR2LMIX */
+#define WM8985_DACR2LMIX_WIDTH 1 /* DACR2LMIX */
+#define WM8985_OUT4BOOST 0x0010 /* OUT4BOOST */
+#define WM8985_OUT4BOOST_MASK 0x0010 /* OUT4BOOST */
+#define WM8985_OUT4BOOST_SHIFT 4 /* OUT4BOOST */
+#define WM8985_OUT4BOOST_WIDTH 1 /* OUT4BOOST */
+#define WM8985_OUT3BOOST 0x0008 /* OUT3BOOST */
+#define WM8985_OUT3BOOST_MASK 0x0008 /* OUT3BOOST */
+#define WM8985_OUT3BOOST_SHIFT 3 /* OUT3BOOST */
+#define WM8985_OUT3BOOST_WIDTH 1 /* OUT3BOOST */
+#define WM8985_TSOPCTRL 0x0004 /* TSOPCTRL */
+#define WM8985_TSOPCTRL_MASK 0x0004 /* TSOPCTRL */
+#define WM8985_TSOPCTRL_SHIFT 2 /* TSOPCTRL */
+#define WM8985_TSOPCTRL_WIDTH 1 /* TSOPCTRL */
+#define WM8985_TSDEN 0x0002 /* TSDEN */
+#define WM8985_TSDEN_MASK 0x0002 /* TSDEN */
+#define WM8985_TSDEN_SHIFT 1 /* TSDEN */
+#define WM8985_TSDEN_WIDTH 1 /* TSDEN */
+#define WM8985_VROI 0x0001 /* VROI */
+#define WM8985_VROI_MASK 0x0001 /* VROI */
+#define WM8985_VROI_SHIFT 0 /* VROI */
+#define WM8985_VROI_WIDTH 1 /* VROI */
+
+/*
+ * R50 (0x32) - Left mixer ctrl
+ */
+#define WM8985_AUXLMIXVOL_MASK 0x01C0 /* AUXLMIXVOL - [8:6] */
+#define WM8985_AUXLMIXVOL_SHIFT 6 /* AUXLMIXVOL - [8:6] */
+#define WM8985_AUXLMIXVOL_WIDTH 3 /* AUXLMIXVOL - [8:6] */
+#define WM8985_AUXL2LMIX 0x0020 /* AUXL2LMIX */
+#define WM8985_AUXL2LMIX_MASK 0x0020 /* AUXL2LMIX */
+#define WM8985_AUXL2LMIX_SHIFT 5 /* AUXL2LMIX */
+#define WM8985_AUXL2LMIX_WIDTH 1 /* AUXL2LMIX */
+#define WM8985_BYPLMIXVOL_MASK 0x001C /* BYPLMIXVOL - [4:2] */
+#define WM8985_BYPLMIXVOL_SHIFT 2 /* BYPLMIXVOL - [4:2] */
+#define WM8985_BYPLMIXVOL_WIDTH 3 /* BYPLMIXVOL - [4:2] */
+#define WM8985_BYPL2LMIX 0x0002 /* BYPL2LMIX */
+#define WM8985_BYPL2LMIX_MASK 0x0002 /* BYPL2LMIX */
+#define WM8985_BYPL2LMIX_SHIFT 1 /* BYPL2LMIX */
+#define WM8985_BYPL2LMIX_WIDTH 1 /* BYPL2LMIX */
+#define WM8985_DACL2LMIX 0x0001 /* DACL2LMIX */
+#define WM8985_DACL2LMIX_MASK 0x0001 /* DACL2LMIX */
+#define WM8985_DACL2LMIX_SHIFT 0 /* DACL2LMIX */
+#define WM8985_DACL2LMIX_WIDTH 1 /* DACL2LMIX */
+
+/*
+ * R51 (0x33) - Right mixer ctrl
+ */
+#define WM8985_AUXRMIXVOL_MASK 0x01C0 /* AUXRMIXVOL - [8:6] */
+#define WM8985_AUXRMIXVOL_SHIFT 6 /* AUXRMIXVOL - [8:6] */
+#define WM8985_AUXRMIXVOL_WIDTH 3 /* AUXRMIXVOL - [8:6] */
+#define WM8985_AUXR2RMIX 0x0020 /* AUXR2RMIX */
+#define WM8985_AUXR2RMIX_MASK 0x0020 /* AUXR2RMIX */
+#define WM8985_AUXR2RMIX_SHIFT 5 /* AUXR2RMIX */
+#define WM8985_AUXR2RMIX_WIDTH 1 /* AUXR2RMIX */
+#define WM8985_BYPRMIXVOL_MASK 0x001C /* BYPRMIXVOL - [4:2] */
+#define WM8985_BYPRMIXVOL_SHIFT 2 /* BYPRMIXVOL - [4:2] */
+#define WM8985_BYPRMIXVOL_WIDTH 3 /* BYPRMIXVOL - [4:2] */
+#define WM8985_BYPR2RMIX 0x0002 /* BYPR2RMIX */
+#define WM8985_BYPR2RMIX_MASK 0x0002 /* BYPR2RMIX */
+#define WM8985_BYPR2RMIX_SHIFT 1 /* BYPR2RMIX */
+#define WM8985_BYPR2RMIX_WIDTH 1 /* BYPR2RMIX */
+#define WM8985_DACR2RMIX 0x0001 /* DACR2RMIX */
+#define WM8985_DACR2RMIX_MASK 0x0001 /* DACR2RMIX */
+#define WM8985_DACR2RMIX_SHIFT 0 /* DACR2RMIX */
+#define WM8985_DACR2RMIX_WIDTH 1 /* DACR2RMIX */
+
+/*
+ * R52 (0x34) - LOUT1 (HP) volume ctrl
+ */
+#define WM8985_OUT1VU 0x0100 /* OUT1VU */
+#define WM8985_OUT1VU_MASK 0x0100 /* OUT1VU */
+#define WM8985_OUT1VU_SHIFT 8 /* OUT1VU */
+#define WM8985_OUT1VU_WIDTH 1 /* OUT1VU */
+#define WM8985_LOUT1ZC 0x0080 /* LOUT1ZC */
+#define WM8985_LOUT1ZC_MASK 0x0080 /* LOUT1ZC */
+#define WM8985_LOUT1ZC_SHIFT 7 /* LOUT1ZC */
+#define WM8985_LOUT1ZC_WIDTH 1 /* LOUT1ZC */
+#define WM8985_LOUT1MUTE 0x0040 /* LOUT1MUTE */
+#define WM8985_LOUT1MUTE_MASK 0x0040 /* LOUT1MUTE */
+#define WM8985_LOUT1MUTE_SHIFT 6 /* LOUT1MUTE */
+#define WM8985_LOUT1MUTE_WIDTH 1 /* LOUT1MUTE */
+#define WM8985_LOUT1VOL_MASK 0x003F /* LOUT1VOL - [5:0] */
+#define WM8985_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [5:0] */
+#define WM8985_LOUT1VOL_WIDTH 6 /* LOUT1VOL - [5:0] */
+
+/*
+ * R53 (0x35) - ROUT1 (HP) volume ctrl
+ */
+#define WM8985_OUT1VU 0x0100 /* OUT1VU */
+#define WM8985_OUT1VU_MASK 0x0100 /* OUT1VU */
+#define WM8985_OUT1VU_SHIFT 8 /* OUT1VU */
+#define WM8985_OUT1VU_WIDTH 1 /* OUT1VU */
+#define WM8985_ROUT1ZC 0x0080 /* ROUT1ZC */
+#define WM8985_ROUT1ZC_MASK 0x0080 /* ROUT1ZC */
+#define WM8985_ROUT1ZC_SHIFT 7 /* ROUT1ZC */
+#define WM8985_ROUT1ZC_WIDTH 1 /* ROUT1ZC */
+#define WM8985_ROUT1MUTE 0x0040 /* ROUT1MUTE */
+#define WM8985_ROUT1MUTE_MASK 0x0040 /* ROUT1MUTE */
+#define WM8985_ROUT1MUTE_SHIFT 6 /* ROUT1MUTE */
+#define WM8985_ROUT1MUTE_WIDTH 1 /* ROUT1MUTE */
+#define WM8985_ROUT1VOL_MASK 0x003F /* ROUT1VOL - [5:0] */
+#define WM8985_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [5:0] */
+#define WM8985_ROUT1VOL_WIDTH 6 /* ROUT1VOL - [5:0] */
+
+/*
+ * R54 (0x36) - LOUT2 (SPK) volume ctrl
+ */
+#define WM8985_OUT2VU 0x0100 /* OUT2VU */
+#define WM8985_OUT2VU_MASK 0x0100 /* OUT2VU */
+#define WM8985_OUT2VU_SHIFT 8 /* OUT2VU */
+#define WM8985_OUT2VU_WIDTH 1 /* OUT2VU */
+#define WM8985_LOUT2ZC 0x0080 /* LOUT2ZC */
+#define WM8985_LOUT2ZC_MASK 0x0080 /* LOUT2ZC */
+#define WM8985_LOUT2ZC_SHIFT 7 /* LOUT2ZC */
+#define WM8985_LOUT2ZC_WIDTH 1 /* LOUT2ZC */
+#define WM8985_LOUT2MUTE 0x0040 /* LOUT2MUTE */
+#define WM8985_LOUT2MUTE_MASK 0x0040 /* LOUT2MUTE */
+#define WM8985_LOUT2MUTE_SHIFT 6 /* LOUT2MUTE */
+#define WM8985_LOUT2MUTE_WIDTH 1 /* LOUT2MUTE */
+#define WM8985_LOUT2VOL_MASK 0x003F /* LOUT2VOL - [5:0] */
+#define WM8985_LOUT2VOL_SHIFT 0 /* LOUT2VOL - [5:0] */
+#define WM8985_LOUT2VOL_WIDTH 6 /* LOUT2VOL - [5:0] */
+
+/*
+ * R55 (0x37) - ROUT2 (SPK) volume ctrl
+ */
+#define WM8985_OUT2VU 0x0100 /* OUT2VU */
+#define WM8985_OUT2VU_MASK 0x0100 /* OUT2VU */
+#define WM8985_OUT2VU_SHIFT 8 /* OUT2VU */
+#define WM8985_OUT2VU_WIDTH 1 /* OUT2VU */
+#define WM8985_ROUT2ZC 0x0080 /* ROUT2ZC */
+#define WM8985_ROUT2ZC_MASK 0x0080 /* ROUT2ZC */
+#define WM8985_ROUT2ZC_SHIFT 7 /* ROUT2ZC */
+#define WM8985_ROUT2ZC_WIDTH 1 /* ROUT2ZC */
+#define WM8985_ROUT2MUTE 0x0040 /* ROUT2MUTE */
+#define WM8985_ROUT2MUTE_MASK 0x0040 /* ROUT2MUTE */
+#define WM8985_ROUT2MUTE_SHIFT 6 /* ROUT2MUTE */
+#define WM8985_ROUT2MUTE_WIDTH 1 /* ROUT2MUTE */
+#define WM8985_ROUT2VOL_MASK 0x003F /* ROUT2VOL - [5:0] */
+#define WM8985_ROUT2VOL_SHIFT 0 /* ROUT2VOL - [5:0] */
+#define WM8985_ROUT2VOL_WIDTH 6 /* ROUT2VOL - [5:0] */
+
+/*
+ * R56 (0x38) - OUT3 mixer ctrl
+ */
+#define WM8985_OUT3MUTE 0x0040 /* OUT3MUTE */
+#define WM8985_OUT3MUTE_MASK 0x0040 /* OUT3MUTE */
+#define WM8985_OUT3MUTE_SHIFT 6 /* OUT3MUTE */
+#define WM8985_OUT3MUTE_WIDTH 1 /* OUT3MUTE */
+#define WM8985_OUT4_2OUT3 0x0008 /* OUT4_2OUT3 */
+#define WM8985_OUT4_2OUT3_MASK 0x0008 /* OUT4_2OUT3 */
+#define WM8985_OUT4_2OUT3_SHIFT 3 /* OUT4_2OUT3 */
+#define WM8985_OUT4_2OUT3_WIDTH 1 /* OUT4_2OUT3 */
+#define WM8985_BYPL2OUT3 0x0004 /* BYPL2OUT3 */
+#define WM8985_BYPL2OUT3_MASK 0x0004 /* BYPL2OUT3 */
+#define WM8985_BYPL2OUT3_SHIFT 2 /* BYPL2OUT3 */
+#define WM8985_BYPL2OUT3_WIDTH 1 /* BYPL2OUT3 */
+#define WM8985_LMIX2OUT3 0x0002 /* LMIX2OUT3 */
+#define WM8985_LMIX2OUT3_MASK 0x0002 /* LMIX2OUT3 */
+#define WM8985_LMIX2OUT3_SHIFT 1 /* LMIX2OUT3 */
+#define WM8985_LMIX2OUT3_WIDTH 1 /* LMIX2OUT3 */
+#define WM8985_LDAC2OUT3 0x0001 /* LDAC2OUT3 */
+#define WM8985_LDAC2OUT3_MASK 0x0001 /* LDAC2OUT3 */
+#define WM8985_LDAC2OUT3_SHIFT 0 /* LDAC2OUT3 */
+#define WM8985_LDAC2OUT3_WIDTH 1 /* LDAC2OUT3 */
+
+/*
+ * R57 (0x39) - OUT4 (MONO) mix ctrl
+ */
+#define WM8985_OUT3_2OUT4 0x0080 /* OUT3_2OUT4 */
+#define WM8985_OUT3_2OUT4_MASK 0x0080 /* OUT3_2OUT4 */
+#define WM8985_OUT3_2OUT4_SHIFT 7 /* OUT3_2OUT4 */
+#define WM8985_OUT3_2OUT4_WIDTH 1 /* OUT3_2OUT4 */
+#define WM8985_OUT4MUTE 0x0040 /* OUT4MUTE */
+#define WM8985_OUT4MUTE_MASK 0x0040 /* OUT4MUTE */
+#define WM8985_OUT4MUTE_SHIFT 6 /* OUT4MUTE */
+#define WM8985_OUT4MUTE_WIDTH 1 /* OUT4MUTE */
+#define WM8985_OUT4ATTN 0x0020 /* OUT4ATTN */
+#define WM8985_OUT4ATTN_MASK 0x0020 /* OUT4ATTN */
+#define WM8985_OUT4ATTN_SHIFT 5 /* OUT4ATTN */
+#define WM8985_OUT4ATTN_WIDTH 1 /* OUT4ATTN */
+#define WM8985_LMIX2OUT4 0x0010 /* LMIX2OUT4 */
+#define WM8985_LMIX2OUT4_MASK 0x0010 /* LMIX2OUT4 */
+#define WM8985_LMIX2OUT4_SHIFT 4 /* LMIX2OUT4 */
+#define WM8985_LMIX2OUT4_WIDTH 1 /* LMIX2OUT4 */
+#define WM8985_LDAC2OUT4 0x0008 /* LDAC2OUT4 */
+#define WM8985_LDAC2OUT4_MASK 0x0008 /* LDAC2OUT4 */
+#define WM8985_LDAC2OUT4_SHIFT 3 /* LDAC2OUT4 */
+#define WM8985_LDAC2OUT4_WIDTH 1 /* LDAC2OUT4 */
+#define WM8985_BYPR2OUT4 0x0004 /* BYPR2OUT4 */
+#define WM8985_BYPR2OUT4_MASK 0x0004 /* BYPR2OUT4 */
+#define WM8985_BYPR2OUT4_SHIFT 2 /* BYPR2OUT4 */
+#define WM8985_BYPR2OUT4_WIDTH 1 /* BYPR2OUT4 */
+#define WM8985_RMIX2OUT4 0x0002 /* RMIX2OUT4 */
+#define WM8985_RMIX2OUT4_MASK 0x0002 /* RMIX2OUT4 */
+#define WM8985_RMIX2OUT4_SHIFT 1 /* RMIX2OUT4 */
+#define WM8985_RMIX2OUT4_WIDTH 1 /* RMIX2OUT4 */
+#define WM8985_RDAC2OUT4 0x0001 /* RDAC2OUT4 */
+#define WM8985_RDAC2OUT4_MASK 0x0001 /* RDAC2OUT4 */
+#define WM8985_RDAC2OUT4_SHIFT 0 /* RDAC2OUT4 */
+#define WM8985_RDAC2OUT4_WIDTH 1 /* RDAC2OUT4 */
+
+/*
+ * R60 (0x3C) - OUTPUT ctrl
+ */
+#define WM8985_VIDBUFFTST_MASK 0x01E0 /* VIDBUFFTST - [8:5] */
+#define WM8985_VIDBUFFTST_SHIFT 5 /* VIDBUFFTST - [8:5] */
+#define WM8985_VIDBUFFTST_WIDTH 4 /* VIDBUFFTST - [8:5] */
+#define WM8985_HPTOG 0x0008 /* HPTOG */
+#define WM8985_HPTOG_MASK 0x0008 /* HPTOG */
+#define WM8985_HPTOG_SHIFT 3 /* HPTOG */
+#define WM8985_HPTOG_WIDTH 1 /* HPTOG */
+
+/*
+ * R61 (0x3D) - BIAS CTRL
+ */
+#define WM8985_BIASCUT 0x0100 /* BIASCUT */
+#define WM8985_BIASCUT_MASK 0x0100 /* BIASCUT */
+#define WM8985_BIASCUT_SHIFT 8 /* BIASCUT */
+#define WM8985_BIASCUT_WIDTH 1 /* BIASCUT */
+#define WM8985_HALFIPBIAS 0x0080 /* HALFIPBIAS */
+#define WM8985_HALFIPBIAS_MASK 0x0080 /* HALFIPBIAS */
+#define WM8985_HALFIPBIAS_SHIFT 7 /* HALFIPBIAS */
+#define WM8985_HALFIPBIAS_WIDTH 1 /* HALFIPBIAS */
+#define WM8985_VBBIASTST_MASK 0x0060 /* VBBIASTST - [6:5] */
+#define WM8985_VBBIASTST_SHIFT 5 /* VBBIASTST - [6:5] */
+#define WM8985_VBBIASTST_WIDTH 2 /* VBBIASTST - [6:5] */
+#define WM8985_BUFBIAS_MASK 0x0018 /* BUFBIAS - [4:3] */
+#define WM8985_BUFBIAS_SHIFT 3 /* BUFBIAS - [4:3] */
+#define WM8985_BUFBIAS_WIDTH 2 /* BUFBIAS - [4:3] */
+#define WM8985_ADCBIAS_MASK 0x0006 /* ADCBIAS - [2:1] */
+#define WM8985_ADCBIAS_SHIFT 1 /* ADCBIAS - [2:1] */
+#define WM8985_ADCBIAS_WIDTH 2 /* ADCBIAS - [2:1] */
+#define WM8985_HALFOPBIAS 0x0001 /* HALFOPBIAS */
+#define WM8985_HALFOPBIAS_MASK 0x0001 /* HALFOPBIAS */
+#define WM8985_HALFOPBIAS_SHIFT 0 /* HALFOPBIAS */
+#define WM8985_HALFOPBIAS_WIDTH 1 /* HALFOPBIAS */
+
+enum clk_src {
+ WM8985_CLKSRC_MCLK,
+ WM8985_CLKSRC_PLL
+};
+
+#define WM8985_PLL 0
+
+#endif
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 19ad590ca0b3..d7f259711970 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -52,7 +52,7 @@ static const u16 wm8988_reg[] = {
/* codec private data */
struct wm8988_priv {
unsigned int sysclk;
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
u16 reg_cache[WM8988_NUM_REG];
};
@@ -608,8 +608,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
@@ -711,8 +710,8 @@ static struct snd_soc_dai_ops wm8988_ops = {
.digital_mute = wm8988_mute,
};
-struct snd_soc_dai wm8988_dai = {
- .name = "WM8988",
+static struct snd_soc_dai_driver wm8988_dai = {
+ .name = "wm8988-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -730,21 +729,15 @@ struct snd_soc_dai wm8988_dai = {
.ops = &wm8988_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8988_dai);
-static int wm8988_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8988_resume(struct platform_device *pdev)
+static int wm8988_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -763,99 +756,22 @@ static int wm8988_resume(struct platform_device *pdev)
return 0;
}
-static struct snd_soc_codec *wm8988_codec;
-
-static int wm8988_probe(struct platform_device *pdev)
+static int wm8988_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
+ struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
-
- if (wm8988_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8988_codec;
- codec = wm8988_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
- }
-
- snd_soc_add_controls(codec, wm8988_snd_controls,
- ARRAY_SIZE(wm8988_snd_controls));
- snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
- ARRAY_SIZE(wm8988_dapm_widgets));
- snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
-
- return ret;
-
-pcm_err:
- return ret;
-}
-
-static int wm8988_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8988 = {
- .probe = wm8988_probe,
- .remove = wm8988_remove,
- .suspend = wm8988_suspend,
- .resume = wm8988_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
-
-static int wm8988_register(struct wm8988_priv *wm8988,
- enum snd_soc_control_type control)
-{
- struct snd_soc_codec *codec = &wm8988->codec;
- int ret;
u16 reg;
- if (wm8988_codec) {
- dev_err(codec->dev, "Another WM8988 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm8988);
- codec->name = "WM8988";
- codec->owner = THIS_MODULE;
- codec->dai = &wm8988_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
- codec->reg_cache = &wm8988->reg_cache;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8988_set_bias_level;
-
- memcpy(codec->reg_cache, wm8988_reg,
- sizeof(wm8988_reg));
-
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
+ return ret;
}
ret = wm8988_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
- goto err;
+ return ret;
}
/* set the update bits (we always update left then right) */
@@ -870,139 +786,132 @@ static int wm8988_register(struct wm8988_priv *wm8988,
reg = snd_soc_read(codec, WM8988_RINVOL);
snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
- wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
-
- wm8988_dai.dev = codec->dev;
-
- wm8988_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
+ wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- ret = snd_soc_register_dai(&wm8988_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
+ snd_soc_add_controls(codec, wm8988_snd_controls,
+ ARRAY_SIZE(wm8988_snd_controls));
+ snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
+ ARRAY_SIZE(wm8988_dapm_widgets));
+ snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm8988);
- return ret;
}
-static void wm8988_unregister(struct wm8988_priv *wm8988)
+static int wm8988_remove(struct snd_soc_codec *codec)
{
- wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm8988_dai);
- snd_soc_unregister_codec(&wm8988->codec);
- kfree(wm8988);
- wm8988_codec = NULL;
+ wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static int wm8988_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
+ .probe = wm8988_probe,
+ .remove = wm8988_remove,
+ .suspend = wm8988_suspend,
+ .resume = wm8988_resume,
+ .set_bias_level = wm8988_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8988_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8988_reg,
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8988_spi_probe(struct spi_device *spi)
{
struct wm8988_priv *wm8988;
- struct snd_soc_codec *codec;
+ int ret;
wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
if (wm8988 == NULL)
return -ENOMEM;
- codec = &wm8988->codec;
-
- i2c_set_clientdata(i2c, wm8988);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
+ wm8988->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8988);
- return wm8988_register(wm8988, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8988, &wm8988_dai, 1);
+ if (ret < 0)
+ kfree(wm8988);
+ return ret;
}
-static int wm8988_i2c_remove(struct i2c_client *client)
+static int __devexit wm8988_spi_remove(struct spi_device *spi)
{
- struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
- wm8988_unregister(wm8988);
+ snd_soc_unregister_codec(&spi->dev);
+ kfree(spi_get_drvdata(spi));
return 0;
}
-static const struct i2c_device_id wm8988_i2c_id[] = {
- { "wm8988", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
-
-static struct i2c_driver wm8988_i2c_driver = {
+static struct spi_driver wm8988_spi_driver = {
.driver = {
- .name = "WM8988",
- .owner = THIS_MODULE,
+ .name = "wm8988-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8988_i2c_probe,
- .remove = wm8988_i2c_remove,
- .id_table = wm8988_i2c_id,
+ .probe = wm8988_spi_probe,
+ .remove = __devexit_p(wm8988_spi_remove),
};
-#endif
+#endif /* CONFIG_SPI_MASTER */
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8988_spi_probe(struct spi_device *spi)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8988_priv *wm8988;
- struct snd_soc_codec *codec;
+ int ret;
wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
if (wm8988 == NULL)
return -ENOMEM;
- codec = &wm8988->codec;
- codec->control_data = spi;
- codec->dev = &spi->dev;
-
- dev_set_drvdata(&spi->dev, wm8988);
+ i2c_set_clientdata(i2c, wm8988);
+ wm8988->control_type = SND_SOC_I2C;
- return wm8988_register(wm8988, SND_SOC_SPI);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8988, &wm8988_dai, 1);
+ if (ret < 0)
+ kfree(wm8988);
+ return ret;
}
-static int __devexit wm8988_spi_remove(struct spi_device *spi)
+static __devexit int wm8988_i2c_remove(struct i2c_client *client)
{
- struct wm8988_priv *wm8988 = dev_get_drvdata(&spi->dev);
-
- wm8988_unregister(wm8988);
-
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
-static struct spi_driver wm8988_spi_driver = {
+static const struct i2c_device_id wm8988_i2c_id[] = {
+ { "wm8988", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
+
+static struct i2c_driver wm8988_i2c_driver = {
.driver = {
- .name = "wm8988",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
+ .name = "wm8988-codec",
+ .owner = THIS_MODULE,
},
- .probe = wm8988_spi_probe,
- .remove = __devexit_p(wm8988_spi_remove),
+ .probe = wm8988_i2c_probe,
+ .remove = __devexit_p(wm8988_i2c_remove),
+ .id_table = wm8988_i2c_id,
};
#endif
static int __init wm8988_modinit(void)
{
- int ret;
-
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8988_i2c_driver);
- if (ret != 0)
- pr_err("WM8988: Unable to register I2C driver: %d\n", ret);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n",
+ ret);
+ }
#endif
#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&wm8988_spi_driver);
- if (ret != 0)
- pr_err("WM8988: Unable to register SPI driver: %d\n", ret);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n",
+ ret);
+ }
#endif
return ret;
}
diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h
index 4552d37fdd41..5c04024e5f9f 100644
--- a/sound/soc/codecs/wm8988.h
+++ b/sound/soc/codecs/wm8988.h
@@ -54,7 +54,4 @@
#define WM8988_SYSCLK 0
-extern struct snd_soc_dai wm8988_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8988;
-
#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index dd8d909788c1..264828e4e67c 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -32,6 +32,7 @@
/* codec private data */
struct wm8990_priv {
+ enum snd_soc_control_type control_type;
unsigned int sysclk;
unsigned int pcmclk;
};
@@ -1114,8 +1115,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
audio1 &= ~WM8990_AIF_WL_MASK;
@@ -1293,10 +1293,9 @@ static struct snd_soc_dai_ops wm8990_dai_ops = {
.set_sysclk = wm8990_set_dai_sysclk,
};
-struct snd_soc_dai wm8990_dai = {
+static struct snd_soc_dai_driver wm8990_dai = {
/* ADC/DAC on primary */
- .name = "WM8990 ADC/DAC Primary",
- .id = 1,
+ .name = "wm8990-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -1311,21 +1310,15 @@ struct snd_soc_dai wm8990_dai = {
.formats = WM8990_FORMATS,},
.ops = &wm8990_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm8990_dai);
-static int wm8990_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm8990_resume(struct platform_device *pdev)
+static int wm8990_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i;
u8 data[2];
u16 *cache = codec->reg_cache;
@@ -1347,40 +1340,20 @@ static int wm8990_resume(struct platform_device *pdev)
* initialise the WM8990 driver
* register the mixer and dsp interfaces with the kernel
*/
-static int wm8990_init(struct snd_soc_device *socdev)
+static int wm8990_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = socdev->card->codec;
+ int ret;
u16 reg;
- int ret = 0;
-
- codec->name = "WM8990";
- codec->owner = THIS_MODULE;
- codec->set_bias_level = wm8990_set_bias_level;
- codec->dai = &wm8990_dai;
- codec->num_dai = 2;
- codec->reg_cache_size = ARRAY_SIZE(wm8990_reg);
- codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL);
-
- if (codec->reg_cache == NULL)
- return -ENOMEM;
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
if (ret < 0) {
printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
- goto pcm_err;
+ return ret;
}
wm8990_reset(codec);
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "wm8990: failed to create pcms\n");
- goto pcm_err;
- }
-
/* charge output caps */
- codec->bias_level = SND_SOC_BIAS_OFF;
wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
@@ -1400,47 +1373,51 @@ static int wm8990_init(struct snd_soc_device *socdev)
ARRAY_SIZE(wm8990_snd_controls));
wm8990_add_widgets(codec);
- return ret;
+ return 0;
+}
-pcm_err:
- kfree(codec->reg_cache);
- return ret;
+/* power down chip */
+static int wm8990_remove(struct snd_soc_codec *codec)
+{
+ wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
}
-/* If the i2c layer weren't so broken, we could pass this kind of data
- around */
-static struct snd_soc_device *wm8990_socdev;
+static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
+ .probe = wm8990_probe,
+ .remove = wm8990_remove,
+ .suspend = wm8990_suspend,
+ .resume = wm8990_resume,
+ .set_bias_level = wm8990_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8990_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8990_reg,
+};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-/*
- * WM891 2 wire address is determined by GPIO5
- * state during powerup.
- * low = 0x34
- * high = 0x36
- */
-
-static int wm8990_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
- struct snd_soc_device *socdev = wm8990_socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct wm8990_priv *wm8990;
int ret;
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
+ wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
+ if (wm8990 == NULL)
+ return -ENOMEM;
- ret = wm8990_init(socdev);
- if (ret < 0)
- pr_err("failed to initialise WM8990\n");
+ i2c_set_clientdata(i2c, wm8990);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8990, &wm8990_dai, 1);
+ if (ret < 0)
+ kfree(wm8990);
return ret;
}
-static int wm8990_i2c_remove(struct i2c_client *client)
+static __devexit int wm8990_i2c_remove(struct i2c_client *client)
{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1452,134 +1429,34 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
static struct i2c_driver wm8990_i2c_driver = {
.driver = {
- .name = "WM8990 I2C Codec",
+ .name = "wm8990-codec",
.owner = THIS_MODULE,
},
.probe = wm8990_i2c_probe,
- .remove = wm8990_i2c_remove,
+ .remove = __devexit_p(wm8990_i2c_remove),
.id_table = wm8990_i2c_id,
};
-
-static int wm8990_add_i2c_device(struct platform_device *pdev,
- const struct wm8990_setup_data *setup)
-{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- int ret;
-
- ret = i2c_add_driver(&wm8990_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = setup->i2c_address;
- strlcpy(info.type, "wm8990", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n",
- setup->i2c_bus);
- goto err_driver;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
-
- return 0;
-
-err_driver:
- i2c_del_driver(&wm8990_i2c_driver);
- return -ENODEV;
-}
#endif
-static int wm8990_probe(struct platform_device *pdev)
+static int __init wm8990_modinit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8990_setup_data *setup;
- struct snd_soc_codec *codec;
- struct wm8990_priv *wm8990;
- int ret;
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
- if (wm8990 == NULL) {
- kfree(codec);
- return -ENOMEM;
- }
-
- snd_soc_codec_set_drvdata(codec, wm8990);
- socdev->card->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
- wm8990_socdev = socdev;
-
- ret = -ENODEV;
-
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- codec->hw_write = (hw_write_t)i2c_master_send;
- ret = wm8990_add_i2c_device(pdev, setup);
- }
-#endif
-
+ ret = i2c_add_driver(&wm8990_i2c_driver);
if (ret != 0) {
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec);
+ printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n",
+ ret);
}
+#endif
return ret;
}
+module_init(wm8990_modinit);
-/* power down chip */
-static int wm8990_remove(struct platform_device *pdev)
+static void __exit wm8990_exit(void)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec->control_data)
- wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8990_i2c_driver);
#endif
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8990 = {
- .probe = wm8990_probe,
- .remove = wm8990_remove,
- .suspend = wm8990_suspend,
- .resume = wm8990_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
-
-static int __init wm8990_modinit(void)
-{
- return snd_soc_register_dai(&wm8990_dai);
-}
-module_init(wm8990_modinit);
-
-static void __exit wm8990_exit(void)
-{
- snd_soc_unregister_dai(&wm8990_dai);
}
module_exit(wm8990_exit);
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h
index 7114ddc88b4b..77c98a4bfe9c 100644
--- a/sound/soc/codecs/wm8990.h
+++ b/sound/soc/codecs/wm8990.h
@@ -826,18 +826,10 @@
#define WM8990_INMIXR_PWR_BIT 2
#define WM8990_AINRMUX_PWR_BIT 3
-struct wm8990_setup_data {
- unsigned i2c_bus;
- unsigned short i2c_address;
-};
-
#define WM8990_MCLK_DIV 0
#define WM8990_DACCLK_DIV 1
#define WM8990_ADCCLK_DIV 2
#define WM8990_BCLK_DIV 3
-extern struct snd_soc_dai wm8990_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8990;
-
#endif /* __WM8990REGISTERDEFS_H__ */
/*------------------------------ END OF FILE ---------------------------------*/
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index d8d300c6175f..589e3fa24734 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -229,7 +229,7 @@ struct wm8993_priv {
u16 reg_cache[WM8993_REGISTER_COUNT];
struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES];
struct wm8993_platform_data pdata;
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
int master;
int sysclk_source;
int tdm_slots;
@@ -367,10 +367,9 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
return 0;
}
-static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
+static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
unsigned int Fref, unsigned int Fout)
{
- struct snd_soc_codec *codec = dai->codec;
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
u16 reg1, reg4, reg5;
struct _fll_div fll_div;
@@ -456,6 +455,12 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
return 0;
}
+static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
+ unsigned int Fref, unsigned int Fout)
+{
+ return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout);
+}
+
static int configure_clock(struct snd_soc_codec *codec)
{
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
@@ -1394,8 +1399,8 @@ static struct snd_soc_dai_ops wm8993_ops = {
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
-struct snd_soc_dai wm8993_dai = {
- .name = "WM8993",
+static struct snd_soc_dai_driver wm8993_dai = {
+ .name = "wm8993-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
@@ -1413,32 +1418,81 @@ struct snd_soc_dai wm8993_dai = {
.ops = &wm8993_ops,
.symmetric_rates = 1,
};
-EXPORT_SYMBOL_GPL(wm8993_dai);
-
-static struct snd_soc_codec *wm8993_codec;
-static int wm8993_probe(struct platform_device *pdev)
+static int wm8993_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct wm8993_priv *wm8993;
- int ret = 0;
+ struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
+ int ret, i, val;
+
+ wm8993->hubs_data.hp_startup_mode = 1;
+ wm8993->hubs_data.dcs_codes = -2;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
+ wm8993->supplies[i].supply = wm8993_supply_names[i];
- if (!wm8993_codec) {
- dev_err(&pdev->dev, "I2C device not yet probed\n");
- goto err;
+ ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
+ wm8993->supplies);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ return ret;
}
- socdev->card->codec = wm8993_codec;
- codec = wm8993_codec;
- wm8993 = snd_soc_codec_get_drvdata(codec);
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
+ wm8993->supplies);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_get;
+ }
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms\n");
- goto err;
+ val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
+ if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
+ dev_err(codec->dev, "Invalid ID register value %x\n", val);
+ ret = -EINVAL;
+ goto err_enable;
}
+ ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
+ if (ret != 0)
+ goto err_enable;
+
+ codec->cache_only = 1;
+
+ /* By default we're using the output mixers */
+ wm8993->class_w_users = 2;
+
+ /* Latch volume update bits and default ZC on */
+ snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
+ WM8993_DAC_VU, WM8993_DAC_VU);
+ snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
+ WM8993_ADC_VU, WM8993_ADC_VU);
+
+ /* Manualy manage the HPOUT sequencing for independent stereo
+ * control. */
+ snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
+ WM8993_HPOUT1_AUTO_PU, 0);
+
+ /* Use automatic clock configuration */
+ snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
+
+ wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
+ wm8993->pdata.lineout2_diff,
+ wm8993->pdata.lineout1fb,
+ wm8993->pdata.lineout2fb,
+ wm8993->pdata.jd_scthr,
+ wm8993->pdata.jd_thr,
+ wm8993->pdata.micbias1_lvl,
+ wm8993->pdata.micbias2_lvl);
+
+ ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ if (ret != 0)
+ goto err_enable;
+
snd_soc_add_controls(codec, wm8993_snd_controls,
ARRAY_SIZE(wm8993_snd_controls));
if (wm8993->pdata.num_retune_configs != 0) {
@@ -1457,36 +1511,36 @@ static int wm8993_probe(struct platform_device *pdev)
wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
wm8993->pdata.lineout2_diff);
- return ret;
+ return 0;
-err:
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
return ret;
}
-static int wm8993_remove(struct platform_device *pdev)
+static int wm8993_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
+ wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
return 0;
}
#ifdef CONFIG_PM
-static int wm8993_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
int fll_fout = wm8993->fll_fout;
int fll_fref = wm8993->fll_fref;
int ret;
/* Stop the FLL in an orderly fashion */
- ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0);
+ ret = _wm8993_set_fll(codec, 0, 0, 0, 0);
if (ret != 0) {
- dev_err(&pdev->dev, "Failed to stop FLL\n");
+ dev_err(codec->dev, "Failed to stop FLL\n");
return ret;
}
@@ -1498,10 +1552,8 @@ static int wm8993_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int wm8993_resume(struct platform_device *pdev)
+static int wm8993_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
int ret;
@@ -1515,7 +1567,7 @@ static int wm8993_resume(struct platform_device *pdev)
wm8993->fll_fref = 0;
wm8993->fll_fout = 0;
- ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src,
+ ret = _wm8993_set_fll(codec, 0, wm8993->fll_src,
fll_fref, fll_fout);
if (ret != 0)
dev_err(codec->dev, "Failed to restart FLL\n");
@@ -1528,162 +1580,42 @@ static int wm8993_resume(struct platform_device *pdev)
#define wm8993_resume NULL
#endif
-struct snd_soc_codec_device soc_codec_dev_wm8993 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
.probe = wm8993_probe,
.remove = wm8993_remove,
.suspend = wm8993_suspend,
.resume = wm8993_resume,
+ .set_bias_level = wm8993_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm8993_reg_defaults),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm8993_reg_defaults,
+ .volatile_register = wm8993_volatile,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993);
-static int wm8993_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8993_priv *wm8993;
- struct snd_soc_codec *codec;
- unsigned int val;
int ret;
- int i;
-
- if (wm8993_codec) {
- dev_err(&i2c->dev, "A WM8993 is already registered\n");
- return -EINVAL;
- }
wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);
if (wm8993 == NULL)
return -ENOMEM;
- codec = &wm8993->codec;
- if (i2c->dev.platform_data)
- memcpy(&wm8993->pdata, i2c->dev.platform_data,
- sizeof(wm8993->pdata));
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->name = "WM8993";
- codec->volatile_register = wm8993_volatile;
- codec->reg_cache = wm8993->reg_cache;
- codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache);
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8993_set_bias_level;
- codec->dai = &wm8993_dai;
- codec->num_dai = 1;
- snd_soc_codec_set_drvdata(codec, wm8993);
-
- wm8993->hubs_data.hp_startup_mode = 1;
- wm8993->hubs_data.dcs_codes = -2;
-
- memcpy(wm8993->reg_cache, wm8993_reg_defaults,
- sizeof(wm8993->reg_cache));
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
-
i2c_set_clientdata(i2c, wm8993);
- codec->control_data = i2c;
- wm8993_codec = codec;
-
- codec->dev = &i2c->dev;
-
- for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
- wm8993->supplies[i].supply = wm8993_supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
- wm8993->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
- wm8993->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
- }
-
- val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
- if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
- dev_err(codec->dev, "Invalid ID register value %x\n", val);
- ret = -EINVAL;
- goto err_enable;
- }
-
- ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
- if (ret != 0)
- goto err_enable;
-
- codec->cache_only = 1;
-
- /* By default we're using the output mixers */
- wm8993->class_w_users = 2;
-
- /* Latch volume update bits and default ZC on */
- snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
- WM8993_DAC_VU, WM8993_DAC_VU);
- snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
- WM8993_ADC_VU, WM8993_ADC_VU);
- /* Manualy manage the HPOUT sequencing for independent stereo
- * control. */
- snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
- WM8993_HPOUT1_AUTO_PU, 0);
-
- /* Use automatic clock configuration */
- snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
-
- wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
- wm8993->pdata.lineout2_diff,
- wm8993->pdata.lineout1fb,
- wm8993->pdata.lineout2fb,
- wm8993->pdata.jd_scthr,
- wm8993->pdata.jd_thr,
- wm8993->pdata.micbias1_lvl,
- wm8993->pdata.micbias2_lvl);
-
- ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- if (ret != 0)
- goto err_enable;
-
- wm8993_dai.dev = codec->dev;
-
- ret = snd_soc_register_dai(&wm8993_dai);
- if (ret != 0)
- goto err_bias;
-
- ret = snd_soc_register_codec(codec);
-
- return 0;
-
-err_bias:
- wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
-err_enable:
- regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err:
- wm8993_codec = NULL;
- kfree(wm8993);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8993, &wm8993_dai, 1);
+ if (ret < 0)
+ kfree(wm8993);
return ret;
}
-static int wm8993_i2c_remove(struct i2c_client *client)
+static __devexit int wm8993_i2c_remove(struct i2c_client *client)
{
- struct wm8993_priv *wm8993 = i2c_get_clientdata(client);
-
- snd_soc_unregister_codec(&wm8993->codec);
- snd_soc_unregister_dai(&wm8993_dai);
-
- wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF);
- regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
- kfree(wm8993);
-
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1695,30 +1627,34 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
static struct i2c_driver wm8993_i2c_driver = {
.driver = {
- .name = "WM8993",
+ .name = "wm8993-codec",
.owner = THIS_MODULE,
},
- .probe = wm8993_i2c_probe,
- .remove = wm8993_i2c_remove,
+ .probe = wm8993_i2c_probe,
+ .remove = __devexit_p(wm8993_i2c_remove),
.id_table = wm8993_i2c_id,
};
-
+#endif
static int __init wm8993_modinit(void)
{
- int ret;
-
+ int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8993_i2c_driver);
- if (ret != 0)
- pr_err("WM8993: Unable to register I2C driver: %d\n", ret);
-
+ if (ret != 0) {
+ pr_err("WM8993: Unable to register I2C driver: %d\n",
+ ret);
+ }
+#endif
return ret;
}
module_init(wm8993_modinit);
static void __exit wm8993_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8993_i2c_driver);
+#endif
}
module_exit(wm8993_exit);
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
index 30e71ca88dad..2184617b9611 100644
--- a/sound/soc/codecs/wm8993.h
+++ b/sound/soc/codecs/wm8993.h
@@ -1,9 +1,6 @@
#ifndef WM8993_H
#define WM8993_H
-extern struct snd_soc_dai wm8993_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8993;
-
#define WM8993_SYSCLK_MCLK 1
#define WM8993_SYSCLK_FLL 2
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 522249d5c2b4..4d3e6f1ac584 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -36,9 +36,6 @@
#include "wm8994.h"
#include "wm_hubs.h"
-static struct snd_soc_codec *wm8994_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8994;
-
struct fll_config {
int src;
int in;
@@ -71,7 +68,9 @@ struct wm8994_micdet {
/* codec private data */
struct wm8994_priv {
struct wm_hubs_data hubs;
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
+ struct snd_soc_codec *codec;
u16 reg_cache[WM8994_REG_CACHE_SIZE + 1];
int sysclk[2];
int sysclk_rate[2];
@@ -99,1581 +98,1580 @@ struct wm8994_priv {
struct wm8994_pdata *pdata;
};
-static struct {
- unsigned short readable; /* Mask of readable bits */
- unsigned short writable; /* Mask of writable bits */
- unsigned short vol; /* Mask of volatile bits */
+static const struct {
+ unsigned short readable; /* Mask of readable bits */
+ unsigned short writable; /* Mask of writable bits */
} access_masks[] = {
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R0 - Software Reset */
- { 0x3B37, 0x3B37, 0x0000 }, /* R1 - Power Management (1) */
- { 0x6BF0, 0x6BF0, 0x0000 }, /* R2 - Power Management (2) */
- { 0x3FF0, 0x3FF0, 0x0000 }, /* R3 - Power Management (3) */
- { 0x3F3F, 0x3F3F, 0x0000 }, /* R4 - Power Management (4) */
- { 0x3F0F, 0x3F0F, 0x0000 }, /* R5 - Power Management (5) */
- { 0x003F, 0x003F, 0x0000 }, /* R6 - Power Management (6) */
- { 0x0000, 0x0000, 0x0000 }, /* R7 */
- { 0x0000, 0x0000, 0x0000 }, /* R8 */
- { 0x0000, 0x0000, 0x0000 }, /* R9 */
- { 0x0000, 0x0000, 0x0000 }, /* R10 */
- { 0x0000, 0x0000, 0x0000 }, /* R11 */
- { 0x0000, 0x0000, 0x0000 }, /* R12 */
- { 0x0000, 0x0000, 0x0000 }, /* R13 */
- { 0x0000, 0x0000, 0x0000 }, /* R14 */
- { 0x0000, 0x0000, 0x0000 }, /* R15 */
- { 0x0000, 0x0000, 0x0000 }, /* R16 */
- { 0x0000, 0x0000, 0x0000 }, /* R17 */
- { 0x0000, 0x0000, 0x0000 }, /* R18 */
- { 0x0000, 0x0000, 0x0000 }, /* R19 */
- { 0x0000, 0x0000, 0x0000 }, /* R20 */
- { 0x01C0, 0x01C0, 0x0000 }, /* R21 - Input Mixer (1) */
- { 0x0000, 0x0000, 0x0000 }, /* R22 */
- { 0x0000, 0x0000, 0x0000 }, /* R23 */
- { 0x00DF, 0x01DF, 0x0000 }, /* R24 - Left Line Input 1&2 Volume */
- { 0x00DF, 0x01DF, 0x0000 }, /* R25 - Left Line Input 3&4 Volume */
- { 0x00DF, 0x01DF, 0x0000 }, /* R26 - Right Line Input 1&2 Volume */
- { 0x00DF, 0x01DF, 0x0000 }, /* R27 - Right Line Input 3&4 Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R28 - Left Output Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R29 - Right Output Volume */
- { 0x0077, 0x0077, 0x0000 }, /* R30 - Line Outputs Volume */
- { 0x0030, 0x0030, 0x0000 }, /* R31 - HPOUT2 Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R32 - Left OPGA Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R33 - Right OPGA Volume */
- { 0x007F, 0x007F, 0x0000 }, /* R34 - SPKMIXL Attenuation */
- { 0x017F, 0x017F, 0x0000 }, /* R35 - SPKMIXR Attenuation */
- { 0x003F, 0x003F, 0x0000 }, /* R36 - SPKOUT Mixers */
- { 0x003F, 0x003F, 0x0000 }, /* R37 - ClassD */
- { 0x00FF, 0x01FF, 0x0000 }, /* R38 - Speaker Volume Left */
- { 0x00FF, 0x01FF, 0x0000 }, /* R39 - Speaker Volume Right */
- { 0x00FF, 0x00FF, 0x0000 }, /* R40 - Input Mixer (2) */
- { 0x01B7, 0x01B7, 0x0000 }, /* R41 - Input Mixer (3) */
- { 0x01B7, 0x01B7, 0x0000 }, /* R42 - Input Mixer (4) */
- { 0x01C7, 0x01C7, 0x0000 }, /* R43 - Input Mixer (5) */
- { 0x01C7, 0x01C7, 0x0000 }, /* R44 - Input Mixer (6) */
- { 0x01FF, 0x01FF, 0x0000 }, /* R45 - Output Mixer (1) */
- { 0x01FF, 0x01FF, 0x0000 }, /* R46 - Output Mixer (2) */
- { 0x0FFF, 0x0FFF, 0x0000 }, /* R47 - Output Mixer (3) */
- { 0x0FFF, 0x0FFF, 0x0000 }, /* R48 - Output Mixer (4) */
- { 0x0FFF, 0x0FFF, 0x0000 }, /* R49 - Output Mixer (5) */
- { 0x0FFF, 0x0FFF, 0x0000 }, /* R50 - Output Mixer (6) */
- { 0x0038, 0x0038, 0x0000 }, /* R51 - HPOUT2 Mixer */
- { 0x0077, 0x0077, 0x0000 }, /* R52 - Line Mixer (1) */
- { 0x0077, 0x0077, 0x0000 }, /* R53 - Line Mixer (2) */
- { 0x03FF, 0x03FF, 0x0000 }, /* R54 - Speaker Mixer */
- { 0x00C1, 0x00C1, 0x0000 }, /* R55 - Additional Control */
- { 0x00F0, 0x00F0, 0x0000 }, /* R56 - AntiPOP (1) */
- { 0x01EF, 0x01EF, 0x0000 }, /* R57 - AntiPOP (2) */
- { 0x00FF, 0x00FF, 0x0000 }, /* R58 - MICBIAS */
- { 0x000F, 0x000F, 0x0000 }, /* R59 - LDO 1 */
- { 0x0007, 0x0007, 0x0000 }, /* R60 - LDO 2 */
- { 0x0000, 0x0000, 0x0000 }, /* R61 */
- { 0x0000, 0x0000, 0x0000 }, /* R62 */
- { 0x0000, 0x0000, 0x0000 }, /* R63 */
- { 0x0000, 0x0000, 0x0000 }, /* R64 */
- { 0x0000, 0x0000, 0x0000 }, /* R65 */
- { 0x0000, 0x0000, 0x0000 }, /* R66 */
- { 0x0000, 0x0000, 0x0000 }, /* R67 */
- { 0x0000, 0x0000, 0x0000 }, /* R68 */
- { 0x0000, 0x0000, 0x0000 }, /* R69 */
- { 0x0000, 0x0000, 0x0000 }, /* R70 */
- { 0x0000, 0x0000, 0x0000 }, /* R71 */
- { 0x0000, 0x0000, 0x0000 }, /* R72 */
- { 0x0000, 0x0000, 0x0000 }, /* R73 */
- { 0x0000, 0x0000, 0x0000 }, /* R74 */
- { 0x0000, 0x0000, 0x0000 }, /* R75 */
- { 0x8000, 0x8000, 0x0000 }, /* R76 - Charge Pump (1) */
- { 0x0000, 0x0000, 0x0000 }, /* R77 */
- { 0x0000, 0x0000, 0x0000 }, /* R78 */
- { 0x0000, 0x0000, 0x0000 }, /* R79 */
- { 0x0000, 0x0000, 0x0000 }, /* R80 */
- { 0x0301, 0x0301, 0x0000 }, /* R81 - Class W (1) */
- { 0x0000, 0x0000, 0x0000 }, /* R82 */
- { 0x0000, 0x0000, 0x0000 }, /* R83 */
- { 0x333F, 0x333F, 0x0000 }, /* R84 - DC Servo (1) */
- { 0x0FEF, 0x0FEF, 0x0000 }, /* R85 - DC Servo (2) */
- { 0x0000, 0x0000, 0x0000 }, /* R86 */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R87 - DC Servo (4) */
- { 0x0333, 0x0000, 0x0000 }, /* R88 - DC Servo Readback */
- { 0x0000, 0x0000, 0x0000 }, /* R89 */
- { 0x0000, 0x0000, 0x0000 }, /* R90 */
- { 0x0000, 0x0000, 0x0000 }, /* R91 */
- { 0x0000, 0x0000, 0x0000 }, /* R92 */
- { 0x0000, 0x0000, 0x0000 }, /* R93 */
- { 0x0000, 0x0000, 0x0000 }, /* R94 */
- { 0x0000, 0x0000, 0x0000 }, /* R95 */
- { 0x00EE, 0x00EE, 0x0000 }, /* R96 - Analogue HP (1) */
- { 0x0000, 0x0000, 0x0000 }, /* R97 */
- { 0x0000, 0x0000, 0x0000 }, /* R98 */
- { 0x0000, 0x0000, 0x0000 }, /* R99 */
- { 0x0000, 0x0000, 0x0000 }, /* R100 */
- { 0x0000, 0x0000, 0x0000 }, /* R101 */
- { 0x0000, 0x0000, 0x0000 }, /* R102 */
- { 0x0000, 0x0000, 0x0000 }, /* R103 */
- { 0x0000, 0x0000, 0x0000 }, /* R104 */
- { 0x0000, 0x0000, 0x0000 }, /* R105 */
- { 0x0000, 0x0000, 0x0000 }, /* R106 */
- { 0x0000, 0x0000, 0x0000 }, /* R107 */
- { 0x0000, 0x0000, 0x0000 }, /* R108 */
- { 0x0000, 0x0000, 0x0000 }, /* R109 */
- { 0x0000, 0x0000, 0x0000 }, /* R110 */
- { 0x0000, 0x0000, 0x0000 }, /* R111 */
- { 0x0000, 0x0000, 0x0000 }, /* R112 */
- { 0x0000, 0x0000, 0x0000 }, /* R113 */
- { 0x0000, 0x0000, 0x0000 }, /* R114 */
- { 0x0000, 0x0000, 0x0000 }, /* R115 */
- { 0x0000, 0x0000, 0x0000 }, /* R116 */
- { 0x0000, 0x0000, 0x0000 }, /* R117 */
- { 0x0000, 0x0000, 0x0000 }, /* R118 */
- { 0x0000, 0x0000, 0x0000 }, /* R119 */
- { 0x0000, 0x0000, 0x0000 }, /* R120 */
- { 0x0000, 0x0000, 0x0000 }, /* R121 */
- { 0x0000, 0x0000, 0x0000 }, /* R122 */
- { 0x0000, 0x0000, 0x0000 }, /* R123 */
- { 0x0000, 0x0000, 0x0000 }, /* R124 */
- { 0x0000, 0x0000, 0x0000 }, /* R125 */
- { 0x0000, 0x0000, 0x0000 }, /* R126 */
- { 0x0000, 0x0000, 0x0000 }, /* R127 */
- { 0x0000, 0x0000, 0x0000 }, /* R128 */
- { 0x0000, 0x0000, 0x0000 }, /* R129 */
- { 0x0000, 0x0000, 0x0000 }, /* R130 */
- { 0x0000, 0x0000, 0x0000 }, /* R131 */
- { 0x0000, 0x0000, 0x0000 }, /* R132 */
- { 0x0000, 0x0000, 0x0000 }, /* R133 */
- { 0x0000, 0x0000, 0x0000 }, /* R134 */
- { 0x0000, 0x0000, 0x0000 }, /* R135 */
- { 0x0000, 0x0000, 0x0000 }, /* R136 */
- { 0x0000, 0x0000, 0x0000 }, /* R137 */
- { 0x0000, 0x0000, 0x0000 }, /* R138 */
- { 0x0000, 0x0000, 0x0000 }, /* R139 */
- { 0x0000, 0x0000, 0x0000 }, /* R140 */
- { 0x0000, 0x0000, 0x0000 }, /* R141 */
- { 0x0000, 0x0000, 0x0000 }, /* R142 */
- { 0x0000, 0x0000, 0x0000 }, /* R143 */
- { 0x0000, 0x0000, 0x0000 }, /* R144 */
- { 0x0000, 0x0000, 0x0000 }, /* R145 */
- { 0x0000, 0x0000, 0x0000 }, /* R146 */
- { 0x0000, 0x0000, 0x0000 }, /* R147 */
- { 0x0000, 0x0000, 0x0000 }, /* R148 */
- { 0x0000, 0x0000, 0x0000 }, /* R149 */
- { 0x0000, 0x0000, 0x0000 }, /* R150 */
- { 0x0000, 0x0000, 0x0000 }, /* R151 */
- { 0x0000, 0x0000, 0x0000 }, /* R152 */
- { 0x0000, 0x0000, 0x0000 }, /* R153 */
- { 0x0000, 0x0000, 0x0000 }, /* R154 */
- { 0x0000, 0x0000, 0x0000 }, /* R155 */
- { 0x0000, 0x0000, 0x0000 }, /* R156 */
- { 0x0000, 0x0000, 0x0000 }, /* R157 */
- { 0x0000, 0x0000, 0x0000 }, /* R158 */
- { 0x0000, 0x0000, 0x0000 }, /* R159 */
- { 0x0000, 0x0000, 0x0000 }, /* R160 */
- { 0x0000, 0x0000, 0x0000 }, /* R161 */
- { 0x0000, 0x0000, 0x0000 }, /* R162 */
- { 0x0000, 0x0000, 0x0000 }, /* R163 */
- { 0x0000, 0x0000, 0x0000 }, /* R164 */
- { 0x0000, 0x0000, 0x0000 }, /* R165 */
- { 0x0000, 0x0000, 0x0000 }, /* R166 */
- { 0x0000, 0x0000, 0x0000 }, /* R167 */
- { 0x0000, 0x0000, 0x0000 }, /* R168 */
- { 0x0000, 0x0000, 0x0000 }, /* R169 */
- { 0x0000, 0x0000, 0x0000 }, /* R170 */
- { 0x0000, 0x0000, 0x0000 }, /* R171 */
- { 0x0000, 0x0000, 0x0000 }, /* R172 */
- { 0x0000, 0x0000, 0x0000 }, /* R173 */
- { 0x0000, 0x0000, 0x0000 }, /* R174 */
- { 0x0000, 0x0000, 0x0000 }, /* R175 */
- { 0x0000, 0x0000, 0x0000 }, /* R176 */
- { 0x0000, 0x0000, 0x0000 }, /* R177 */
- { 0x0000, 0x0000, 0x0000 }, /* R178 */
- { 0x0000, 0x0000, 0x0000 }, /* R179 */
- { 0x0000, 0x0000, 0x0000 }, /* R180 */
- { 0x0000, 0x0000, 0x0000 }, /* R181 */
- { 0x0000, 0x0000, 0x0000 }, /* R182 */
- { 0x0000, 0x0000, 0x0000 }, /* R183 */
- { 0x0000, 0x0000, 0x0000 }, /* R184 */
- { 0x0000, 0x0000, 0x0000 }, /* R185 */
- { 0x0000, 0x0000, 0x0000 }, /* R186 */
- { 0x0000, 0x0000, 0x0000 }, /* R187 */
- { 0x0000, 0x0000, 0x0000 }, /* R188 */
- { 0x0000, 0x0000, 0x0000 }, /* R189 */
- { 0x0000, 0x0000, 0x0000 }, /* R190 */
- { 0x0000, 0x0000, 0x0000 }, /* R191 */
- { 0x0000, 0x0000, 0x0000 }, /* R192 */
- { 0x0000, 0x0000, 0x0000 }, /* R193 */
- { 0x0000, 0x0000, 0x0000 }, /* R194 */
- { 0x0000, 0x0000, 0x0000 }, /* R195 */
- { 0x0000, 0x0000, 0x0000 }, /* R196 */
- { 0x0000, 0x0000, 0x0000 }, /* R197 */
- { 0x0000, 0x0000, 0x0000 }, /* R198 */
- { 0x0000, 0x0000, 0x0000 }, /* R199 */
- { 0x0000, 0x0000, 0x0000 }, /* R200 */
- { 0x0000, 0x0000, 0x0000 }, /* R201 */
- { 0x0000, 0x0000, 0x0000 }, /* R202 */
- { 0x0000, 0x0000, 0x0000 }, /* R203 */
- { 0x0000, 0x0000, 0x0000 }, /* R204 */
- { 0x0000, 0x0000, 0x0000 }, /* R205 */
- { 0x0000, 0x0000, 0x0000 }, /* R206 */
- { 0x0000, 0x0000, 0x0000 }, /* R207 */
- { 0x0000, 0x0000, 0x0000 }, /* R208 */
- { 0x0000, 0x0000, 0x0000 }, /* R209 */
- { 0x0000, 0x0000, 0x0000 }, /* R210 */
- { 0x0000, 0x0000, 0x0000 }, /* R211 */
- { 0x0000, 0x0000, 0x0000 }, /* R212 */
- { 0x0000, 0x0000, 0x0000 }, /* R213 */
- { 0x0000, 0x0000, 0x0000 }, /* R214 */
- { 0x0000, 0x0000, 0x0000 }, /* R215 */
- { 0x0000, 0x0000, 0x0000 }, /* R216 */
- { 0x0000, 0x0000, 0x0000 }, /* R217 */
- { 0x0000, 0x0000, 0x0000 }, /* R218 */
- { 0x0000, 0x0000, 0x0000 }, /* R219 */
- { 0x0000, 0x0000, 0x0000 }, /* R220 */
- { 0x0000, 0x0000, 0x0000 }, /* R221 */
- { 0x0000, 0x0000, 0x0000 }, /* R222 */
- { 0x0000, 0x0000, 0x0000 }, /* R223 */
- { 0x0000, 0x0000, 0x0000 }, /* R224 */
- { 0x0000, 0x0000, 0x0000 }, /* R225 */
- { 0x0000, 0x0000, 0x0000 }, /* R226 */
- { 0x0000, 0x0000, 0x0000 }, /* R227 */
- { 0x0000, 0x0000, 0x0000 }, /* R228 */
- { 0x0000, 0x0000, 0x0000 }, /* R229 */
- { 0x0000, 0x0000, 0x0000 }, /* R230 */
- { 0x0000, 0x0000, 0x0000 }, /* R231 */
- { 0x0000, 0x0000, 0x0000 }, /* R232 */
- { 0x0000, 0x0000, 0x0000 }, /* R233 */
- { 0x0000, 0x0000, 0x0000 }, /* R234 */
- { 0x0000, 0x0000, 0x0000 }, /* R235 */
- { 0x0000, 0x0000, 0x0000 }, /* R236 */
- { 0x0000, 0x0000, 0x0000 }, /* R237 */
- { 0x0000, 0x0000, 0x0000 }, /* R238 */
- { 0x0000, 0x0000, 0x0000 }, /* R239 */
- { 0x0000, 0x0000, 0x0000 }, /* R240 */
- { 0x0000, 0x0000, 0x0000 }, /* R241 */
- { 0x0000, 0x0000, 0x0000 }, /* R242 */
- { 0x0000, 0x0000, 0x0000 }, /* R243 */
- { 0x0000, 0x0000, 0x0000 }, /* R244 */
- { 0x0000, 0x0000, 0x0000 }, /* R245 */
- { 0x0000, 0x0000, 0x0000 }, /* R246 */
- { 0x0000, 0x0000, 0x0000 }, /* R247 */
- { 0x0000, 0x0000, 0x0000 }, /* R248 */
- { 0x0000, 0x0000, 0x0000 }, /* R249 */
- { 0x0000, 0x0000, 0x0000 }, /* R250 */
- { 0x0000, 0x0000, 0x0000 }, /* R251 */
- { 0x0000, 0x0000, 0x0000 }, /* R252 */
- { 0x0000, 0x0000, 0x0000 }, /* R253 */
- { 0x0000, 0x0000, 0x0000 }, /* R254 */
- { 0x0000, 0x0000, 0x0000 }, /* R255 */
- { 0x000F, 0x0000, 0x0000 }, /* R256 - Chip Revision */
- { 0x0074, 0x0074, 0x0000 }, /* R257 - Control Interface */
- { 0x0000, 0x0000, 0x0000 }, /* R258 */
- { 0x0000, 0x0000, 0x0000 }, /* R259 */
- { 0x0000, 0x0000, 0x0000 }, /* R260 */
- { 0x0000, 0x0000, 0x0000 }, /* R261 */
- { 0x0000, 0x0000, 0x0000 }, /* R262 */
- { 0x0000, 0x0000, 0x0000 }, /* R263 */
- { 0x0000, 0x0000, 0x0000 }, /* R264 */
- { 0x0000, 0x0000, 0x0000 }, /* R265 */
- { 0x0000, 0x0000, 0x0000 }, /* R266 */
- { 0x0000, 0x0000, 0x0000 }, /* R267 */
- { 0x0000, 0x0000, 0x0000 }, /* R268 */
- { 0x0000, 0x0000, 0x0000 }, /* R269 */
- { 0x0000, 0x0000, 0x0000 }, /* R270 */
- { 0x0000, 0x0000, 0x0000 }, /* R271 */
- { 0x807F, 0x837F, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */
- { 0x017F, 0x0000, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
- { 0x0000, 0x0000, 0x0000 }, /* R274 */
- { 0x0000, 0x0000, 0x0000 }, /* R275 */
- { 0x0000, 0x0000, 0x0000 }, /* R276 */
- { 0x0000, 0x0000, 0x0000 }, /* R277 */
- { 0x0000, 0x0000, 0x0000 }, /* R278 */
- { 0x0000, 0x0000, 0x0000 }, /* R279 */
- { 0x0000, 0x0000, 0x0000 }, /* R280 */
- { 0x0000, 0x0000, 0x0000 }, /* R281 */
- { 0x0000, 0x0000, 0x0000 }, /* R282 */
- { 0x0000, 0x0000, 0x0000 }, /* R283 */
- { 0x0000, 0x0000, 0x0000 }, /* R284 */
- { 0x0000, 0x0000, 0x0000 }, /* R285 */
- { 0x0000, 0x0000, 0x0000 }, /* R286 */
- { 0x0000, 0x0000, 0x0000 }, /* R287 */
- { 0x0000, 0x0000, 0x0000 }, /* R288 */
- { 0x0000, 0x0000, 0x0000 }, /* R289 */
- { 0x0000, 0x0000, 0x0000 }, /* R290 */
- { 0x0000, 0x0000, 0x0000 }, /* R291 */
- { 0x0000, 0x0000, 0x0000 }, /* R292 */
- { 0x0000, 0x0000, 0x0000 }, /* R293 */
- { 0x0000, 0x0000, 0x0000 }, /* R294 */
- { 0x0000, 0x0000, 0x0000 }, /* R295 */
- { 0x0000, 0x0000, 0x0000 }, /* R296 */
- { 0x0000, 0x0000, 0x0000 }, /* R297 */
- { 0x0000, 0x0000, 0x0000 }, /* R298 */
- { 0x0000, 0x0000, 0x0000 }, /* R299 */
- { 0x0000, 0x0000, 0x0000 }, /* R300 */
- { 0x0000, 0x0000, 0x0000 }, /* R301 */
- { 0x0000, 0x0000, 0x0000 }, /* R302 */
- { 0x0000, 0x0000, 0x0000 }, /* R303 */
- { 0x0000, 0x0000, 0x0000 }, /* R304 */
- { 0x0000, 0x0000, 0x0000 }, /* R305 */
- { 0x0000, 0x0000, 0x0000 }, /* R306 */
- { 0x0000, 0x0000, 0x0000 }, /* R307 */
- { 0x0000, 0x0000, 0x0000 }, /* R308 */
- { 0x0000, 0x0000, 0x0000 }, /* R309 */
- { 0x0000, 0x0000, 0x0000 }, /* R310 */
- { 0x0000, 0x0000, 0x0000 }, /* R311 */
- { 0x0000, 0x0000, 0x0000 }, /* R312 */
- { 0x0000, 0x0000, 0x0000 }, /* R313 */
- { 0x0000, 0x0000, 0x0000 }, /* R314 */
- { 0x0000, 0x0000, 0x0000 }, /* R315 */
- { 0x0000, 0x0000, 0x0000 }, /* R316 */
- { 0x0000, 0x0000, 0x0000 }, /* R317 */
- { 0x0000, 0x0000, 0x0000 }, /* R318 */
- { 0x0000, 0x0000, 0x0000 }, /* R319 */
- { 0x0000, 0x0000, 0x0000 }, /* R320 */
- { 0x0000, 0x0000, 0x0000 }, /* R321 */
- { 0x0000, 0x0000, 0x0000 }, /* R322 */
- { 0x0000, 0x0000, 0x0000 }, /* R323 */
- { 0x0000, 0x0000, 0x0000 }, /* R324 */
- { 0x0000, 0x0000, 0x0000 }, /* R325 */
- { 0x0000, 0x0000, 0x0000 }, /* R326 */
- { 0x0000, 0x0000, 0x0000 }, /* R327 */
- { 0x0000, 0x0000, 0x0000 }, /* R328 */
- { 0x0000, 0x0000, 0x0000 }, /* R329 */
- { 0x0000, 0x0000, 0x0000 }, /* R330 */
- { 0x0000, 0x0000, 0x0000 }, /* R331 */
- { 0x0000, 0x0000, 0x0000 }, /* R332 */
- { 0x0000, 0x0000, 0x0000 }, /* R333 */
- { 0x0000, 0x0000, 0x0000 }, /* R334 */
- { 0x0000, 0x0000, 0x0000 }, /* R335 */
- { 0x0000, 0x0000, 0x0000 }, /* R336 */
- { 0x0000, 0x0000, 0x0000 }, /* R337 */
- { 0x0000, 0x0000, 0x0000 }, /* R338 */
- { 0x0000, 0x0000, 0x0000 }, /* R339 */
- { 0x0000, 0x0000, 0x0000 }, /* R340 */
- { 0x0000, 0x0000, 0x0000 }, /* R341 */
- { 0x0000, 0x0000, 0x0000 }, /* R342 */
- { 0x0000, 0x0000, 0x0000 }, /* R343 */
- { 0x0000, 0x0000, 0x0000 }, /* R344 */
- { 0x0000, 0x0000, 0x0000 }, /* R345 */
- { 0x0000, 0x0000, 0x0000 }, /* R346 */
- { 0x0000, 0x0000, 0x0000 }, /* R347 */
- { 0x0000, 0x0000, 0x0000 }, /* R348 */
- { 0x0000, 0x0000, 0x0000 }, /* R349 */
- { 0x0000, 0x0000, 0x0000 }, /* R350 */
- { 0x0000, 0x0000, 0x0000 }, /* R351 */
- { 0x0000, 0x0000, 0x0000 }, /* R352 */
- { 0x0000, 0x0000, 0x0000 }, /* R353 */
- { 0x0000, 0x0000, 0x0000 }, /* R354 */
- { 0x0000, 0x0000, 0x0000 }, /* R355 */
- { 0x0000, 0x0000, 0x0000 }, /* R356 */
- { 0x0000, 0x0000, 0x0000 }, /* R357 */
- { 0x0000, 0x0000, 0x0000 }, /* R358 */
- { 0x0000, 0x0000, 0x0000 }, /* R359 */
- { 0x0000, 0x0000, 0x0000 }, /* R360 */
- { 0x0000, 0x0000, 0x0000 }, /* R361 */
- { 0x0000, 0x0000, 0x0000 }, /* R362 */
- { 0x0000, 0x0000, 0x0000 }, /* R363 */
- { 0x0000, 0x0000, 0x0000 }, /* R364 */
- { 0x0000, 0x0000, 0x0000 }, /* R365 */
- { 0x0000, 0x0000, 0x0000 }, /* R366 */
- { 0x0000, 0x0000, 0x0000 }, /* R367 */
- { 0x0000, 0x0000, 0x0000 }, /* R368 */
- { 0x0000, 0x0000, 0x0000 }, /* R369 */
- { 0x0000, 0x0000, 0x0000 }, /* R370 */
- { 0x0000, 0x0000, 0x0000 }, /* R371 */
- { 0x0000, 0x0000, 0x0000 }, /* R372 */
- { 0x0000, 0x0000, 0x0000 }, /* R373 */
- { 0x0000, 0x0000, 0x0000 }, /* R374 */
- { 0x0000, 0x0000, 0x0000 }, /* R375 */
- { 0x0000, 0x0000, 0x0000 }, /* R376 */
- { 0x0000, 0x0000, 0x0000 }, /* R377 */
- { 0x0000, 0x0000, 0x0000 }, /* R378 */
- { 0x0000, 0x0000, 0x0000 }, /* R379 */
- { 0x0000, 0x0000, 0x0000 }, /* R380 */
- { 0x0000, 0x0000, 0x0000 }, /* R381 */
- { 0x0000, 0x0000, 0x0000 }, /* R382 */
- { 0x0000, 0x0000, 0x0000 }, /* R383 */
- { 0x0000, 0x0000, 0x0000 }, /* R384 */
- { 0x0000, 0x0000, 0x0000 }, /* R385 */
- { 0x0000, 0x0000, 0x0000 }, /* R386 */
- { 0x0000, 0x0000, 0x0000 }, /* R387 */
- { 0x0000, 0x0000, 0x0000 }, /* R388 */
- { 0x0000, 0x0000, 0x0000 }, /* R389 */
- { 0x0000, 0x0000, 0x0000 }, /* R390 */
- { 0x0000, 0x0000, 0x0000 }, /* R391 */
- { 0x0000, 0x0000, 0x0000 }, /* R392 */
- { 0x0000, 0x0000, 0x0000 }, /* R393 */
- { 0x0000, 0x0000, 0x0000 }, /* R394 */
- { 0x0000, 0x0000, 0x0000 }, /* R395 */
- { 0x0000, 0x0000, 0x0000 }, /* R396 */
- { 0x0000, 0x0000, 0x0000 }, /* R397 */
- { 0x0000, 0x0000, 0x0000 }, /* R398 */
- { 0x0000, 0x0000, 0x0000 }, /* R399 */
- { 0x0000, 0x0000, 0x0000 }, /* R400 */
- { 0x0000, 0x0000, 0x0000 }, /* R401 */
- { 0x0000, 0x0000, 0x0000 }, /* R402 */
- { 0x0000, 0x0000, 0x0000 }, /* R403 */
- { 0x0000, 0x0000, 0x0000 }, /* R404 */
- { 0x0000, 0x0000, 0x0000 }, /* R405 */
- { 0x0000, 0x0000, 0x0000 }, /* R406 */
- { 0x0000, 0x0000, 0x0000 }, /* R407 */
- { 0x0000, 0x0000, 0x0000 }, /* R408 */
- { 0x0000, 0x0000, 0x0000 }, /* R409 */
- { 0x0000, 0x0000, 0x0000 }, /* R410 */
- { 0x0000, 0x0000, 0x0000 }, /* R411 */
- { 0x0000, 0x0000, 0x0000 }, /* R412 */
- { 0x0000, 0x0000, 0x0000 }, /* R413 */
- { 0x0000, 0x0000, 0x0000 }, /* R414 */
- { 0x0000, 0x0000, 0x0000 }, /* R415 */
- { 0x0000, 0x0000, 0x0000 }, /* R416 */
- { 0x0000, 0x0000, 0x0000 }, /* R417 */
- { 0x0000, 0x0000, 0x0000 }, /* R418 */
- { 0x0000, 0x0000, 0x0000 }, /* R419 */
- { 0x0000, 0x0000, 0x0000 }, /* R420 */
- { 0x0000, 0x0000, 0x0000 }, /* R421 */
- { 0x0000, 0x0000, 0x0000 }, /* R422 */
- { 0x0000, 0x0000, 0x0000 }, /* R423 */
- { 0x0000, 0x0000, 0x0000 }, /* R424 */
- { 0x0000, 0x0000, 0x0000 }, /* R425 */
- { 0x0000, 0x0000, 0x0000 }, /* R426 */
- { 0x0000, 0x0000, 0x0000 }, /* R427 */
- { 0x0000, 0x0000, 0x0000 }, /* R428 */
- { 0x0000, 0x0000, 0x0000 }, /* R429 */
- { 0x0000, 0x0000, 0x0000 }, /* R430 */
- { 0x0000, 0x0000, 0x0000 }, /* R431 */
- { 0x0000, 0x0000, 0x0000 }, /* R432 */
- { 0x0000, 0x0000, 0x0000 }, /* R433 */
- { 0x0000, 0x0000, 0x0000 }, /* R434 */
- { 0x0000, 0x0000, 0x0000 }, /* R435 */
- { 0x0000, 0x0000, 0x0000 }, /* R436 */
- { 0x0000, 0x0000, 0x0000 }, /* R437 */
- { 0x0000, 0x0000, 0x0000 }, /* R438 */
- { 0x0000, 0x0000, 0x0000 }, /* R439 */
- { 0x0000, 0x0000, 0x0000 }, /* R440 */
- { 0x0000, 0x0000, 0x0000 }, /* R441 */
- { 0x0000, 0x0000, 0x0000 }, /* R442 */
- { 0x0000, 0x0000, 0x0000 }, /* R443 */
- { 0x0000, 0x0000, 0x0000 }, /* R444 */
- { 0x0000, 0x0000, 0x0000 }, /* R445 */
- { 0x0000, 0x0000, 0x0000 }, /* R446 */
- { 0x0000, 0x0000, 0x0000 }, /* R447 */
- { 0x0000, 0x0000, 0x0000 }, /* R448 */
- { 0x0000, 0x0000, 0x0000 }, /* R449 */
- { 0x0000, 0x0000, 0x0000 }, /* R450 */
- { 0x0000, 0x0000, 0x0000 }, /* R451 */
- { 0x0000, 0x0000, 0x0000 }, /* R452 */
- { 0x0000, 0x0000, 0x0000 }, /* R453 */
- { 0x0000, 0x0000, 0x0000 }, /* R454 */
- { 0x0000, 0x0000, 0x0000 }, /* R455 */
- { 0x0000, 0x0000, 0x0000 }, /* R456 */
- { 0x0000, 0x0000, 0x0000 }, /* R457 */
- { 0x0000, 0x0000, 0x0000 }, /* R458 */
- { 0x0000, 0x0000, 0x0000 }, /* R459 */
- { 0x0000, 0x0000, 0x0000 }, /* R460 */
- { 0x0000, 0x0000, 0x0000 }, /* R461 */
- { 0x0000, 0x0000, 0x0000 }, /* R462 */
- { 0x0000, 0x0000, 0x0000 }, /* R463 */
- { 0x0000, 0x0000, 0x0000 }, /* R464 */
- { 0x0000, 0x0000, 0x0000 }, /* R465 */
- { 0x0000, 0x0000, 0x0000 }, /* R466 */
- { 0x0000, 0x0000, 0x0000 }, /* R467 */
- { 0x0000, 0x0000, 0x0000 }, /* R468 */
- { 0x0000, 0x0000, 0x0000 }, /* R469 */
- { 0x0000, 0x0000, 0x0000 }, /* R470 */
- { 0x0000, 0x0000, 0x0000 }, /* R471 */
- { 0x0000, 0x0000, 0x0000 }, /* R472 */
- { 0x0000, 0x0000, 0x0000 }, /* R473 */
- { 0x0000, 0x0000, 0x0000 }, /* R474 */
- { 0x0000, 0x0000, 0x0000 }, /* R475 */
- { 0x0000, 0x0000, 0x0000 }, /* R476 */
- { 0x0000, 0x0000, 0x0000 }, /* R477 */
- { 0x0000, 0x0000, 0x0000 }, /* R478 */
- { 0x0000, 0x0000, 0x0000 }, /* R479 */
- { 0x0000, 0x0000, 0x0000 }, /* R480 */
- { 0x0000, 0x0000, 0x0000 }, /* R481 */
- { 0x0000, 0x0000, 0x0000 }, /* R482 */
- { 0x0000, 0x0000, 0x0000 }, /* R483 */
- { 0x0000, 0x0000, 0x0000 }, /* R484 */
- { 0x0000, 0x0000, 0x0000 }, /* R485 */
- { 0x0000, 0x0000, 0x0000 }, /* R486 */
- { 0x0000, 0x0000, 0x0000 }, /* R487 */
- { 0x0000, 0x0000, 0x0000 }, /* R488 */
- { 0x0000, 0x0000, 0x0000 }, /* R489 */
- { 0x0000, 0x0000, 0x0000 }, /* R490 */
- { 0x0000, 0x0000, 0x0000 }, /* R491 */
- { 0x0000, 0x0000, 0x0000 }, /* R492 */
- { 0x0000, 0x0000, 0x0000 }, /* R493 */
- { 0x0000, 0x0000, 0x0000 }, /* R494 */
- { 0x0000, 0x0000, 0x0000 }, /* R495 */
- { 0x0000, 0x0000, 0x0000 }, /* R496 */
- { 0x0000, 0x0000, 0x0000 }, /* R497 */
- { 0x0000, 0x0000, 0x0000 }, /* R498 */
- { 0x0000, 0x0000, 0x0000 }, /* R499 */
- { 0x0000, 0x0000, 0x0000 }, /* R500 */
- { 0x0000, 0x0000, 0x0000 }, /* R501 */
- { 0x0000, 0x0000, 0x0000 }, /* R502 */
- { 0x0000, 0x0000, 0x0000 }, /* R503 */
- { 0x0000, 0x0000, 0x0000 }, /* R504 */
- { 0x0000, 0x0000, 0x0000 }, /* R505 */
- { 0x0000, 0x0000, 0x0000 }, /* R506 */
- { 0x0000, 0x0000, 0x0000 }, /* R507 */
- { 0x0000, 0x0000, 0x0000 }, /* R508 */
- { 0x0000, 0x0000, 0x0000 }, /* R509 */
- { 0x0000, 0x0000, 0x0000 }, /* R510 */
- { 0x0000, 0x0000, 0x0000 }, /* R511 */
- { 0x001F, 0x001F, 0x0000 }, /* R512 - AIF1 Clocking (1) */
- { 0x003F, 0x003F, 0x0000 }, /* R513 - AIF1 Clocking (2) */
- { 0x0000, 0x0000, 0x0000 }, /* R514 */
- { 0x0000, 0x0000, 0x0000 }, /* R515 */
- { 0x001F, 0x001F, 0x0000 }, /* R516 - AIF2 Clocking (1) */
- { 0x003F, 0x003F, 0x0000 }, /* R517 - AIF2 Clocking (2) */
- { 0x0000, 0x0000, 0x0000 }, /* R518 */
- { 0x0000, 0x0000, 0x0000 }, /* R519 */
- { 0x001F, 0x001F, 0x0000 }, /* R520 - Clocking (1) */
- { 0x0777, 0x0777, 0x0000 }, /* R521 - Clocking (2) */
- { 0x0000, 0x0000, 0x0000 }, /* R522 */
- { 0x0000, 0x0000, 0x0000 }, /* R523 */
- { 0x0000, 0x0000, 0x0000 }, /* R524 */
- { 0x0000, 0x0000, 0x0000 }, /* R525 */
- { 0x0000, 0x0000, 0x0000 }, /* R526 */
- { 0x0000, 0x0000, 0x0000 }, /* R527 */
- { 0x00FF, 0x00FF, 0x0000 }, /* R528 - AIF1 Rate */
- { 0x00FF, 0x00FF, 0x0000 }, /* R529 - AIF2 Rate */
- { 0x000F, 0x0000, 0x0000 }, /* R530 - Rate Status */
- { 0x0000, 0x0000, 0x0000 }, /* R531 */
- { 0x0000, 0x0000, 0x0000 }, /* R532 */
- { 0x0000, 0x0000, 0x0000 }, /* R533 */
- { 0x0000, 0x0000, 0x0000 }, /* R534 */
- { 0x0000, 0x0000, 0x0000 }, /* R535 */
- { 0x0000, 0x0000, 0x0000 }, /* R536 */
- { 0x0000, 0x0000, 0x0000 }, /* R537 */
- { 0x0000, 0x0000, 0x0000 }, /* R538 */
- { 0x0000, 0x0000, 0x0000 }, /* R539 */
- { 0x0000, 0x0000, 0x0000 }, /* R540 */
- { 0x0000, 0x0000, 0x0000 }, /* R541 */
- { 0x0000, 0x0000, 0x0000 }, /* R542 */
- { 0x0000, 0x0000, 0x0000 }, /* R543 */
- { 0x0007, 0x0007, 0x0000 }, /* R544 - FLL1 Control (1) */
- { 0x3F77, 0x3F77, 0x0000 }, /* R545 - FLL1 Control (2) */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R546 - FLL1 Control (3) */
- { 0x7FEF, 0x7FEF, 0x0000 }, /* R547 - FLL1 Control (4) */
- { 0x1FDB, 0x1FDB, 0x0000 }, /* R548 - FLL1 Control (5) */
- { 0x0000, 0x0000, 0x0000 }, /* R549 */
- { 0x0000, 0x0000, 0x0000 }, /* R550 */
- { 0x0000, 0x0000, 0x0000 }, /* R551 */
- { 0x0000, 0x0000, 0x0000 }, /* R552 */
- { 0x0000, 0x0000, 0x0000 }, /* R553 */
- { 0x0000, 0x0000, 0x0000 }, /* R554 */
- { 0x0000, 0x0000, 0x0000 }, /* R555 */
- { 0x0000, 0x0000, 0x0000 }, /* R556 */
- { 0x0000, 0x0000, 0x0000 }, /* R557 */
- { 0x0000, 0x0000, 0x0000 }, /* R558 */
- { 0x0000, 0x0000, 0x0000 }, /* R559 */
- { 0x0000, 0x0000, 0x0000 }, /* R560 */
- { 0x0000, 0x0000, 0x0000 }, /* R561 */
- { 0x0000, 0x0000, 0x0000 }, /* R562 */
- { 0x0000, 0x0000, 0x0000 }, /* R563 */
- { 0x0000, 0x0000, 0x0000 }, /* R564 */
- { 0x0000, 0x0000, 0x0000 }, /* R565 */
- { 0x0000, 0x0000, 0x0000 }, /* R566 */
- { 0x0000, 0x0000, 0x0000 }, /* R567 */
- { 0x0000, 0x0000, 0x0000 }, /* R568 */
- { 0x0000, 0x0000, 0x0000 }, /* R569 */
- { 0x0000, 0x0000, 0x0000 }, /* R570 */
- { 0x0000, 0x0000, 0x0000 }, /* R571 */
- { 0x0000, 0x0000, 0x0000 }, /* R572 */
- { 0x0000, 0x0000, 0x0000 }, /* R573 */
- { 0x0000, 0x0000, 0x0000 }, /* R574 */
- { 0x0000, 0x0000, 0x0000 }, /* R575 */
- { 0x0007, 0x0007, 0x0000 }, /* R576 - FLL2 Control (1) */
- { 0x3F77, 0x3F77, 0x0000 }, /* R577 - FLL2 Control (2) */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R578 - FLL2 Control (3) */
- { 0x7FEF, 0x7FEF, 0x0000 }, /* R579 - FLL2 Control (4) */
- { 0x1FDB, 0x1FDB, 0x0000 }, /* R580 - FLL2 Control (5) */
- { 0x0000, 0x0000, 0x0000 }, /* R581 */
- { 0x0000, 0x0000, 0x0000 }, /* R582 */
- { 0x0000, 0x0000, 0x0000 }, /* R583 */
- { 0x0000, 0x0000, 0x0000 }, /* R584 */
- { 0x0000, 0x0000, 0x0000 }, /* R585 */
- { 0x0000, 0x0000, 0x0000 }, /* R586 */
- { 0x0000, 0x0000, 0x0000 }, /* R587 */
- { 0x0000, 0x0000, 0x0000 }, /* R588 */
- { 0x0000, 0x0000, 0x0000 }, /* R589 */
- { 0x0000, 0x0000, 0x0000 }, /* R590 */
- { 0x0000, 0x0000, 0x0000 }, /* R591 */
- { 0x0000, 0x0000, 0x0000 }, /* R592 */
- { 0x0000, 0x0000, 0x0000 }, /* R593 */
- { 0x0000, 0x0000, 0x0000 }, /* R594 */
- { 0x0000, 0x0000, 0x0000 }, /* R595 */
- { 0x0000, 0x0000, 0x0000 }, /* R596 */
- { 0x0000, 0x0000, 0x0000 }, /* R597 */
- { 0x0000, 0x0000, 0x0000 }, /* R598 */
- { 0x0000, 0x0000, 0x0000 }, /* R599 */
- { 0x0000, 0x0000, 0x0000 }, /* R600 */
- { 0x0000, 0x0000, 0x0000 }, /* R601 */
- { 0x0000, 0x0000, 0x0000 }, /* R602 */
- { 0x0000, 0x0000, 0x0000 }, /* R603 */
- { 0x0000, 0x0000, 0x0000 }, /* R604 */
- { 0x0000, 0x0000, 0x0000 }, /* R605 */
- { 0x0000, 0x0000, 0x0000 }, /* R606 */
- { 0x0000, 0x0000, 0x0000 }, /* R607 */
- { 0x0000, 0x0000, 0x0000 }, /* R608 */
- { 0x0000, 0x0000, 0x0000 }, /* R609 */
- { 0x0000, 0x0000, 0x0000 }, /* R610 */
- { 0x0000, 0x0000, 0x0000 }, /* R611 */
- { 0x0000, 0x0000, 0x0000 }, /* R612 */
- { 0x0000, 0x0000, 0x0000 }, /* R613 */
- { 0x0000, 0x0000, 0x0000 }, /* R614 */
- { 0x0000, 0x0000, 0x0000 }, /* R615 */
- { 0x0000, 0x0000, 0x0000 }, /* R616 */
- { 0x0000, 0x0000, 0x0000 }, /* R617 */
- { 0x0000, 0x0000, 0x0000 }, /* R618 */
- { 0x0000, 0x0000, 0x0000 }, /* R619 */
- { 0x0000, 0x0000, 0x0000 }, /* R620 */
- { 0x0000, 0x0000, 0x0000 }, /* R621 */
- { 0x0000, 0x0000, 0x0000 }, /* R622 */
- { 0x0000, 0x0000, 0x0000 }, /* R623 */
- { 0x0000, 0x0000, 0x0000 }, /* R624 */
- { 0x0000, 0x0000, 0x0000 }, /* R625 */
- { 0x0000, 0x0000, 0x0000 }, /* R626 */
- { 0x0000, 0x0000, 0x0000 }, /* R627 */
- { 0x0000, 0x0000, 0x0000 }, /* R628 */
- { 0x0000, 0x0000, 0x0000 }, /* R629 */
- { 0x0000, 0x0000, 0x0000 }, /* R630 */
- { 0x0000, 0x0000, 0x0000 }, /* R631 */
- { 0x0000, 0x0000, 0x0000 }, /* R632 */
- { 0x0000, 0x0000, 0x0000 }, /* R633 */
- { 0x0000, 0x0000, 0x0000 }, /* R634 */
- { 0x0000, 0x0000, 0x0000 }, /* R635 */
- { 0x0000, 0x0000, 0x0000 }, /* R636 */
- { 0x0000, 0x0000, 0x0000 }, /* R637 */
- { 0x0000, 0x0000, 0x0000 }, /* R638 */
- { 0x0000, 0x0000, 0x0000 }, /* R639 */
- { 0x0000, 0x0000, 0x0000 }, /* R640 */
- { 0x0000, 0x0000, 0x0000 }, /* R641 */
- { 0x0000, 0x0000, 0x0000 }, /* R642 */
- { 0x0000, 0x0000, 0x0000 }, /* R643 */
- { 0x0000, 0x0000, 0x0000 }, /* R644 */
- { 0x0000, 0x0000, 0x0000 }, /* R645 */
- { 0x0000, 0x0000, 0x0000 }, /* R646 */
- { 0x0000, 0x0000, 0x0000 }, /* R647 */
- { 0x0000, 0x0000, 0x0000 }, /* R648 */
- { 0x0000, 0x0000, 0x0000 }, /* R649 */
- { 0x0000, 0x0000, 0x0000 }, /* R650 */
- { 0x0000, 0x0000, 0x0000 }, /* R651 */
- { 0x0000, 0x0000, 0x0000 }, /* R652 */
- { 0x0000, 0x0000, 0x0000 }, /* R653 */
- { 0x0000, 0x0000, 0x0000 }, /* R654 */
- { 0x0000, 0x0000, 0x0000 }, /* R655 */
- { 0x0000, 0x0000, 0x0000 }, /* R656 */
- { 0x0000, 0x0000, 0x0000 }, /* R657 */
- { 0x0000, 0x0000, 0x0000 }, /* R658 */
- { 0x0000, 0x0000, 0x0000 }, /* R659 */
- { 0x0000, 0x0000, 0x0000 }, /* R660 */
- { 0x0000, 0x0000, 0x0000 }, /* R661 */
- { 0x0000, 0x0000, 0x0000 }, /* R662 */
- { 0x0000, 0x0000, 0x0000 }, /* R663 */
- { 0x0000, 0x0000, 0x0000 }, /* R664 */
- { 0x0000, 0x0000, 0x0000 }, /* R665 */
- { 0x0000, 0x0000, 0x0000 }, /* R666 */
- { 0x0000, 0x0000, 0x0000 }, /* R667 */
- { 0x0000, 0x0000, 0x0000 }, /* R668 */
- { 0x0000, 0x0000, 0x0000 }, /* R669 */
- { 0x0000, 0x0000, 0x0000 }, /* R670 */
- { 0x0000, 0x0000, 0x0000 }, /* R671 */
- { 0x0000, 0x0000, 0x0000 }, /* R672 */
- { 0x0000, 0x0000, 0x0000 }, /* R673 */
- { 0x0000, 0x0000, 0x0000 }, /* R674 */
- { 0x0000, 0x0000, 0x0000 }, /* R675 */
- { 0x0000, 0x0000, 0x0000 }, /* R676 */
- { 0x0000, 0x0000, 0x0000 }, /* R677 */
- { 0x0000, 0x0000, 0x0000 }, /* R678 */
- { 0x0000, 0x0000, 0x0000 }, /* R679 */
- { 0x0000, 0x0000, 0x0000 }, /* R680 */
- { 0x0000, 0x0000, 0x0000 }, /* R681 */
- { 0x0000, 0x0000, 0x0000 }, /* R682 */
- { 0x0000, 0x0000, 0x0000 }, /* R683 */
- { 0x0000, 0x0000, 0x0000 }, /* R684 */
- { 0x0000, 0x0000, 0x0000 }, /* R685 */
- { 0x0000, 0x0000, 0x0000 }, /* R686 */
- { 0x0000, 0x0000, 0x0000 }, /* R687 */
- { 0x0000, 0x0000, 0x0000 }, /* R688 */
- { 0x0000, 0x0000, 0x0000 }, /* R689 */
- { 0x0000, 0x0000, 0x0000 }, /* R690 */
- { 0x0000, 0x0000, 0x0000 }, /* R691 */
- { 0x0000, 0x0000, 0x0000 }, /* R692 */
- { 0x0000, 0x0000, 0x0000 }, /* R693 */
- { 0x0000, 0x0000, 0x0000 }, /* R694 */
- { 0x0000, 0x0000, 0x0000 }, /* R695 */
- { 0x0000, 0x0000, 0x0000 }, /* R696 */
- { 0x0000, 0x0000, 0x0000 }, /* R697 */
- { 0x0000, 0x0000, 0x0000 }, /* R698 */
- { 0x0000, 0x0000, 0x0000 }, /* R699 */
- { 0x0000, 0x0000, 0x0000 }, /* R700 */
- { 0x0000, 0x0000, 0x0000 }, /* R701 */
- { 0x0000, 0x0000, 0x0000 }, /* R702 */
- { 0x0000, 0x0000, 0x0000 }, /* R703 */
- { 0x0000, 0x0000, 0x0000 }, /* R704 */
- { 0x0000, 0x0000, 0x0000 }, /* R705 */
- { 0x0000, 0x0000, 0x0000 }, /* R706 */
- { 0x0000, 0x0000, 0x0000 }, /* R707 */
- { 0x0000, 0x0000, 0x0000 }, /* R708 */
- { 0x0000, 0x0000, 0x0000 }, /* R709 */
- { 0x0000, 0x0000, 0x0000 }, /* R710 */
- { 0x0000, 0x0000, 0x0000 }, /* R711 */
- { 0x0000, 0x0000, 0x0000 }, /* R712 */
- { 0x0000, 0x0000, 0x0000 }, /* R713 */
- { 0x0000, 0x0000, 0x0000 }, /* R714 */
- { 0x0000, 0x0000, 0x0000 }, /* R715 */
- { 0x0000, 0x0000, 0x0000 }, /* R716 */
- { 0x0000, 0x0000, 0x0000 }, /* R717 */
- { 0x0000, 0x0000, 0x0000 }, /* R718 */
- { 0x0000, 0x0000, 0x0000 }, /* R719 */
- { 0x0000, 0x0000, 0x0000 }, /* R720 */
- { 0x0000, 0x0000, 0x0000 }, /* R721 */
- { 0x0000, 0x0000, 0x0000 }, /* R722 */
- { 0x0000, 0x0000, 0x0000 }, /* R723 */
- { 0x0000, 0x0000, 0x0000 }, /* R724 */
- { 0x0000, 0x0000, 0x0000 }, /* R725 */
- { 0x0000, 0x0000, 0x0000 }, /* R726 */
- { 0x0000, 0x0000, 0x0000 }, /* R727 */
- { 0x0000, 0x0000, 0x0000 }, /* R728 */
- { 0x0000, 0x0000, 0x0000 }, /* R729 */
- { 0x0000, 0x0000, 0x0000 }, /* R730 */
- { 0x0000, 0x0000, 0x0000 }, /* R731 */
- { 0x0000, 0x0000, 0x0000 }, /* R732 */
- { 0x0000, 0x0000, 0x0000 }, /* R733 */
- { 0x0000, 0x0000, 0x0000 }, /* R734 */
- { 0x0000, 0x0000, 0x0000 }, /* R735 */
- { 0x0000, 0x0000, 0x0000 }, /* R736 */
- { 0x0000, 0x0000, 0x0000 }, /* R737 */
- { 0x0000, 0x0000, 0x0000 }, /* R738 */
- { 0x0000, 0x0000, 0x0000 }, /* R739 */
- { 0x0000, 0x0000, 0x0000 }, /* R740 */
- { 0x0000, 0x0000, 0x0000 }, /* R741 */
- { 0x0000, 0x0000, 0x0000 }, /* R742 */
- { 0x0000, 0x0000, 0x0000 }, /* R743 */
- { 0x0000, 0x0000, 0x0000 }, /* R744 */
- { 0x0000, 0x0000, 0x0000 }, /* R745 */
- { 0x0000, 0x0000, 0x0000 }, /* R746 */
- { 0x0000, 0x0000, 0x0000 }, /* R747 */
- { 0x0000, 0x0000, 0x0000 }, /* R748 */
- { 0x0000, 0x0000, 0x0000 }, /* R749 */
- { 0x0000, 0x0000, 0x0000 }, /* R750 */
- { 0x0000, 0x0000, 0x0000 }, /* R751 */
- { 0x0000, 0x0000, 0x0000 }, /* R752 */
- { 0x0000, 0x0000, 0x0000 }, /* R753 */
- { 0x0000, 0x0000, 0x0000 }, /* R754 */
- { 0x0000, 0x0000, 0x0000 }, /* R755 */
- { 0x0000, 0x0000, 0x0000 }, /* R756 */
- { 0x0000, 0x0000, 0x0000 }, /* R757 */
- { 0x0000, 0x0000, 0x0000 }, /* R758 */
- { 0x0000, 0x0000, 0x0000 }, /* R759 */
- { 0x0000, 0x0000, 0x0000 }, /* R760 */
- { 0x0000, 0x0000, 0x0000 }, /* R761 */
- { 0x0000, 0x0000, 0x0000 }, /* R762 */
- { 0x0000, 0x0000, 0x0000 }, /* R763 */
- { 0x0000, 0x0000, 0x0000 }, /* R764 */
- { 0x0000, 0x0000, 0x0000 }, /* R765 */
- { 0x0000, 0x0000, 0x0000 }, /* R766 */
- { 0x0000, 0x0000, 0x0000 }, /* R767 */
- { 0xE1F8, 0xE1F8, 0x0000 }, /* R768 - AIF1 Control (1) */
- { 0xCD1F, 0xCD1F, 0x0000 }, /* R769 - AIF1 Control (2) */
- { 0xF000, 0xF000, 0x0000 }, /* R770 - AIF1 Master/Slave */
- { 0x01F0, 0x01F0, 0x0000 }, /* R771 - AIF1 BCLK */
- { 0x0FFF, 0x0FFF, 0x0000 }, /* R772 - AIF1ADC LRCLK */
- { 0x0FFF, 0x0FFF, 0x0000 }, /* R773 - AIF1DAC LRCLK */
- { 0x0003, 0x0003, 0x0000 }, /* R774 - AIF1DAC Data */
- { 0x0003, 0x0003, 0x0000 }, /* R775 - AIF1ADC Data */
- { 0x0000, 0x0000, 0x0000 }, /* R776 */
- { 0x0000, 0x0000, 0x0000 }, /* R777 */
- { 0x0000, 0x0000, 0x0000 }, /* R778 */
- { 0x0000, 0x0000, 0x0000 }, /* R779 */
- { 0x0000, 0x0000, 0x0000 }, /* R780 */
- { 0x0000, 0x0000, 0x0000 }, /* R781 */
- { 0x0000, 0x0000, 0x0000 }, /* R782 */
- { 0x0000, 0x0000, 0x0000 }, /* R783 */
- { 0xF1F8, 0xF1F8, 0x0000 }, /* R784 - AIF2 Control (1) */
- { 0xFD1F, 0xFD1F, 0x0000 }, /* R785 - AIF2 Control (2) */
- { 0xF000, 0xF000, 0x0000 }, /* R786 - AIF2 Master/Slave */
- { 0x01F0, 0x01F0, 0x0000 }, /* R787 - AIF2 BCLK */
- { 0x0FFF, 0x0FFF, 0x0000 }, /* R788 - AIF2ADC LRCLK */
- { 0x0FFF, 0x0FFF, 0x0000 }, /* R789 - AIF2DAC LRCLK */
- { 0x0003, 0x0003, 0x0000 }, /* R790 - AIF2DAC Data */
- { 0x0003, 0x0003, 0x0000 }, /* R791 - AIF2ADC Data */
- { 0x0000, 0x0000, 0x0000 }, /* R792 */
- { 0x0000, 0x0000, 0x0000 }, /* R793 */
- { 0x0000, 0x0000, 0x0000 }, /* R794 */
- { 0x0000, 0x0000, 0x0000 }, /* R795 */
- { 0x0000, 0x0000, 0x0000 }, /* R796 */
- { 0x0000, 0x0000, 0x0000 }, /* R797 */
- { 0x0000, 0x0000, 0x0000 }, /* R798 */
- { 0x0000, 0x0000, 0x0000 }, /* R799 */
- { 0x0000, 0x0000, 0x0000 }, /* R800 */
- { 0x0000, 0x0000, 0x0000 }, /* R801 */
- { 0x0000, 0x0000, 0x0000 }, /* R802 */
- { 0x0000, 0x0000, 0x0000 }, /* R803 */
- { 0x0000, 0x0000, 0x0000 }, /* R804 */
- { 0x0000, 0x0000, 0x0000 }, /* R805 */
- { 0x0000, 0x0000, 0x0000 }, /* R806 */
- { 0x0000, 0x0000, 0x0000 }, /* R807 */
- { 0x0000, 0x0000, 0x0000 }, /* R808 */
- { 0x0000, 0x0000, 0x0000 }, /* R809 */
- { 0x0000, 0x0000, 0x0000 }, /* R810 */
- { 0x0000, 0x0000, 0x0000 }, /* R811 */
- { 0x0000, 0x0000, 0x0000 }, /* R812 */
- { 0x0000, 0x0000, 0x0000 }, /* R813 */
- { 0x0000, 0x0000, 0x0000 }, /* R814 */
- { 0x0000, 0x0000, 0x0000 }, /* R815 */
- { 0x0000, 0x0000, 0x0000 }, /* R816 */
- { 0x0000, 0x0000, 0x0000 }, /* R817 */
- { 0x0000, 0x0000, 0x0000 }, /* R818 */
- { 0x0000, 0x0000, 0x0000 }, /* R819 */
- { 0x0000, 0x0000, 0x0000 }, /* R820 */
- { 0x0000, 0x0000, 0x0000 }, /* R821 */
- { 0x0000, 0x0000, 0x0000 }, /* R822 */
- { 0x0000, 0x0000, 0x0000 }, /* R823 */
- { 0x0000, 0x0000, 0x0000 }, /* R824 */
- { 0x0000, 0x0000, 0x0000 }, /* R825 */
- { 0x0000, 0x0000, 0x0000 }, /* R826 */
- { 0x0000, 0x0000, 0x0000 }, /* R827 */
- { 0x0000, 0x0000, 0x0000 }, /* R828 */
- { 0x0000, 0x0000, 0x0000 }, /* R829 */
- { 0x0000, 0x0000, 0x0000 }, /* R830 */
- { 0x0000, 0x0000, 0x0000 }, /* R831 */
- { 0x0000, 0x0000, 0x0000 }, /* R832 */
- { 0x0000, 0x0000, 0x0000 }, /* R833 */
- { 0x0000, 0x0000, 0x0000 }, /* R834 */
- { 0x0000, 0x0000, 0x0000 }, /* R835 */
- { 0x0000, 0x0000, 0x0000 }, /* R836 */
- { 0x0000, 0x0000, 0x0000 }, /* R837 */
- { 0x0000, 0x0000, 0x0000 }, /* R838 */
- { 0x0000, 0x0000, 0x0000 }, /* R839 */
- { 0x0000, 0x0000, 0x0000 }, /* R840 */
- { 0x0000, 0x0000, 0x0000 }, /* R841 */
- { 0x0000, 0x0000, 0x0000 }, /* R842 */
- { 0x0000, 0x0000, 0x0000 }, /* R843 */
- { 0x0000, 0x0000, 0x0000 }, /* R844 */
- { 0x0000, 0x0000, 0x0000 }, /* R845 */
- { 0x0000, 0x0000, 0x0000 }, /* R846 */
- { 0x0000, 0x0000, 0x0000 }, /* R847 */
- { 0x0000, 0x0000, 0x0000 }, /* R848 */
- { 0x0000, 0x0000, 0x0000 }, /* R849 */
- { 0x0000, 0x0000, 0x0000 }, /* R850 */
- { 0x0000, 0x0000, 0x0000 }, /* R851 */
- { 0x0000, 0x0000, 0x0000 }, /* R852 */
- { 0x0000, 0x0000, 0x0000 }, /* R853 */
- { 0x0000, 0x0000, 0x0000 }, /* R854 */
- { 0x0000, 0x0000, 0x0000 }, /* R855 */
- { 0x0000, 0x0000, 0x0000 }, /* R856 */
- { 0x0000, 0x0000, 0x0000 }, /* R857 */
- { 0x0000, 0x0000, 0x0000 }, /* R858 */
- { 0x0000, 0x0000, 0x0000 }, /* R859 */
- { 0x0000, 0x0000, 0x0000 }, /* R860 */
- { 0x0000, 0x0000, 0x0000 }, /* R861 */
- { 0x0000, 0x0000, 0x0000 }, /* R862 */
- { 0x0000, 0x0000, 0x0000 }, /* R863 */
- { 0x0000, 0x0000, 0x0000 }, /* R864 */
- { 0x0000, 0x0000, 0x0000 }, /* R865 */
- { 0x0000, 0x0000, 0x0000 }, /* R866 */
- { 0x0000, 0x0000, 0x0000 }, /* R867 */
- { 0x0000, 0x0000, 0x0000 }, /* R868 */
- { 0x0000, 0x0000, 0x0000 }, /* R869 */
- { 0x0000, 0x0000, 0x0000 }, /* R870 */
- { 0x0000, 0x0000, 0x0000 }, /* R871 */
- { 0x0000, 0x0000, 0x0000 }, /* R872 */
- { 0x0000, 0x0000, 0x0000 }, /* R873 */
- { 0x0000, 0x0000, 0x0000 }, /* R874 */
- { 0x0000, 0x0000, 0x0000 }, /* R875 */
- { 0x0000, 0x0000, 0x0000 }, /* R876 */
- { 0x0000, 0x0000, 0x0000 }, /* R877 */
- { 0x0000, 0x0000, 0x0000 }, /* R878 */
- { 0x0000, 0x0000, 0x0000 }, /* R879 */
- { 0x0000, 0x0000, 0x0000 }, /* R880 */
- { 0x0000, 0x0000, 0x0000 }, /* R881 */
- { 0x0000, 0x0000, 0x0000 }, /* R882 */
- { 0x0000, 0x0000, 0x0000 }, /* R883 */
- { 0x0000, 0x0000, 0x0000 }, /* R884 */
- { 0x0000, 0x0000, 0x0000 }, /* R885 */
- { 0x0000, 0x0000, 0x0000 }, /* R886 */
- { 0x0000, 0x0000, 0x0000 }, /* R887 */
- { 0x0000, 0x0000, 0x0000 }, /* R888 */
- { 0x0000, 0x0000, 0x0000 }, /* R889 */
- { 0x0000, 0x0000, 0x0000 }, /* R890 */
- { 0x0000, 0x0000, 0x0000 }, /* R891 */
- { 0x0000, 0x0000, 0x0000 }, /* R892 */
- { 0x0000, 0x0000, 0x0000 }, /* R893 */
- { 0x0000, 0x0000, 0x0000 }, /* R894 */
- { 0x0000, 0x0000, 0x0000 }, /* R895 */
- { 0x0000, 0x0000, 0x0000 }, /* R896 */
- { 0x0000, 0x0000, 0x0000 }, /* R897 */
- { 0x0000, 0x0000, 0x0000 }, /* R898 */
- { 0x0000, 0x0000, 0x0000 }, /* R899 */
- { 0x0000, 0x0000, 0x0000 }, /* R900 */
- { 0x0000, 0x0000, 0x0000 }, /* R901 */
- { 0x0000, 0x0000, 0x0000 }, /* R902 */
- { 0x0000, 0x0000, 0x0000 }, /* R903 */
- { 0x0000, 0x0000, 0x0000 }, /* R904 */
- { 0x0000, 0x0000, 0x0000 }, /* R905 */
- { 0x0000, 0x0000, 0x0000 }, /* R906 */
- { 0x0000, 0x0000, 0x0000 }, /* R907 */
- { 0x0000, 0x0000, 0x0000 }, /* R908 */
- { 0x0000, 0x0000, 0x0000 }, /* R909 */
- { 0x0000, 0x0000, 0x0000 }, /* R910 */
- { 0x0000, 0x0000, 0x0000 }, /* R911 */
- { 0x0000, 0x0000, 0x0000 }, /* R912 */
- { 0x0000, 0x0000, 0x0000 }, /* R913 */
- { 0x0000, 0x0000, 0x0000 }, /* R914 */
- { 0x0000, 0x0000, 0x0000 }, /* R915 */
- { 0x0000, 0x0000, 0x0000 }, /* R916 */
- { 0x0000, 0x0000, 0x0000 }, /* R917 */
- { 0x0000, 0x0000, 0x0000 }, /* R918 */
- { 0x0000, 0x0000, 0x0000 }, /* R919 */
- { 0x0000, 0x0000, 0x0000 }, /* R920 */
- { 0x0000, 0x0000, 0x0000 }, /* R921 */
- { 0x0000, 0x0000, 0x0000 }, /* R922 */
- { 0x0000, 0x0000, 0x0000 }, /* R923 */
- { 0x0000, 0x0000, 0x0000 }, /* R924 */
- { 0x0000, 0x0000, 0x0000 }, /* R925 */
- { 0x0000, 0x0000, 0x0000 }, /* R926 */
- { 0x0000, 0x0000, 0x0000 }, /* R927 */
- { 0x0000, 0x0000, 0x0000 }, /* R928 */
- { 0x0000, 0x0000, 0x0000 }, /* R929 */
- { 0x0000, 0x0000, 0x0000 }, /* R930 */
- { 0x0000, 0x0000, 0x0000 }, /* R931 */
- { 0x0000, 0x0000, 0x0000 }, /* R932 */
- { 0x0000, 0x0000, 0x0000 }, /* R933 */
- { 0x0000, 0x0000, 0x0000 }, /* R934 */
- { 0x0000, 0x0000, 0x0000 }, /* R935 */
- { 0x0000, 0x0000, 0x0000 }, /* R936 */
- { 0x0000, 0x0000, 0x0000 }, /* R937 */
- { 0x0000, 0x0000, 0x0000 }, /* R938 */
- { 0x0000, 0x0000, 0x0000 }, /* R939 */
- { 0x0000, 0x0000, 0x0000 }, /* R940 */
- { 0x0000, 0x0000, 0x0000 }, /* R941 */
- { 0x0000, 0x0000, 0x0000 }, /* R942 */
- { 0x0000, 0x0000, 0x0000 }, /* R943 */
- { 0x0000, 0x0000, 0x0000 }, /* R944 */
- { 0x0000, 0x0000, 0x0000 }, /* R945 */
- { 0x0000, 0x0000, 0x0000 }, /* R946 */
- { 0x0000, 0x0000, 0x0000 }, /* R947 */
- { 0x0000, 0x0000, 0x0000 }, /* R948 */
- { 0x0000, 0x0000, 0x0000 }, /* R949 */
- { 0x0000, 0x0000, 0x0000 }, /* R950 */
- { 0x0000, 0x0000, 0x0000 }, /* R951 */
- { 0x0000, 0x0000, 0x0000 }, /* R952 */
- { 0x0000, 0x0000, 0x0000 }, /* R953 */
- { 0x0000, 0x0000, 0x0000 }, /* R954 */
- { 0x0000, 0x0000, 0x0000 }, /* R955 */
- { 0x0000, 0x0000, 0x0000 }, /* R956 */
- { 0x0000, 0x0000, 0x0000 }, /* R957 */
- { 0x0000, 0x0000, 0x0000 }, /* R958 */
- { 0x0000, 0x0000, 0x0000 }, /* R959 */
- { 0x0000, 0x0000, 0x0000 }, /* R960 */
- { 0x0000, 0x0000, 0x0000 }, /* R961 */
- { 0x0000, 0x0000, 0x0000 }, /* R962 */
- { 0x0000, 0x0000, 0x0000 }, /* R963 */
- { 0x0000, 0x0000, 0x0000 }, /* R964 */
- { 0x0000, 0x0000, 0x0000 }, /* R965 */
- { 0x0000, 0x0000, 0x0000 }, /* R966 */
- { 0x0000, 0x0000, 0x0000 }, /* R967 */
- { 0x0000, 0x0000, 0x0000 }, /* R968 */
- { 0x0000, 0x0000, 0x0000 }, /* R969 */
- { 0x0000, 0x0000, 0x0000 }, /* R970 */
- { 0x0000, 0x0000, 0x0000 }, /* R971 */
- { 0x0000, 0x0000, 0x0000 }, /* R972 */
- { 0x0000, 0x0000, 0x0000 }, /* R973 */
- { 0x0000, 0x0000, 0x0000 }, /* R974 */
- { 0x0000, 0x0000, 0x0000 }, /* R975 */
- { 0x0000, 0x0000, 0x0000 }, /* R976 */
- { 0x0000, 0x0000, 0x0000 }, /* R977 */
- { 0x0000, 0x0000, 0x0000 }, /* R978 */
- { 0x0000, 0x0000, 0x0000 }, /* R979 */
- { 0x0000, 0x0000, 0x0000 }, /* R980 */
- { 0x0000, 0x0000, 0x0000 }, /* R981 */
- { 0x0000, 0x0000, 0x0000 }, /* R982 */
- { 0x0000, 0x0000, 0x0000 }, /* R983 */
- { 0x0000, 0x0000, 0x0000 }, /* R984 */
- { 0x0000, 0x0000, 0x0000 }, /* R985 */
- { 0x0000, 0x0000, 0x0000 }, /* R986 */
- { 0x0000, 0x0000, 0x0000 }, /* R987 */
- { 0x0000, 0x0000, 0x0000 }, /* R988 */
- { 0x0000, 0x0000, 0x0000 }, /* R989 */
- { 0x0000, 0x0000, 0x0000 }, /* R990 */
- { 0x0000, 0x0000, 0x0000 }, /* R991 */
- { 0x0000, 0x0000, 0x0000 }, /* R992 */
- { 0x0000, 0x0000, 0x0000 }, /* R993 */
- { 0x0000, 0x0000, 0x0000 }, /* R994 */
- { 0x0000, 0x0000, 0x0000 }, /* R995 */
- { 0x0000, 0x0000, 0x0000 }, /* R996 */
- { 0x0000, 0x0000, 0x0000 }, /* R997 */
- { 0x0000, 0x0000, 0x0000 }, /* R998 */
- { 0x0000, 0x0000, 0x0000 }, /* R999 */
- { 0x0000, 0x0000, 0x0000 }, /* R1000 */
- { 0x0000, 0x0000, 0x0000 }, /* R1001 */
- { 0x0000, 0x0000, 0x0000 }, /* R1002 */
- { 0x0000, 0x0000, 0x0000 }, /* R1003 */
- { 0x0000, 0x0000, 0x0000 }, /* R1004 */
- { 0x0000, 0x0000, 0x0000 }, /* R1005 */
- { 0x0000, 0x0000, 0x0000 }, /* R1006 */
- { 0x0000, 0x0000, 0x0000 }, /* R1007 */
- { 0x0000, 0x0000, 0x0000 }, /* R1008 */
- { 0x0000, 0x0000, 0x0000 }, /* R1009 */
- { 0x0000, 0x0000, 0x0000 }, /* R1010 */
- { 0x0000, 0x0000, 0x0000 }, /* R1011 */
- { 0x0000, 0x0000, 0x0000 }, /* R1012 */
- { 0x0000, 0x0000, 0x0000 }, /* R1013 */
- { 0x0000, 0x0000, 0x0000 }, /* R1014 */
- { 0x0000, 0x0000, 0x0000 }, /* R1015 */
- { 0x0000, 0x0000, 0x0000 }, /* R1016 */
- { 0x0000, 0x0000, 0x0000 }, /* R1017 */
- { 0x0000, 0x0000, 0x0000 }, /* R1018 */
- { 0x0000, 0x0000, 0x0000 }, /* R1019 */
- { 0x0000, 0x0000, 0x0000 }, /* R1020 */
- { 0x0000, 0x0000, 0x0000 }, /* R1021 */
- { 0x0000, 0x0000, 0x0000 }, /* R1022 */
- { 0x0000, 0x0000, 0x0000 }, /* R1023 */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1024 - AIF1 ADC1 Left Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1025 - AIF1 ADC1 Right Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1026 - AIF1 DAC1 Left Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1027 - AIF1 DAC1 Right Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1028 - AIF1 ADC2 Left Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1029 - AIF1 ADC2 Right Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1030 - AIF1 DAC2 Left Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1031 - AIF1 DAC2 Right Volume */
- { 0x0000, 0x0000, 0x0000 }, /* R1032 */
- { 0x0000, 0x0000, 0x0000 }, /* R1033 */
- { 0x0000, 0x0000, 0x0000 }, /* R1034 */
- { 0x0000, 0x0000, 0x0000 }, /* R1035 */
- { 0x0000, 0x0000, 0x0000 }, /* R1036 */
- { 0x0000, 0x0000, 0x0000 }, /* R1037 */
- { 0x0000, 0x0000, 0x0000 }, /* R1038 */
- { 0x0000, 0x0000, 0x0000 }, /* R1039 */
- { 0xF800, 0xF800, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
- { 0x7800, 0x7800, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */
- { 0x0000, 0x0000, 0x0000 }, /* R1042 */
- { 0x0000, 0x0000, 0x0000 }, /* R1043 */
- { 0x0000, 0x0000, 0x0000 }, /* R1044 */
- { 0x0000, 0x0000, 0x0000 }, /* R1045 */
- { 0x0000, 0x0000, 0x0000 }, /* R1046 */
- { 0x0000, 0x0000, 0x0000 }, /* R1047 */
- { 0x0000, 0x0000, 0x0000 }, /* R1048 */
- { 0x0000, 0x0000, 0x0000 }, /* R1049 */
- { 0x0000, 0x0000, 0x0000 }, /* R1050 */
- { 0x0000, 0x0000, 0x0000 }, /* R1051 */
- { 0x0000, 0x0000, 0x0000 }, /* R1052 */
- { 0x0000, 0x0000, 0x0000 }, /* R1053 */
- { 0x0000, 0x0000, 0x0000 }, /* R1054 */
- { 0x0000, 0x0000, 0x0000 }, /* R1055 */
- { 0x02B6, 0x02B6, 0x0000 }, /* R1056 - AIF1 DAC1 Filters (1) */
- { 0x3F00, 0x3F00, 0x0000 }, /* R1057 - AIF1 DAC1 Filters (2) */
- { 0x02B6, 0x02B6, 0x0000 }, /* R1058 - AIF1 DAC2 Filters (1) */
- { 0x3F00, 0x3F00, 0x0000 }, /* R1059 - AIF1 DAC2 Filters (2) */
- { 0x0000, 0x0000, 0x0000 }, /* R1060 */
- { 0x0000, 0x0000, 0x0000 }, /* R1061 */
- { 0x0000, 0x0000, 0x0000 }, /* R1062 */
- { 0x0000, 0x0000, 0x0000 }, /* R1063 */
- { 0x0000, 0x0000, 0x0000 }, /* R1064 */
- { 0x0000, 0x0000, 0x0000 }, /* R1065 */
- { 0x0000, 0x0000, 0x0000 }, /* R1066 */
- { 0x0000, 0x0000, 0x0000 }, /* R1067 */
- { 0x0000, 0x0000, 0x0000 }, /* R1068 */
- { 0x0000, 0x0000, 0x0000 }, /* R1069 */
- { 0x0000, 0x0000, 0x0000 }, /* R1070 */
- { 0x0000, 0x0000, 0x0000 }, /* R1071 */
- { 0x0000, 0x0000, 0x0000 }, /* R1072 */
- { 0x0000, 0x0000, 0x0000 }, /* R1073 */
- { 0x0000, 0x0000, 0x0000 }, /* R1074 */
- { 0x0000, 0x0000, 0x0000 }, /* R1075 */
- { 0x0000, 0x0000, 0x0000 }, /* R1076 */
- { 0x0000, 0x0000, 0x0000 }, /* R1077 */
- { 0x0000, 0x0000, 0x0000 }, /* R1078 */
- { 0x0000, 0x0000, 0x0000 }, /* R1079 */
- { 0x0000, 0x0000, 0x0000 }, /* R1080 */
- { 0x0000, 0x0000, 0x0000 }, /* R1081 */
- { 0x0000, 0x0000, 0x0000 }, /* R1082 */
- { 0x0000, 0x0000, 0x0000 }, /* R1083 */
- { 0x0000, 0x0000, 0x0000 }, /* R1084 */
- { 0x0000, 0x0000, 0x0000 }, /* R1085 */
- { 0x0000, 0x0000, 0x0000 }, /* R1086 */
- { 0x0000, 0x0000, 0x0000 }, /* R1087 */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1088 - AIF1 DRC1 (1) */
- { 0x1FFF, 0x1FFF, 0x0000 }, /* R1089 - AIF1 DRC1 (2) */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
- { 0x07FF, 0x07FF, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
- { 0x03FF, 0x03FF, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
- { 0x0000, 0x0000, 0x0000 }, /* R1093 */
- { 0x0000, 0x0000, 0x0000 }, /* R1094 */
- { 0x0000, 0x0000, 0x0000 }, /* R1095 */
- { 0x0000, 0x0000, 0x0000 }, /* R1096 */
- { 0x0000, 0x0000, 0x0000 }, /* R1097 */
- { 0x0000, 0x0000, 0x0000 }, /* R1098 */
- { 0x0000, 0x0000, 0x0000 }, /* R1099 */
- { 0x0000, 0x0000, 0x0000 }, /* R1100 */
- { 0x0000, 0x0000, 0x0000 }, /* R1101 */
- { 0x0000, 0x0000, 0x0000 }, /* R1102 */
- { 0x0000, 0x0000, 0x0000 }, /* R1103 */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1104 - AIF1 DRC2 (1) */
- { 0x1FFF, 0x1FFF, 0x0000 }, /* R1105 - AIF1 DRC2 (2) */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */
- { 0x07FF, 0x07FF, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */
- { 0x03FF, 0x03FF, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */
- { 0x0000, 0x0000, 0x0000 }, /* R1109 */
- { 0x0000, 0x0000, 0x0000 }, /* R1110 */
- { 0x0000, 0x0000, 0x0000 }, /* R1111 */
- { 0x0000, 0x0000, 0x0000 }, /* R1112 */
- { 0x0000, 0x0000, 0x0000 }, /* R1113 */
- { 0x0000, 0x0000, 0x0000 }, /* R1114 */
- { 0x0000, 0x0000, 0x0000 }, /* R1115 */
- { 0x0000, 0x0000, 0x0000 }, /* R1116 */
- { 0x0000, 0x0000, 0x0000 }, /* R1117 */
- { 0x0000, 0x0000, 0x0000 }, /* R1118 */
- { 0x0000, 0x0000, 0x0000 }, /* R1119 */
- { 0x0000, 0x0000, 0x0000 }, /* R1120 */
- { 0x0000, 0x0000, 0x0000 }, /* R1121 */
- { 0x0000, 0x0000, 0x0000 }, /* R1122 */
- { 0x0000, 0x0000, 0x0000 }, /* R1123 */
- { 0x0000, 0x0000, 0x0000 }, /* R1124 */
- { 0x0000, 0x0000, 0x0000 }, /* R1125 */
- { 0x0000, 0x0000, 0x0000 }, /* R1126 */
- { 0x0000, 0x0000, 0x0000 }, /* R1127 */
- { 0x0000, 0x0000, 0x0000 }, /* R1128 */
- { 0x0000, 0x0000, 0x0000 }, /* R1129 */
- { 0x0000, 0x0000, 0x0000 }, /* R1130 */
- { 0x0000, 0x0000, 0x0000 }, /* R1131 */
- { 0x0000, 0x0000, 0x0000 }, /* R1132 */
- { 0x0000, 0x0000, 0x0000 }, /* R1133 */
- { 0x0000, 0x0000, 0x0000 }, /* R1134 */
- { 0x0000, 0x0000, 0x0000 }, /* R1135 */
- { 0x0000, 0x0000, 0x0000 }, /* R1136 */
- { 0x0000, 0x0000, 0x0000 }, /* R1137 */
- { 0x0000, 0x0000, 0x0000 }, /* R1138 */
- { 0x0000, 0x0000, 0x0000 }, /* R1139 */
- { 0x0000, 0x0000, 0x0000 }, /* R1140 */
- { 0x0000, 0x0000, 0x0000 }, /* R1141 */
- { 0x0000, 0x0000, 0x0000 }, /* R1142 */
- { 0x0000, 0x0000, 0x0000 }, /* R1143 */
- { 0x0000, 0x0000, 0x0000 }, /* R1144 */
- { 0x0000, 0x0000, 0x0000 }, /* R1145 */
- { 0x0000, 0x0000, 0x0000 }, /* R1146 */
- { 0x0000, 0x0000, 0x0000 }, /* R1147 */
- { 0x0000, 0x0000, 0x0000 }, /* R1148 */
- { 0x0000, 0x0000, 0x0000 }, /* R1149 */
- { 0x0000, 0x0000, 0x0000 }, /* R1150 */
- { 0x0000, 0x0000, 0x0000 }, /* R1151 */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
- { 0xFFC0, 0xFFC0, 0x0000 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
- { 0x0000, 0x0000, 0x0000 }, /* R1172 */
- { 0x0000, 0x0000, 0x0000 }, /* R1173 */
- { 0x0000, 0x0000, 0x0000 }, /* R1174 */
- { 0x0000, 0x0000, 0x0000 }, /* R1175 */
- { 0x0000, 0x0000, 0x0000 }, /* R1176 */
- { 0x0000, 0x0000, 0x0000 }, /* R1177 */
- { 0x0000, 0x0000, 0x0000 }, /* R1178 */
- { 0x0000, 0x0000, 0x0000 }, /* R1179 */
- { 0x0000, 0x0000, 0x0000 }, /* R1180 */
- { 0x0000, 0x0000, 0x0000 }, /* R1181 */
- { 0x0000, 0x0000, 0x0000 }, /* R1182 */
- { 0x0000, 0x0000, 0x0000 }, /* R1183 */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
- { 0xFFC0, 0xFFC0, 0x0000 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
- { 0x0000, 0x0000, 0x0000 }, /* R1204 */
- { 0x0000, 0x0000, 0x0000 }, /* R1205 */
- { 0x0000, 0x0000, 0x0000 }, /* R1206 */
- { 0x0000, 0x0000, 0x0000 }, /* R1207 */
- { 0x0000, 0x0000, 0x0000 }, /* R1208 */
- { 0x0000, 0x0000, 0x0000 }, /* R1209 */
- { 0x0000, 0x0000, 0x0000 }, /* R1210 */
- { 0x0000, 0x0000, 0x0000 }, /* R1211 */
- { 0x0000, 0x0000, 0x0000 }, /* R1212 */
- { 0x0000, 0x0000, 0x0000 }, /* R1213 */
- { 0x0000, 0x0000, 0x0000 }, /* R1214 */
- { 0x0000, 0x0000, 0x0000 }, /* R1215 */
- { 0x0000, 0x0000, 0x0000 }, /* R1216 */
- { 0x0000, 0x0000, 0x0000 }, /* R1217 */
- { 0x0000, 0x0000, 0x0000 }, /* R1218 */
- { 0x0000, 0x0000, 0x0000 }, /* R1219 */
- { 0x0000, 0x0000, 0x0000 }, /* R1220 */
- { 0x0000, 0x0000, 0x0000 }, /* R1221 */
- { 0x0000, 0x0000, 0x0000 }, /* R1222 */
- { 0x0000, 0x0000, 0x0000 }, /* R1223 */
- { 0x0000, 0x0000, 0x0000 }, /* R1224 */
- { 0x0000, 0x0000, 0x0000 }, /* R1225 */
- { 0x0000, 0x0000, 0x0000 }, /* R1226 */
- { 0x0000, 0x0000, 0x0000 }, /* R1227 */
- { 0x0000, 0x0000, 0x0000 }, /* R1228 */
- { 0x0000, 0x0000, 0x0000 }, /* R1229 */
- { 0x0000, 0x0000, 0x0000 }, /* R1230 */
- { 0x0000, 0x0000, 0x0000 }, /* R1231 */
- { 0x0000, 0x0000, 0x0000 }, /* R1232 */
- { 0x0000, 0x0000, 0x0000 }, /* R1233 */
- { 0x0000, 0x0000, 0x0000 }, /* R1234 */
- { 0x0000, 0x0000, 0x0000 }, /* R1235 */
- { 0x0000, 0x0000, 0x0000 }, /* R1236 */
- { 0x0000, 0x0000, 0x0000 }, /* R1237 */
- { 0x0000, 0x0000, 0x0000 }, /* R1238 */
- { 0x0000, 0x0000, 0x0000 }, /* R1239 */
- { 0x0000, 0x0000, 0x0000 }, /* R1240 */
- { 0x0000, 0x0000, 0x0000 }, /* R1241 */
- { 0x0000, 0x0000, 0x0000 }, /* R1242 */
- { 0x0000, 0x0000, 0x0000 }, /* R1243 */
- { 0x0000, 0x0000, 0x0000 }, /* R1244 */
- { 0x0000, 0x0000, 0x0000 }, /* R1245 */
- { 0x0000, 0x0000, 0x0000 }, /* R1246 */
- { 0x0000, 0x0000, 0x0000 }, /* R1247 */
- { 0x0000, 0x0000, 0x0000 }, /* R1248 */
- { 0x0000, 0x0000, 0x0000 }, /* R1249 */
- { 0x0000, 0x0000, 0x0000 }, /* R1250 */
- { 0x0000, 0x0000, 0x0000 }, /* R1251 */
- { 0x0000, 0x0000, 0x0000 }, /* R1252 */
- { 0x0000, 0x0000, 0x0000 }, /* R1253 */
- { 0x0000, 0x0000, 0x0000 }, /* R1254 */
- { 0x0000, 0x0000, 0x0000 }, /* R1255 */
- { 0x0000, 0x0000, 0x0000 }, /* R1256 */
- { 0x0000, 0x0000, 0x0000 }, /* R1257 */
- { 0x0000, 0x0000, 0x0000 }, /* R1258 */
- { 0x0000, 0x0000, 0x0000 }, /* R1259 */
- { 0x0000, 0x0000, 0x0000 }, /* R1260 */
- { 0x0000, 0x0000, 0x0000 }, /* R1261 */
- { 0x0000, 0x0000, 0x0000 }, /* R1262 */
- { 0x0000, 0x0000, 0x0000 }, /* R1263 */
- { 0x0000, 0x0000, 0x0000 }, /* R1264 */
- { 0x0000, 0x0000, 0x0000 }, /* R1265 */
- { 0x0000, 0x0000, 0x0000 }, /* R1266 */
- { 0x0000, 0x0000, 0x0000 }, /* R1267 */
- { 0x0000, 0x0000, 0x0000 }, /* R1268 */
- { 0x0000, 0x0000, 0x0000 }, /* R1269 */
- { 0x0000, 0x0000, 0x0000 }, /* R1270 */
- { 0x0000, 0x0000, 0x0000 }, /* R1271 */
- { 0x0000, 0x0000, 0x0000 }, /* R1272 */
- { 0x0000, 0x0000, 0x0000 }, /* R1273 */
- { 0x0000, 0x0000, 0x0000 }, /* R1274 */
- { 0x0000, 0x0000, 0x0000 }, /* R1275 */
- { 0x0000, 0x0000, 0x0000 }, /* R1276 */
- { 0x0000, 0x0000, 0x0000 }, /* R1277 */
- { 0x0000, 0x0000, 0x0000 }, /* R1278 */
- { 0x0000, 0x0000, 0x0000 }, /* R1279 */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1280 - AIF2 ADC Left Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1281 - AIF2 ADC Right Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1282 - AIF2 DAC Left Volume */
- { 0x00FF, 0x01FF, 0x0000 }, /* R1283 - AIF2 DAC Right Volume */
- { 0x0000, 0x0000, 0x0000 }, /* R1284 */
- { 0x0000, 0x0000, 0x0000 }, /* R1285 */
- { 0x0000, 0x0000, 0x0000 }, /* R1286 */
- { 0x0000, 0x0000, 0x0000 }, /* R1287 */
- { 0x0000, 0x0000, 0x0000 }, /* R1288 */
- { 0x0000, 0x0000, 0x0000 }, /* R1289 */
- { 0x0000, 0x0000, 0x0000 }, /* R1290 */
- { 0x0000, 0x0000, 0x0000 }, /* R1291 */
- { 0x0000, 0x0000, 0x0000 }, /* R1292 */
- { 0x0000, 0x0000, 0x0000 }, /* R1293 */
- { 0x0000, 0x0000, 0x0000 }, /* R1294 */
- { 0x0000, 0x0000, 0x0000 }, /* R1295 */
- { 0xF800, 0xF800, 0x0000 }, /* R1296 - AIF2 ADC Filters */
- { 0x0000, 0x0000, 0x0000 }, /* R1297 */
- { 0x0000, 0x0000, 0x0000 }, /* R1298 */
- { 0x0000, 0x0000, 0x0000 }, /* R1299 */
- { 0x0000, 0x0000, 0x0000 }, /* R1300 */
- { 0x0000, 0x0000, 0x0000 }, /* R1301 */
- { 0x0000, 0x0000, 0x0000 }, /* R1302 */
- { 0x0000, 0x0000, 0x0000 }, /* R1303 */
- { 0x0000, 0x0000, 0x0000 }, /* R1304 */
- { 0x0000, 0x0000, 0x0000 }, /* R1305 */
- { 0x0000, 0x0000, 0x0000 }, /* R1306 */
- { 0x0000, 0x0000, 0x0000 }, /* R1307 */
- { 0x0000, 0x0000, 0x0000 }, /* R1308 */
- { 0x0000, 0x0000, 0x0000 }, /* R1309 */
- { 0x0000, 0x0000, 0x0000 }, /* R1310 */
- { 0x0000, 0x0000, 0x0000 }, /* R1311 */
- { 0x02B6, 0x02B6, 0x0000 }, /* R1312 - AIF2 DAC Filters (1) */
- { 0x3F00, 0x3F00, 0x0000 }, /* R1313 - AIF2 DAC Filters (2) */
- { 0x0000, 0x0000, 0x0000 }, /* R1314 */
- { 0x0000, 0x0000, 0x0000 }, /* R1315 */
- { 0x0000, 0x0000, 0x0000 }, /* R1316 */
- { 0x0000, 0x0000, 0x0000 }, /* R1317 */
- { 0x0000, 0x0000, 0x0000 }, /* R1318 */
- { 0x0000, 0x0000, 0x0000 }, /* R1319 */
- { 0x0000, 0x0000, 0x0000 }, /* R1320 */
- { 0x0000, 0x0000, 0x0000 }, /* R1321 */
- { 0x0000, 0x0000, 0x0000 }, /* R1322 */
- { 0x0000, 0x0000, 0x0000 }, /* R1323 */
- { 0x0000, 0x0000, 0x0000 }, /* R1324 */
- { 0x0000, 0x0000, 0x0000 }, /* R1325 */
- { 0x0000, 0x0000, 0x0000 }, /* R1326 */
- { 0x0000, 0x0000, 0x0000 }, /* R1327 */
- { 0x0000, 0x0000, 0x0000 }, /* R1328 */
- { 0x0000, 0x0000, 0x0000 }, /* R1329 */
- { 0x0000, 0x0000, 0x0000 }, /* R1330 */
- { 0x0000, 0x0000, 0x0000 }, /* R1331 */
- { 0x0000, 0x0000, 0x0000 }, /* R1332 */
- { 0x0000, 0x0000, 0x0000 }, /* R1333 */
- { 0x0000, 0x0000, 0x0000 }, /* R1334 */
- { 0x0000, 0x0000, 0x0000 }, /* R1335 */
- { 0x0000, 0x0000, 0x0000 }, /* R1336 */
- { 0x0000, 0x0000, 0x0000 }, /* R1337 */
- { 0x0000, 0x0000, 0x0000 }, /* R1338 */
- { 0x0000, 0x0000, 0x0000 }, /* R1339 */
- { 0x0000, 0x0000, 0x0000 }, /* R1340 */
- { 0x0000, 0x0000, 0x0000 }, /* R1341 */
- { 0x0000, 0x0000, 0x0000 }, /* R1342 */
- { 0x0000, 0x0000, 0x0000 }, /* R1343 */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1344 - AIF2 DRC (1) */
- { 0x1FFF, 0x1FFF, 0x0000 }, /* R1345 - AIF2 DRC (2) */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1346 - AIF2 DRC (3) */
- { 0x07FF, 0x07FF, 0x0000 }, /* R1347 - AIF2 DRC (4) */
- { 0x03FF, 0x03FF, 0x0000 }, /* R1348 - AIF2 DRC (5) */
- { 0x0000, 0x0000, 0x0000 }, /* R1349 */
- { 0x0000, 0x0000, 0x0000 }, /* R1350 */
- { 0x0000, 0x0000, 0x0000 }, /* R1351 */
- { 0x0000, 0x0000, 0x0000 }, /* R1352 */
- { 0x0000, 0x0000, 0x0000 }, /* R1353 */
- { 0x0000, 0x0000, 0x0000 }, /* R1354 */
- { 0x0000, 0x0000, 0x0000 }, /* R1355 */
- { 0x0000, 0x0000, 0x0000 }, /* R1356 */
- { 0x0000, 0x0000, 0x0000 }, /* R1357 */
- { 0x0000, 0x0000, 0x0000 }, /* R1358 */
- { 0x0000, 0x0000, 0x0000 }, /* R1359 */
- { 0x0000, 0x0000, 0x0000 }, /* R1360 */
- { 0x0000, 0x0000, 0x0000 }, /* R1361 */
- { 0x0000, 0x0000, 0x0000 }, /* R1362 */
- { 0x0000, 0x0000, 0x0000 }, /* R1363 */
- { 0x0000, 0x0000, 0x0000 }, /* R1364 */
- { 0x0000, 0x0000, 0x0000 }, /* R1365 */
- { 0x0000, 0x0000, 0x0000 }, /* R1366 */
- { 0x0000, 0x0000, 0x0000 }, /* R1367 */
- { 0x0000, 0x0000, 0x0000 }, /* R1368 */
- { 0x0000, 0x0000, 0x0000 }, /* R1369 */
- { 0x0000, 0x0000, 0x0000 }, /* R1370 */
- { 0x0000, 0x0000, 0x0000 }, /* R1371 */
- { 0x0000, 0x0000, 0x0000 }, /* R1372 */
- { 0x0000, 0x0000, 0x0000 }, /* R1373 */
- { 0x0000, 0x0000, 0x0000 }, /* R1374 */
- { 0x0000, 0x0000, 0x0000 }, /* R1375 */
- { 0x0000, 0x0000, 0x0000 }, /* R1376 */
- { 0x0000, 0x0000, 0x0000 }, /* R1377 */
- { 0x0000, 0x0000, 0x0000 }, /* R1378 */
- { 0x0000, 0x0000, 0x0000 }, /* R1379 */
- { 0x0000, 0x0000, 0x0000 }, /* R1380 */
- { 0x0000, 0x0000, 0x0000 }, /* R1381 */
- { 0x0000, 0x0000, 0x0000 }, /* R1382 */
- { 0x0000, 0x0000, 0x0000 }, /* R1383 */
- { 0x0000, 0x0000, 0x0000 }, /* R1384 */
- { 0x0000, 0x0000, 0x0000 }, /* R1385 */
- { 0x0000, 0x0000, 0x0000 }, /* R1386 */
- { 0x0000, 0x0000, 0x0000 }, /* R1387 */
- { 0x0000, 0x0000, 0x0000 }, /* R1388 */
- { 0x0000, 0x0000, 0x0000 }, /* R1389 */
- { 0x0000, 0x0000, 0x0000 }, /* R1390 */
- { 0x0000, 0x0000, 0x0000 }, /* R1391 */
- { 0x0000, 0x0000, 0x0000 }, /* R1392 */
- { 0x0000, 0x0000, 0x0000 }, /* R1393 */
- { 0x0000, 0x0000, 0x0000 }, /* R1394 */
- { 0x0000, 0x0000, 0x0000 }, /* R1395 */
- { 0x0000, 0x0000, 0x0000 }, /* R1396 */
- { 0x0000, 0x0000, 0x0000 }, /* R1397 */
- { 0x0000, 0x0000, 0x0000 }, /* R1398 */
- { 0x0000, 0x0000, 0x0000 }, /* R1399 */
- { 0x0000, 0x0000, 0x0000 }, /* R1400 */
- { 0x0000, 0x0000, 0x0000 }, /* R1401 */
- { 0x0000, 0x0000, 0x0000 }, /* R1402 */
- { 0x0000, 0x0000, 0x0000 }, /* R1403 */
- { 0x0000, 0x0000, 0x0000 }, /* R1404 */
- { 0x0000, 0x0000, 0x0000 }, /* R1405 */
- { 0x0000, 0x0000, 0x0000 }, /* R1406 */
- { 0x0000, 0x0000, 0x0000 }, /* R1407 */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1408 - AIF2 EQ Gains (1) */
- { 0xFFC0, 0xFFC0, 0x0000 }, /* R1409 - AIF2 EQ Gains (2) */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1410 - AIF2 EQ Band 1 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1411 - AIF2 EQ Band 1 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1412 - AIF2 EQ Band 1 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1413 - AIF2 EQ Band 2 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1414 - AIF2 EQ Band 2 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1415 - AIF2 EQ Band 2 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1416 - AIF2 EQ Band 2 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1417 - AIF2 EQ Band 3 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1418 - AIF2 EQ Band 3 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1419 - AIF2 EQ Band 3 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1420 - AIF2 EQ Band 3 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1421 - AIF2 EQ Band 4 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1422 - AIF2 EQ Band 4 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1423 - AIF2 EQ Band 4 C */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1424 - AIF2 EQ Band 4 PG */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1425 - AIF2 EQ Band 5 A */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1426 - AIF2 EQ Band 5 B */
- { 0xFFFF, 0xFFFF, 0x0000 }, /* R1427 - AIF2 EQ Band 5 PG */
- { 0x0000, 0x0000, 0x0000 }, /* R1428 */
- { 0x0000, 0x0000, 0x0000 }, /* R1429 */
- { 0x0000, 0x0000, 0x0000 }, /* R1430 */
- { 0x0000, 0x0000, 0x0000 }, /* R1431 */
- { 0x0000, 0x0000, 0x0000 }, /* R1432 */
- { 0x0000, 0x0000, 0x0000 }, /* R1433 */
- { 0x0000, 0x0000, 0x0000 }, /* R1434 */
- { 0x0000, 0x0000, 0x0000 }, /* R1435 */
- { 0x0000, 0x0000, 0x0000 }, /* R1436 */
- { 0x0000, 0x0000, 0x0000 }, /* R1437 */
- { 0x0000, 0x0000, 0x0000 }, /* R1438 */
- { 0x0000, 0x0000, 0x0000 }, /* R1439 */
- { 0x0000, 0x0000, 0x0000 }, /* R1440 */
- { 0x0000, 0x0000, 0x0000 }, /* R1441 */
- { 0x0000, 0x0000, 0x0000 }, /* R1442 */
- { 0x0000, 0x0000, 0x0000 }, /* R1443 */
- { 0x0000, 0x0000, 0x0000 }, /* R1444 */
- { 0x0000, 0x0000, 0x0000 }, /* R1445 */
- { 0x0000, 0x0000, 0x0000 }, /* R1446 */
- { 0x0000, 0x0000, 0x0000 }, /* R1447 */
- { 0x0000, 0x0000, 0x0000 }, /* R1448 */
- { 0x0000, 0x0000, 0x0000 }, /* R1449 */
- { 0x0000, 0x0000, 0x0000 }, /* R1450 */
- { 0x0000, 0x0000, 0x0000 }, /* R1451 */
- { 0x0000, 0x0000, 0x0000 }, /* R1452 */
- { 0x0000, 0x0000, 0x0000 }, /* R1453 */
- { 0x0000, 0x0000, 0x0000 }, /* R1454 */
- { 0x0000, 0x0000, 0x0000 }, /* R1455 */
- { 0x0000, 0x0000, 0x0000 }, /* R1456 */
- { 0x0000, 0x0000, 0x0000 }, /* R1457 */
- { 0x0000, 0x0000, 0x0000 }, /* R1458 */
- { 0x0000, 0x0000, 0x0000 }, /* R1459 */
- { 0x0000, 0x0000, 0x0000 }, /* R1460 */
- { 0x0000, 0x0000, 0x0000 }, /* R1461 */
- { 0x0000, 0x0000, 0x0000 }, /* R1462 */
- { 0x0000, 0x0000, 0x0000 }, /* R1463 */
- { 0x0000, 0x0000, 0x0000 }, /* R1464 */
- { 0x0000, 0x0000, 0x0000 }, /* R1465 */
- { 0x0000, 0x0000, 0x0000 }, /* R1466 */
- { 0x0000, 0x0000, 0x0000 }, /* R1467 */
- { 0x0000, 0x0000, 0x0000 }, /* R1468 */
- { 0x0000, 0x0000, 0x0000 }, /* R1469 */
- { 0x0000, 0x0000, 0x0000 }, /* R1470 */
- { 0x0000, 0x0000, 0x0000 }, /* R1471 */
- { 0x0000, 0x0000, 0x0000 }, /* R1472 */
- { 0x0000, 0x0000, 0x0000 }, /* R1473 */
- { 0x0000, 0x0000, 0x0000 }, /* R1474 */
- { 0x0000, 0x0000, 0x0000 }, /* R1475 */
- { 0x0000, 0x0000, 0x0000 }, /* R1476 */
- { 0x0000, 0x0000, 0x0000 }, /* R1477 */
- { 0x0000, 0x0000, 0x0000 }, /* R1478 */
- { 0x0000, 0x0000, 0x0000 }, /* R1479 */
- { 0x0000, 0x0000, 0x0000 }, /* R1480 */
- { 0x0000, 0x0000, 0x0000 }, /* R1481 */
- { 0x0000, 0x0000, 0x0000 }, /* R1482 */
- { 0x0000, 0x0000, 0x0000 }, /* R1483 */
- { 0x0000, 0x0000, 0x0000 }, /* R1484 */
- { 0x0000, 0x0000, 0x0000 }, /* R1485 */
- { 0x0000, 0x0000, 0x0000 }, /* R1486 */
- { 0x0000, 0x0000, 0x0000 }, /* R1487 */
- { 0x0000, 0x0000, 0x0000 }, /* R1488 */
- { 0x0000, 0x0000, 0x0000 }, /* R1489 */
- { 0x0000, 0x0000, 0x0000 }, /* R1490 */
- { 0x0000, 0x0000, 0x0000 }, /* R1491 */
- { 0x0000, 0x0000, 0x0000 }, /* R1492 */
- { 0x0000, 0x0000, 0x0000 }, /* R1493 */
- { 0x0000, 0x0000, 0x0000 }, /* R1494 */
- { 0x0000, 0x0000, 0x0000 }, /* R1495 */
- { 0x0000, 0x0000, 0x0000 }, /* R1496 */
- { 0x0000, 0x0000, 0x0000 }, /* R1497 */
- { 0x0000, 0x0000, 0x0000 }, /* R1498 */
- { 0x0000, 0x0000, 0x0000 }, /* R1499 */
- { 0x0000, 0x0000, 0x0000 }, /* R1500 */
- { 0x0000, 0x0000, 0x0000 }, /* R1501 */
- { 0x0000, 0x0000, 0x0000 }, /* R1502 */
- { 0x0000, 0x0000, 0x0000 }, /* R1503 */
- { 0x0000, 0x0000, 0x0000 }, /* R1504 */
- { 0x0000, 0x0000, 0x0000 }, /* R1505 */
- { 0x0000, 0x0000, 0x0000 }, /* R1506 */
- { 0x0000, 0x0000, 0x0000 }, /* R1507 */
- { 0x0000, 0x0000, 0x0000 }, /* R1508 */
- { 0x0000, 0x0000, 0x0000 }, /* R1509 */
- { 0x0000, 0x0000, 0x0000 }, /* R1510 */
- { 0x0000, 0x0000, 0x0000 }, /* R1511 */
- { 0x0000, 0x0000, 0x0000 }, /* R1512 */
- { 0x0000, 0x0000, 0x0000 }, /* R1513 */
- { 0x0000, 0x0000, 0x0000 }, /* R1514 */
- { 0x0000, 0x0000, 0x0000 }, /* R1515 */
- { 0x0000, 0x0000, 0x0000 }, /* R1516 */
- { 0x0000, 0x0000, 0x0000 }, /* R1517 */
- { 0x0000, 0x0000, 0x0000 }, /* R1518 */
- { 0x0000, 0x0000, 0x0000 }, /* R1519 */
- { 0x0000, 0x0000, 0x0000 }, /* R1520 */
- { 0x0000, 0x0000, 0x0000 }, /* R1521 */
- { 0x0000, 0x0000, 0x0000 }, /* R1522 */
- { 0x0000, 0x0000, 0x0000 }, /* R1523 */
- { 0x0000, 0x0000, 0x0000 }, /* R1524 */
- { 0x0000, 0x0000, 0x0000 }, /* R1525 */
- { 0x0000, 0x0000, 0x0000 }, /* R1526 */
- { 0x0000, 0x0000, 0x0000 }, /* R1527 */
- { 0x0000, 0x0000, 0x0000 }, /* R1528 */
- { 0x0000, 0x0000, 0x0000 }, /* R1529 */
- { 0x0000, 0x0000, 0x0000 }, /* R1530 */
- { 0x0000, 0x0000, 0x0000 }, /* R1531 */
- { 0x0000, 0x0000, 0x0000 }, /* R1532 */
- { 0x0000, 0x0000, 0x0000 }, /* R1533 */
- { 0x0000, 0x0000, 0x0000 }, /* R1534 */
- { 0x0000, 0x0000, 0x0000 }, /* R1535 */
- { 0x01EF, 0x01EF, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */
- { 0x0037, 0x0037, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */
- { 0x0037, 0x0037, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */
- { 0x01EF, 0x01EF, 0x0000 }, /* R1539 - DAC2 Mixer Volumes */
- { 0x0037, 0x0037, 0x0000 }, /* R1540 - DAC2 Left Mixer Routing */
- { 0x0037, 0x0037, 0x0000 }, /* R1541 - DAC2 Right Mixer Routing */
- { 0x0003, 0x0003, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
- { 0x0003, 0x0003, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
- { 0x0003, 0x0003, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
- { 0x0003, 0x0003, 0x0000 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
- { 0x0000, 0x0000, 0x0000 }, /* R1546 */
- { 0x0000, 0x0000, 0x0000 }, /* R1547 */
- { 0x0000, 0x0000, 0x0000 }, /* R1548 */
- { 0x0000, 0x0000, 0x0000 }, /* R1549 */
- { 0x0000, 0x0000, 0x0000 }, /* R1550 */
- { 0x0000, 0x0000, 0x0000 }, /* R1551 */
- { 0x02FF, 0x03FF, 0x0000 }, /* R1552 - DAC1 Left Volume */
- { 0x02FF, 0x03FF, 0x0000 }, /* R1553 - DAC1 Right Volume */
- { 0x02FF, 0x03FF, 0x0000 }, /* R1554 - DAC2 Left Volume */
- { 0x02FF, 0x03FF, 0x0000 }, /* R1555 - DAC2 Right Volume */
- { 0x0003, 0x0003, 0x0000 }, /* R1556 - DAC Softmute */
- { 0x0000, 0x0000, 0x0000 }, /* R1557 */
- { 0x0000, 0x0000, 0x0000 }, /* R1558 */
- { 0x0000, 0x0000, 0x0000 }, /* R1559 */
- { 0x0000, 0x0000, 0x0000 }, /* R1560 */
- { 0x0000, 0x0000, 0x0000 }, /* R1561 */
- { 0x0000, 0x0000, 0x0000 }, /* R1562 */
- { 0x0000, 0x0000, 0x0000 }, /* R1563 */
- { 0x0000, 0x0000, 0x0000 }, /* R1564 */
- { 0x0000, 0x0000, 0x0000 }, /* R1565 */
- { 0x0000, 0x0000, 0x0000 }, /* R1566 */
- { 0x0000, 0x0000, 0x0000 }, /* R1567 */
- { 0x0003, 0x0003, 0x0000 }, /* R1568 - Oversampling */
- { 0x03C3, 0x03C3, 0x0000 }, /* R1569 - Sidetone */
+ { 0xFFFF, 0xFFFF }, /* R0 - Software Reset */
+ { 0x3B37, 0x3B37 }, /* R1 - Power Management (1) */
+ { 0x6BF0, 0x6BF0 }, /* R2 - Power Management (2) */
+ { 0x3FF0, 0x3FF0 }, /* R3 - Power Management (3) */
+ { 0x3F3F, 0x3F3F }, /* R4 - Power Management (4) */
+ { 0x3F0F, 0x3F0F }, /* R5 - Power Management (5) */
+ { 0x003F, 0x003F }, /* R6 - Power Management (6) */
+ { 0x0000, 0x0000 }, /* R7 */
+ { 0x0000, 0x0000 }, /* R8 */
+ { 0x0000, 0x0000 }, /* R9 */
+ { 0x0000, 0x0000 }, /* R10 */
+ { 0x0000, 0x0000 }, /* R11 */
+ { 0x0000, 0x0000 }, /* R12 */
+ { 0x0000, 0x0000 }, /* R13 */
+ { 0x0000, 0x0000 }, /* R14 */
+ { 0x0000, 0x0000 }, /* R15 */
+ { 0x0000, 0x0000 }, /* R16 */
+ { 0x0000, 0x0000 }, /* R17 */
+ { 0x0000, 0x0000 }, /* R18 */
+ { 0x0000, 0x0000 }, /* R19 */
+ { 0x0000, 0x0000 }, /* R20 */
+ { 0x01C0, 0x01C0 }, /* R21 - Input Mixer (1) */
+ { 0x0000, 0x0000 }, /* R22 */
+ { 0x0000, 0x0000 }, /* R23 */
+ { 0x00DF, 0x01DF }, /* R24 - Left Line Input 1&2 Volume */
+ { 0x00DF, 0x01DF }, /* R25 - Left Line Input 3&4 Volume */
+ { 0x00DF, 0x01DF }, /* R26 - Right Line Input 1&2 Volume */
+ { 0x00DF, 0x01DF }, /* R27 - Right Line Input 3&4 Volume */
+ { 0x00FF, 0x01FF }, /* R28 - Left Output Volume */
+ { 0x00FF, 0x01FF }, /* R29 - Right Output Volume */
+ { 0x0077, 0x0077 }, /* R30 - Line Outputs Volume */
+ { 0x0030, 0x0030 }, /* R31 - HPOUT2 Volume */
+ { 0x00FF, 0x01FF }, /* R32 - Left OPGA Volume */
+ { 0x00FF, 0x01FF }, /* R33 - Right OPGA Volume */
+ { 0x007F, 0x007F }, /* R34 - SPKMIXL Attenuation */
+ { 0x017F, 0x017F }, /* R35 - SPKMIXR Attenuation */
+ { 0x003F, 0x003F }, /* R36 - SPKOUT Mixers */
+ { 0x003F, 0x003F }, /* R37 - ClassD */
+ { 0x00FF, 0x01FF }, /* R38 - Speaker Volume Left */
+ { 0x00FF, 0x01FF }, /* R39 - Speaker Volume Right */
+ { 0x00FF, 0x00FF }, /* R40 - Input Mixer (2) */
+ { 0x01B7, 0x01B7 }, /* R41 - Input Mixer (3) */
+ { 0x01B7, 0x01B7 }, /* R42 - Input Mixer (4) */
+ { 0x01C7, 0x01C7 }, /* R43 - Input Mixer (5) */
+ { 0x01C7, 0x01C7 }, /* R44 - Input Mixer (6) */
+ { 0x01FF, 0x01FF }, /* R45 - Output Mixer (1) */
+ { 0x01FF, 0x01FF }, /* R46 - Output Mixer (2) */
+ { 0x0FFF, 0x0FFF }, /* R47 - Output Mixer (3) */
+ { 0x0FFF, 0x0FFF }, /* R48 - Output Mixer (4) */
+ { 0x0FFF, 0x0FFF }, /* R49 - Output Mixer (5) */
+ { 0x0FFF, 0x0FFF }, /* R50 - Output Mixer (6) */
+ { 0x0038, 0x0038 }, /* R51 - HPOUT2 Mixer */
+ { 0x0077, 0x0077 }, /* R52 - Line Mixer (1) */
+ { 0x0077, 0x0077 }, /* R53 - Line Mixer (2) */
+ { 0x03FF, 0x03FF }, /* R54 - Speaker Mixer */
+ { 0x00C1, 0x00C1 }, /* R55 - Additional Control */
+ { 0x00F0, 0x00F0 }, /* R56 - AntiPOP (1) */
+ { 0x01EF, 0x01EF }, /* R57 - AntiPOP (2) */
+ { 0x00FF, 0x00FF }, /* R58 - MICBIAS */
+ { 0x000F, 0x000F }, /* R59 - LDO 1 */
+ { 0x0007, 0x0007 }, /* R60 - LDO 2 */
+ { 0x0000, 0x0000 }, /* R61 */
+ { 0x0000, 0x0000 }, /* R62 */
+ { 0x0000, 0x0000 }, /* R63 */
+ { 0x0000, 0x0000 }, /* R64 */
+ { 0x0000, 0x0000 }, /* R65 */
+ { 0x0000, 0x0000 }, /* R66 */
+ { 0x0000, 0x0000 }, /* R67 */
+ { 0x0000, 0x0000 }, /* R68 */
+ { 0x0000, 0x0000 }, /* R69 */
+ { 0x0000, 0x0000 }, /* R70 */
+ { 0x0000, 0x0000 }, /* R71 */
+ { 0x0000, 0x0000 }, /* R72 */
+ { 0x0000, 0x0000 }, /* R73 */
+ { 0x0000, 0x0000 }, /* R74 */
+ { 0x0000, 0x0000 }, /* R75 */
+ { 0x8000, 0x8000 }, /* R76 - Charge Pump (1) */
+ { 0x0000, 0x0000 }, /* R77 */
+ { 0x0000, 0x0000 }, /* R78 */
+ { 0x0000, 0x0000 }, /* R79 */
+ { 0x0000, 0x0000 }, /* R80 */
+ { 0x0301, 0x0301 }, /* R81 - Class W (1) */
+ { 0x0000, 0x0000 }, /* R82 */
+ { 0x0000, 0x0000 }, /* R83 */
+ { 0x333F, 0x333F }, /* R84 - DC Servo (1) */
+ { 0x0FEF, 0x0FEF }, /* R85 - DC Servo (2) */
+ { 0x0000, 0x0000 }, /* R86 */
+ { 0xFFFF, 0xFFFF }, /* R87 - DC Servo (4) */
+ { 0x0333, 0x0000 }, /* R88 - DC Servo Readback */
+ { 0x0000, 0x0000 }, /* R89 */
+ { 0x0000, 0x0000 }, /* R90 */
+ { 0x0000, 0x0000 }, /* R91 */
+ { 0x0000, 0x0000 }, /* R92 */
+ { 0x0000, 0x0000 }, /* R93 */
+ { 0x0000, 0x0000 }, /* R94 */
+ { 0x0000, 0x0000 }, /* R95 */
+ { 0x00EE, 0x00EE }, /* R96 - Analogue HP (1) */
+ { 0x0000, 0x0000 }, /* R97 */
+ { 0x0000, 0x0000 }, /* R98 */
+ { 0x0000, 0x0000 }, /* R99 */
+ { 0x0000, 0x0000 }, /* R100 */
+ { 0x0000, 0x0000 }, /* R101 */
+ { 0x0000, 0x0000 }, /* R102 */
+ { 0x0000, 0x0000 }, /* R103 */
+ { 0x0000, 0x0000 }, /* R104 */
+ { 0x0000, 0x0000 }, /* R105 */
+ { 0x0000, 0x0000 }, /* R106 */
+ { 0x0000, 0x0000 }, /* R107 */
+ { 0x0000, 0x0000 }, /* R108 */
+ { 0x0000, 0x0000 }, /* R109 */
+ { 0x0000, 0x0000 }, /* R110 */
+ { 0x0000, 0x0000 }, /* R111 */
+ { 0x0000, 0x0000 }, /* R112 */
+ { 0x0000, 0x0000 }, /* R113 */
+ { 0x0000, 0x0000 }, /* R114 */
+ { 0x0000, 0x0000 }, /* R115 */
+ { 0x0000, 0x0000 }, /* R116 */
+ { 0x0000, 0x0000 }, /* R117 */
+ { 0x0000, 0x0000 }, /* R118 */
+ { 0x0000, 0x0000 }, /* R119 */
+ { 0x0000, 0x0000 }, /* R120 */
+ { 0x0000, 0x0000 }, /* R121 */
+ { 0x0000, 0x0000 }, /* R122 */
+ { 0x0000, 0x0000 }, /* R123 */
+ { 0x0000, 0x0000 }, /* R124 */
+ { 0x0000, 0x0000 }, /* R125 */
+ { 0x0000, 0x0000 }, /* R126 */
+ { 0x0000, 0x0000 }, /* R127 */
+ { 0x0000, 0x0000 }, /* R128 */
+ { 0x0000, 0x0000 }, /* R129 */
+ { 0x0000, 0x0000 }, /* R130 */
+ { 0x0000, 0x0000 }, /* R131 */
+ { 0x0000, 0x0000 }, /* R132 */
+ { 0x0000, 0x0000 }, /* R133 */
+ { 0x0000, 0x0000 }, /* R134 */
+ { 0x0000, 0x0000 }, /* R135 */
+ { 0x0000, 0x0000 }, /* R136 */
+ { 0x0000, 0x0000 }, /* R137 */
+ { 0x0000, 0x0000 }, /* R138 */
+ { 0x0000, 0x0000 }, /* R139 */
+ { 0x0000, 0x0000 }, /* R140 */
+ { 0x0000, 0x0000 }, /* R141 */
+ { 0x0000, 0x0000 }, /* R142 */
+ { 0x0000, 0x0000 }, /* R143 */
+ { 0x0000, 0x0000 }, /* R144 */
+ { 0x0000, 0x0000 }, /* R145 */
+ { 0x0000, 0x0000 }, /* R146 */
+ { 0x0000, 0x0000 }, /* R147 */
+ { 0x0000, 0x0000 }, /* R148 */
+ { 0x0000, 0x0000 }, /* R149 */
+ { 0x0000, 0x0000 }, /* R150 */
+ { 0x0000, 0x0000 }, /* R151 */
+ { 0x0000, 0x0000 }, /* R152 */
+ { 0x0000, 0x0000 }, /* R153 */
+ { 0x0000, 0x0000 }, /* R154 */
+ { 0x0000, 0x0000 }, /* R155 */
+ { 0x0000, 0x0000 }, /* R156 */
+ { 0x0000, 0x0000 }, /* R157 */
+ { 0x0000, 0x0000 }, /* R158 */
+ { 0x0000, 0x0000 }, /* R159 */
+ { 0x0000, 0x0000 }, /* R160 */
+ { 0x0000, 0x0000 }, /* R161 */
+ { 0x0000, 0x0000 }, /* R162 */
+ { 0x0000, 0x0000 }, /* R163 */
+ { 0x0000, 0x0000 }, /* R164 */
+ { 0x0000, 0x0000 }, /* R165 */
+ { 0x0000, 0x0000 }, /* R166 */
+ { 0x0000, 0x0000 }, /* R167 */
+ { 0x0000, 0x0000 }, /* R168 */
+ { 0x0000, 0x0000 }, /* R169 */
+ { 0x0000, 0x0000 }, /* R170 */
+ { 0x0000, 0x0000 }, /* R171 */
+ { 0x0000, 0x0000 }, /* R172 */
+ { 0x0000, 0x0000 }, /* R173 */
+ { 0x0000, 0x0000 }, /* R174 */
+ { 0x0000, 0x0000 }, /* R175 */
+ { 0x0000, 0x0000 }, /* R176 */
+ { 0x0000, 0x0000 }, /* R177 */
+ { 0x0000, 0x0000 }, /* R178 */
+ { 0x0000, 0x0000 }, /* R179 */
+ { 0x0000, 0x0000 }, /* R180 */
+ { 0x0000, 0x0000 }, /* R181 */
+ { 0x0000, 0x0000 }, /* R182 */
+ { 0x0000, 0x0000 }, /* R183 */
+ { 0x0000, 0x0000 }, /* R184 */
+ { 0x0000, 0x0000 }, /* R185 */
+ { 0x0000, 0x0000 }, /* R186 */
+ { 0x0000, 0x0000 }, /* R187 */
+ { 0x0000, 0x0000 }, /* R188 */
+ { 0x0000, 0x0000 }, /* R189 */
+ { 0x0000, 0x0000 }, /* R190 */
+ { 0x0000, 0x0000 }, /* R191 */
+ { 0x0000, 0x0000 }, /* R192 */
+ { 0x0000, 0x0000 }, /* R193 */
+ { 0x0000, 0x0000 }, /* R194 */
+ { 0x0000, 0x0000 }, /* R195 */
+ { 0x0000, 0x0000 }, /* R196 */
+ { 0x0000, 0x0000 }, /* R197 */
+ { 0x0000, 0x0000 }, /* R198 */
+ { 0x0000, 0x0000 }, /* R199 */
+ { 0x0000, 0x0000 }, /* R200 */
+ { 0x0000, 0x0000 }, /* R201 */
+ { 0x0000, 0x0000 }, /* R202 */
+ { 0x0000, 0x0000 }, /* R203 */
+ { 0x0000, 0x0000 }, /* R204 */
+ { 0x0000, 0x0000 }, /* R205 */
+ { 0x0000, 0x0000 }, /* R206 */
+ { 0x0000, 0x0000 }, /* R207 */
+ { 0x0000, 0x0000 }, /* R208 */
+ { 0x0000, 0x0000 }, /* R209 */
+ { 0x0000, 0x0000 }, /* R210 */
+ { 0x0000, 0x0000 }, /* R211 */
+ { 0x0000, 0x0000 }, /* R212 */
+ { 0x0000, 0x0000 }, /* R213 */
+ { 0x0000, 0x0000 }, /* R214 */
+ { 0x0000, 0x0000 }, /* R215 */
+ { 0x0000, 0x0000 }, /* R216 */
+ { 0x0000, 0x0000 }, /* R217 */
+ { 0x0000, 0x0000 }, /* R218 */
+ { 0x0000, 0x0000 }, /* R219 */
+ { 0x0000, 0x0000 }, /* R220 */
+ { 0x0000, 0x0000 }, /* R221 */
+ { 0x0000, 0x0000 }, /* R222 */
+ { 0x0000, 0x0000 }, /* R223 */
+ { 0x0000, 0x0000 }, /* R224 */
+ { 0x0000, 0x0000 }, /* R225 */
+ { 0x0000, 0x0000 }, /* R226 */
+ { 0x0000, 0x0000 }, /* R227 */
+ { 0x0000, 0x0000 }, /* R228 */
+ { 0x0000, 0x0000 }, /* R229 */
+ { 0x0000, 0x0000 }, /* R230 */
+ { 0x0000, 0x0000 }, /* R231 */
+ { 0x0000, 0x0000 }, /* R232 */
+ { 0x0000, 0x0000 }, /* R233 */
+ { 0x0000, 0x0000 }, /* R234 */
+ { 0x0000, 0x0000 }, /* R235 */
+ { 0x0000, 0x0000 }, /* R236 */
+ { 0x0000, 0x0000 }, /* R237 */
+ { 0x0000, 0x0000 }, /* R238 */
+ { 0x0000, 0x0000 }, /* R239 */
+ { 0x0000, 0x0000 }, /* R240 */
+ { 0x0000, 0x0000 }, /* R241 */
+ { 0x0000, 0x0000 }, /* R242 */
+ { 0x0000, 0x0000 }, /* R243 */
+ { 0x0000, 0x0000 }, /* R244 */
+ { 0x0000, 0x0000 }, /* R245 */
+ { 0x0000, 0x0000 }, /* R246 */
+ { 0x0000, 0x0000 }, /* R247 */
+ { 0x0000, 0x0000 }, /* R248 */
+ { 0x0000, 0x0000 }, /* R249 */
+ { 0x0000, 0x0000 }, /* R250 */
+ { 0x0000, 0x0000 }, /* R251 */
+ { 0x0000, 0x0000 }, /* R252 */
+ { 0x0000, 0x0000 }, /* R253 */
+ { 0x0000, 0x0000 }, /* R254 */
+ { 0x0000, 0x0000 }, /* R255 */
+ { 0x000F, 0x0000 }, /* R256 - Chip Revision */
+ { 0x0074, 0x0074 }, /* R257 - Control Interface */
+ { 0x0000, 0x0000 }, /* R258 */
+ { 0x0000, 0x0000 }, /* R259 */
+ { 0x0000, 0x0000 }, /* R260 */
+ { 0x0000, 0x0000 }, /* R261 */
+ { 0x0000, 0x0000 }, /* R262 */
+ { 0x0000, 0x0000 }, /* R263 */
+ { 0x0000, 0x0000 }, /* R264 */
+ { 0x0000, 0x0000 }, /* R265 */
+ { 0x0000, 0x0000 }, /* R266 */
+ { 0x0000, 0x0000 }, /* R267 */
+ { 0x0000, 0x0000 }, /* R268 */
+ { 0x0000, 0x0000 }, /* R269 */
+ { 0x0000, 0x0000 }, /* R270 */
+ { 0x0000, 0x0000 }, /* R271 */
+ { 0x807F, 0x837F }, /* R272 - Write Sequencer Ctrl (1) */
+ { 0x017F, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
+ { 0x0000, 0x0000 }, /* R274 */
+ { 0x0000, 0x0000 }, /* R275 */
+ { 0x0000, 0x0000 }, /* R276 */
+ { 0x0000, 0x0000 }, /* R277 */
+ { 0x0000, 0x0000 }, /* R278 */
+ { 0x0000, 0x0000 }, /* R279 */
+ { 0x0000, 0x0000 }, /* R280 */
+ { 0x0000, 0x0000 }, /* R281 */
+ { 0x0000, 0x0000 }, /* R282 */
+ { 0x0000, 0x0000 }, /* R283 */
+ { 0x0000, 0x0000 }, /* R284 */
+ { 0x0000, 0x0000 }, /* R285 */
+ { 0x0000, 0x0000 }, /* R286 */
+ { 0x0000, 0x0000 }, /* R287 */
+ { 0x0000, 0x0000 }, /* R288 */
+ { 0x0000, 0x0000 }, /* R289 */
+ { 0x0000, 0x0000 }, /* R290 */
+ { 0x0000, 0x0000 }, /* R291 */
+ { 0x0000, 0x0000 }, /* R292 */
+ { 0x0000, 0x0000 }, /* R293 */
+ { 0x0000, 0x0000 }, /* R294 */
+ { 0x0000, 0x0000 }, /* R295 */
+ { 0x0000, 0x0000 }, /* R296 */
+ { 0x0000, 0x0000 }, /* R297 */
+ { 0x0000, 0x0000 }, /* R298 */
+ { 0x0000, 0x0000 }, /* R299 */
+ { 0x0000, 0x0000 }, /* R300 */
+ { 0x0000, 0x0000 }, /* R301 */
+ { 0x0000, 0x0000 }, /* R302 */
+ { 0x0000, 0x0000 }, /* R303 */
+ { 0x0000, 0x0000 }, /* R304 */
+ { 0x0000, 0x0000 }, /* R305 */
+ { 0x0000, 0x0000 }, /* R306 */
+ { 0x0000, 0x0000 }, /* R307 */
+ { 0x0000, 0x0000 }, /* R308 */
+ { 0x0000, 0x0000 }, /* R309 */
+ { 0x0000, 0x0000 }, /* R310 */
+ { 0x0000, 0x0000 }, /* R311 */
+ { 0x0000, 0x0000 }, /* R312 */
+ { 0x0000, 0x0000 }, /* R313 */
+ { 0x0000, 0x0000 }, /* R314 */
+ { 0x0000, 0x0000 }, /* R315 */
+ { 0x0000, 0x0000 }, /* R316 */
+ { 0x0000, 0x0000 }, /* R317 */
+ { 0x0000, 0x0000 }, /* R318 */
+ { 0x0000, 0x0000 }, /* R319 */
+ { 0x0000, 0x0000 }, /* R320 */
+ { 0x0000, 0x0000 }, /* R321 */
+ { 0x0000, 0x0000 }, /* R322 */
+ { 0x0000, 0x0000 }, /* R323 */
+ { 0x0000, 0x0000 }, /* R324 */
+ { 0x0000, 0x0000 }, /* R325 */
+ { 0x0000, 0x0000 }, /* R326 */
+ { 0x0000, 0x0000 }, /* R327 */
+ { 0x0000, 0x0000 }, /* R328 */
+ { 0x0000, 0x0000 }, /* R329 */
+ { 0x0000, 0x0000 }, /* R330 */
+ { 0x0000, 0x0000 }, /* R331 */
+ { 0x0000, 0x0000 }, /* R332 */
+ { 0x0000, 0x0000 }, /* R333 */
+ { 0x0000, 0x0000 }, /* R334 */
+ { 0x0000, 0x0000 }, /* R335 */
+ { 0x0000, 0x0000 }, /* R336 */
+ { 0x0000, 0x0000 }, /* R337 */
+ { 0x0000, 0x0000 }, /* R338 */
+ { 0x0000, 0x0000 }, /* R339 */
+ { 0x0000, 0x0000 }, /* R340 */
+ { 0x0000, 0x0000 }, /* R341 */
+ { 0x0000, 0x0000 }, /* R342 */
+ { 0x0000, 0x0000 }, /* R343 */
+ { 0x0000, 0x0000 }, /* R344 */
+ { 0x0000, 0x0000 }, /* R345 */
+ { 0x0000, 0x0000 }, /* R346 */
+ { 0x0000, 0x0000 }, /* R347 */
+ { 0x0000, 0x0000 }, /* R348 */
+ { 0x0000, 0x0000 }, /* R349 */
+ { 0x0000, 0x0000 }, /* R350 */
+ { 0x0000, 0x0000 }, /* R351 */
+ { 0x0000, 0x0000 }, /* R352 */
+ { 0x0000, 0x0000 }, /* R353 */
+ { 0x0000, 0x0000 }, /* R354 */
+ { 0x0000, 0x0000 }, /* R355 */
+ { 0x0000, 0x0000 }, /* R356 */
+ { 0x0000, 0x0000 }, /* R357 */
+ { 0x0000, 0x0000 }, /* R358 */
+ { 0x0000, 0x0000 }, /* R359 */
+ { 0x0000, 0x0000 }, /* R360 */
+ { 0x0000, 0x0000 }, /* R361 */
+ { 0x0000, 0x0000 }, /* R362 */
+ { 0x0000, 0x0000 }, /* R363 */
+ { 0x0000, 0x0000 }, /* R364 */
+ { 0x0000, 0x0000 }, /* R365 */
+ { 0x0000, 0x0000 }, /* R366 */
+ { 0x0000, 0x0000 }, /* R367 */
+ { 0x0000, 0x0000 }, /* R368 */
+ { 0x0000, 0x0000 }, /* R369 */
+ { 0x0000, 0x0000 }, /* R370 */
+ { 0x0000, 0x0000 }, /* R371 */
+ { 0x0000, 0x0000 }, /* R372 */
+ { 0x0000, 0x0000 }, /* R373 */
+ { 0x0000, 0x0000 }, /* R374 */
+ { 0x0000, 0x0000 }, /* R375 */
+ { 0x0000, 0x0000 }, /* R376 */
+ { 0x0000, 0x0000 }, /* R377 */
+ { 0x0000, 0x0000 }, /* R378 */
+ { 0x0000, 0x0000 }, /* R379 */
+ { 0x0000, 0x0000 }, /* R380 */
+ { 0x0000, 0x0000 }, /* R381 */
+ { 0x0000, 0x0000 }, /* R382 */
+ { 0x0000, 0x0000 }, /* R383 */
+ { 0x0000, 0x0000 }, /* R384 */
+ { 0x0000, 0x0000 }, /* R385 */
+ { 0x0000, 0x0000 }, /* R386 */
+ { 0x0000, 0x0000 }, /* R387 */
+ { 0x0000, 0x0000 }, /* R388 */
+ { 0x0000, 0x0000 }, /* R389 */
+ { 0x0000, 0x0000 }, /* R390 */
+ { 0x0000, 0x0000 }, /* R391 */
+ { 0x0000, 0x0000 }, /* R392 */
+ { 0x0000, 0x0000 }, /* R393 */
+ { 0x0000, 0x0000 }, /* R394 */
+ { 0x0000, 0x0000 }, /* R395 */
+ { 0x0000, 0x0000 }, /* R396 */
+ { 0x0000, 0x0000 }, /* R397 */
+ { 0x0000, 0x0000 }, /* R398 */
+ { 0x0000, 0x0000 }, /* R399 */
+ { 0x0000, 0x0000 }, /* R400 */
+ { 0x0000, 0x0000 }, /* R401 */
+ { 0x0000, 0x0000 }, /* R402 */
+ { 0x0000, 0x0000 }, /* R403 */
+ { 0x0000, 0x0000 }, /* R404 */
+ { 0x0000, 0x0000 }, /* R405 */
+ { 0x0000, 0x0000 }, /* R406 */
+ { 0x0000, 0x0000 }, /* R407 */
+ { 0x0000, 0x0000 }, /* R408 */
+ { 0x0000, 0x0000 }, /* R409 */
+ { 0x0000, 0x0000 }, /* R410 */
+ { 0x0000, 0x0000 }, /* R411 */
+ { 0x0000, 0x0000 }, /* R412 */
+ { 0x0000, 0x0000 }, /* R413 */
+ { 0x0000, 0x0000 }, /* R414 */
+ { 0x0000, 0x0000 }, /* R415 */
+ { 0x0000, 0x0000 }, /* R416 */
+ { 0x0000, 0x0000 }, /* R417 */
+ { 0x0000, 0x0000 }, /* R418 */
+ { 0x0000, 0x0000 }, /* R419 */
+ { 0x0000, 0x0000 }, /* R420 */
+ { 0x0000, 0x0000 }, /* R421 */
+ { 0x0000, 0x0000 }, /* R422 */
+ { 0x0000, 0x0000 }, /* R423 */
+ { 0x0000, 0x0000 }, /* R424 */
+ { 0x0000, 0x0000 }, /* R425 */
+ { 0x0000, 0x0000 }, /* R426 */
+ { 0x0000, 0x0000 }, /* R427 */
+ { 0x0000, 0x0000 }, /* R428 */
+ { 0x0000, 0x0000 }, /* R429 */
+ { 0x0000, 0x0000 }, /* R430 */
+ { 0x0000, 0x0000 }, /* R431 */
+ { 0x0000, 0x0000 }, /* R432 */
+ { 0x0000, 0x0000 }, /* R433 */
+ { 0x0000, 0x0000 }, /* R434 */
+ { 0x0000, 0x0000 }, /* R435 */
+ { 0x0000, 0x0000 }, /* R436 */
+ { 0x0000, 0x0000 }, /* R437 */
+ { 0x0000, 0x0000 }, /* R438 */
+ { 0x0000, 0x0000 }, /* R439 */
+ { 0x0000, 0x0000 }, /* R440 */
+ { 0x0000, 0x0000 }, /* R441 */
+ { 0x0000, 0x0000 }, /* R442 */
+ { 0x0000, 0x0000 }, /* R443 */
+ { 0x0000, 0x0000 }, /* R444 */
+ { 0x0000, 0x0000 }, /* R445 */
+ { 0x0000, 0x0000 }, /* R446 */
+ { 0x0000, 0x0000 }, /* R447 */
+ { 0x0000, 0x0000 }, /* R448 */
+ { 0x0000, 0x0000 }, /* R449 */
+ { 0x0000, 0x0000 }, /* R450 */
+ { 0x0000, 0x0000 }, /* R451 */
+ { 0x0000, 0x0000 }, /* R452 */
+ { 0x0000, 0x0000 }, /* R453 */
+ { 0x0000, 0x0000 }, /* R454 */
+ { 0x0000, 0x0000 }, /* R455 */
+ { 0x0000, 0x0000 }, /* R456 */
+ { 0x0000, 0x0000 }, /* R457 */
+ { 0x0000, 0x0000 }, /* R458 */
+ { 0x0000, 0x0000 }, /* R459 */
+ { 0x0000, 0x0000 }, /* R460 */
+ { 0x0000, 0x0000 }, /* R461 */
+ { 0x0000, 0x0000 }, /* R462 */
+ { 0x0000, 0x0000 }, /* R463 */
+ { 0x0000, 0x0000 }, /* R464 */
+ { 0x0000, 0x0000 }, /* R465 */
+ { 0x0000, 0x0000 }, /* R466 */
+ { 0x0000, 0x0000 }, /* R467 */
+ { 0x0000, 0x0000 }, /* R468 */
+ { 0x0000, 0x0000 }, /* R469 */
+ { 0x0000, 0x0000 }, /* R470 */
+ { 0x0000, 0x0000 }, /* R471 */
+ { 0x0000, 0x0000 }, /* R472 */
+ { 0x0000, 0x0000 }, /* R473 */
+ { 0x0000, 0x0000 }, /* R474 */
+ { 0x0000, 0x0000 }, /* R475 */
+ { 0x0000, 0x0000 }, /* R476 */
+ { 0x0000, 0x0000 }, /* R477 */
+ { 0x0000, 0x0000 }, /* R478 */
+ { 0x0000, 0x0000 }, /* R479 */
+ { 0x0000, 0x0000 }, /* R480 */
+ { 0x0000, 0x0000 }, /* R481 */
+ { 0x0000, 0x0000 }, /* R482 */
+ { 0x0000, 0x0000 }, /* R483 */
+ { 0x0000, 0x0000 }, /* R484 */
+ { 0x0000, 0x0000 }, /* R485 */
+ { 0x0000, 0x0000 }, /* R486 */
+ { 0x0000, 0x0000 }, /* R487 */
+ { 0x0000, 0x0000 }, /* R488 */
+ { 0x0000, 0x0000 }, /* R489 */
+ { 0x0000, 0x0000 }, /* R490 */
+ { 0x0000, 0x0000 }, /* R491 */
+ { 0x0000, 0x0000 }, /* R492 */
+ { 0x0000, 0x0000 }, /* R493 */
+ { 0x0000, 0x0000 }, /* R494 */
+ { 0x0000, 0x0000 }, /* R495 */
+ { 0x0000, 0x0000 }, /* R496 */
+ { 0x0000, 0x0000 }, /* R497 */
+ { 0x0000, 0x0000 }, /* R498 */
+ { 0x0000, 0x0000 }, /* R499 */
+ { 0x0000, 0x0000 }, /* R500 */
+ { 0x0000, 0x0000 }, /* R501 */
+ { 0x0000, 0x0000 }, /* R502 */
+ { 0x0000, 0x0000 }, /* R503 */
+ { 0x0000, 0x0000 }, /* R504 */
+ { 0x0000, 0x0000 }, /* R505 */
+ { 0x0000, 0x0000 }, /* R506 */
+ { 0x0000, 0x0000 }, /* R507 */
+ { 0x0000, 0x0000 }, /* R508 */
+ { 0x0000, 0x0000 }, /* R509 */
+ { 0x0000, 0x0000 }, /* R510 */
+ { 0x0000, 0x0000 }, /* R511 */
+ { 0x001F, 0x001F }, /* R512 - AIF1 Clocking (1) */
+ { 0x003F, 0x003F }, /* R513 - AIF1 Clocking (2) */
+ { 0x0000, 0x0000 }, /* R514 */
+ { 0x0000, 0x0000 }, /* R515 */
+ { 0x001F, 0x001F }, /* R516 - AIF2 Clocking (1) */
+ { 0x003F, 0x003F }, /* R517 - AIF2 Clocking (2) */
+ { 0x0000, 0x0000 }, /* R518 */
+ { 0x0000, 0x0000 }, /* R519 */
+ { 0x001F, 0x001F }, /* R520 - Clocking (1) */
+ { 0x0777, 0x0777 }, /* R521 - Clocking (2) */
+ { 0x0000, 0x0000 }, /* R522 */
+ { 0x0000, 0x0000 }, /* R523 */
+ { 0x0000, 0x0000 }, /* R524 */
+ { 0x0000, 0x0000 }, /* R525 */
+ { 0x0000, 0x0000 }, /* R526 */
+ { 0x0000, 0x0000 }, /* R527 */
+ { 0x00FF, 0x00FF }, /* R528 - AIF1 Rate */
+ { 0x00FF, 0x00FF }, /* R529 - AIF2 Rate */
+ { 0x000F, 0x0000 }, /* R530 - Rate Status */
+ { 0x0000, 0x0000 }, /* R531 */
+ { 0x0000, 0x0000 }, /* R532 */
+ { 0x0000, 0x0000 }, /* R533 */
+ { 0x0000, 0x0000 }, /* R534 */
+ { 0x0000, 0x0000 }, /* R535 */
+ { 0x0000, 0x0000 }, /* R536 */
+ { 0x0000, 0x0000 }, /* R537 */
+ { 0x0000, 0x0000 }, /* R538 */
+ { 0x0000, 0x0000 }, /* R539 */
+ { 0x0000, 0x0000 }, /* R540 */
+ { 0x0000, 0x0000 }, /* R541 */
+ { 0x0000, 0x0000 }, /* R542 */
+ { 0x0000, 0x0000 }, /* R543 */
+ { 0x0007, 0x0007 }, /* R544 - FLL1 Control (1) */
+ { 0x3F77, 0x3F77 }, /* R545 - FLL1 Control (2) */
+ { 0xFFFF, 0xFFFF }, /* R546 - FLL1 Control (3) */
+ { 0x7FEF, 0x7FEF }, /* R547 - FLL1 Control (4) */
+ { 0x1FDB, 0x1FDB }, /* R548 - FLL1 Control (5) */
+ { 0x0000, 0x0000 }, /* R549 */
+ { 0x0000, 0x0000 }, /* R550 */
+ { 0x0000, 0x0000 }, /* R551 */
+ { 0x0000, 0x0000 }, /* R552 */
+ { 0x0000, 0x0000 }, /* R553 */
+ { 0x0000, 0x0000 }, /* R554 */
+ { 0x0000, 0x0000 }, /* R555 */
+ { 0x0000, 0x0000 }, /* R556 */
+ { 0x0000, 0x0000 }, /* R557 */
+ { 0x0000, 0x0000 }, /* R558 */
+ { 0x0000, 0x0000 }, /* R559 */
+ { 0x0000, 0x0000 }, /* R560 */
+ { 0x0000, 0x0000 }, /* R561 */
+ { 0x0000, 0x0000 }, /* R562 */
+ { 0x0000, 0x0000 }, /* R563 */
+ { 0x0000, 0x0000 }, /* R564 */
+ { 0x0000, 0x0000 }, /* R565 */
+ { 0x0000, 0x0000 }, /* R566 */
+ { 0x0000, 0x0000 }, /* R567 */
+ { 0x0000, 0x0000 }, /* R568 */
+ { 0x0000, 0x0000 }, /* R569 */
+ { 0x0000, 0x0000 }, /* R570 */
+ { 0x0000, 0x0000 }, /* R571 */
+ { 0x0000, 0x0000 }, /* R572 */
+ { 0x0000, 0x0000 }, /* R573 */
+ { 0x0000, 0x0000 }, /* R574 */
+ { 0x0000, 0x0000 }, /* R575 */
+ { 0x0007, 0x0007 }, /* R576 - FLL2 Control (1) */
+ { 0x3F77, 0x3F77 }, /* R577 - FLL2 Control (2) */
+ { 0xFFFF, 0xFFFF }, /* R578 - FLL2 Control (3) */
+ { 0x7FEF, 0x7FEF }, /* R579 - FLL2 Control (4) */
+ { 0x1FDB, 0x1FDB }, /* R580 - FLL2 Control (5) */
+ { 0x0000, 0x0000 }, /* R581 */
+ { 0x0000, 0x0000 }, /* R582 */
+ { 0x0000, 0x0000 }, /* R583 */
+ { 0x0000, 0x0000 }, /* R584 */
+ { 0x0000, 0x0000 }, /* R585 */
+ { 0x0000, 0x0000 }, /* R586 */
+ { 0x0000, 0x0000 }, /* R587 */
+ { 0x0000, 0x0000 }, /* R588 */
+ { 0x0000, 0x0000 }, /* R589 */
+ { 0x0000, 0x0000 }, /* R590 */
+ { 0x0000, 0x0000 }, /* R591 */
+ { 0x0000, 0x0000 }, /* R592 */
+ { 0x0000, 0x0000 }, /* R593 */
+ { 0x0000, 0x0000 }, /* R594 */
+ { 0x0000, 0x0000 }, /* R595 */
+ { 0x0000, 0x0000 }, /* R596 */
+ { 0x0000, 0x0000 }, /* R597 */
+ { 0x0000, 0x0000 }, /* R598 */
+ { 0x0000, 0x0000 }, /* R599 */
+ { 0x0000, 0x0000 }, /* R600 */
+ { 0x0000, 0x0000 }, /* R601 */
+ { 0x0000, 0x0000 }, /* R602 */
+ { 0x0000, 0x0000 }, /* R603 */
+ { 0x0000, 0x0000 }, /* R604 */
+ { 0x0000, 0x0000 }, /* R605 */
+ { 0x0000, 0x0000 }, /* R606 */
+ { 0x0000, 0x0000 }, /* R607 */
+ { 0x0000, 0x0000 }, /* R608 */
+ { 0x0000, 0x0000 }, /* R609 */
+ { 0x0000, 0x0000 }, /* R610 */
+ { 0x0000, 0x0000 }, /* R611 */
+ { 0x0000, 0x0000 }, /* R612 */
+ { 0x0000, 0x0000 }, /* R613 */
+ { 0x0000, 0x0000 }, /* R614 */
+ { 0x0000, 0x0000 }, /* R615 */
+ { 0x0000, 0x0000 }, /* R616 */
+ { 0x0000, 0x0000 }, /* R617 */
+ { 0x0000, 0x0000 }, /* R618 */
+ { 0x0000, 0x0000 }, /* R619 */
+ { 0x0000, 0x0000 }, /* R620 */
+ { 0x0000, 0x0000 }, /* R621 */
+ { 0x0000, 0x0000 }, /* R622 */
+ { 0x0000, 0x0000 }, /* R623 */
+ { 0x0000, 0x0000 }, /* R624 */
+ { 0x0000, 0x0000 }, /* R625 */
+ { 0x0000, 0x0000 }, /* R626 */
+ { 0x0000, 0x0000 }, /* R627 */
+ { 0x0000, 0x0000 }, /* R628 */
+ { 0x0000, 0x0000 }, /* R629 */
+ { 0x0000, 0x0000 }, /* R630 */
+ { 0x0000, 0x0000 }, /* R631 */
+ { 0x0000, 0x0000 }, /* R632 */
+ { 0x0000, 0x0000 }, /* R633 */
+ { 0x0000, 0x0000 }, /* R634 */
+ { 0x0000, 0x0000 }, /* R635 */
+ { 0x0000, 0x0000 }, /* R636 */
+ { 0x0000, 0x0000 }, /* R637 */
+ { 0x0000, 0x0000 }, /* R638 */
+ { 0x0000, 0x0000 }, /* R639 */
+ { 0x0000, 0x0000 }, /* R640 */
+ { 0x0000, 0x0000 }, /* R641 */
+ { 0x0000, 0x0000 }, /* R642 */
+ { 0x0000, 0x0000 }, /* R643 */
+ { 0x0000, 0x0000 }, /* R644 */
+ { 0x0000, 0x0000 }, /* R645 */
+ { 0x0000, 0x0000 }, /* R646 */
+ { 0x0000, 0x0000 }, /* R647 */
+ { 0x0000, 0x0000 }, /* R648 */
+ { 0x0000, 0x0000 }, /* R649 */
+ { 0x0000, 0x0000 }, /* R650 */
+ { 0x0000, 0x0000 }, /* R651 */
+ { 0x0000, 0x0000 }, /* R652 */
+ { 0x0000, 0x0000 }, /* R653 */
+ { 0x0000, 0x0000 }, /* R654 */
+ { 0x0000, 0x0000 }, /* R655 */
+ { 0x0000, 0x0000 }, /* R656 */
+ { 0x0000, 0x0000 }, /* R657 */
+ { 0x0000, 0x0000 }, /* R658 */
+ { 0x0000, 0x0000 }, /* R659 */
+ { 0x0000, 0x0000 }, /* R660 */
+ { 0x0000, 0x0000 }, /* R661 */
+ { 0x0000, 0x0000 }, /* R662 */
+ { 0x0000, 0x0000 }, /* R663 */
+ { 0x0000, 0x0000 }, /* R664 */
+ { 0x0000, 0x0000 }, /* R665 */
+ { 0x0000, 0x0000 }, /* R666 */
+ { 0x0000, 0x0000 }, /* R667 */
+ { 0x0000, 0x0000 }, /* R668 */
+ { 0x0000, 0x0000 }, /* R669 */
+ { 0x0000, 0x0000 }, /* R670 */
+ { 0x0000, 0x0000 }, /* R671 */
+ { 0x0000, 0x0000 }, /* R672 */
+ { 0x0000, 0x0000 }, /* R673 */
+ { 0x0000, 0x0000 }, /* R674 */
+ { 0x0000, 0x0000 }, /* R675 */
+ { 0x0000, 0x0000 }, /* R676 */
+ { 0x0000, 0x0000 }, /* R677 */
+ { 0x0000, 0x0000 }, /* R678 */
+ { 0x0000, 0x0000 }, /* R679 */
+ { 0x0000, 0x0000 }, /* R680 */
+ { 0x0000, 0x0000 }, /* R681 */
+ { 0x0000, 0x0000 }, /* R682 */
+ { 0x0000, 0x0000 }, /* R683 */
+ { 0x0000, 0x0000 }, /* R684 */
+ { 0x0000, 0x0000 }, /* R685 */
+ { 0x0000, 0x0000 }, /* R686 */
+ { 0x0000, 0x0000 }, /* R687 */
+ { 0x0000, 0x0000 }, /* R688 */
+ { 0x0000, 0x0000 }, /* R689 */
+ { 0x0000, 0x0000 }, /* R690 */
+ { 0x0000, 0x0000 }, /* R691 */
+ { 0x0000, 0x0000 }, /* R692 */
+ { 0x0000, 0x0000 }, /* R693 */
+ { 0x0000, 0x0000 }, /* R694 */
+ { 0x0000, 0x0000 }, /* R695 */
+ { 0x0000, 0x0000 }, /* R696 */
+ { 0x0000, 0x0000 }, /* R697 */
+ { 0x0000, 0x0000 }, /* R698 */
+ { 0x0000, 0x0000 }, /* R699 */
+ { 0x0000, 0x0000 }, /* R700 */
+ { 0x0000, 0x0000 }, /* R701 */
+ { 0x0000, 0x0000 }, /* R702 */
+ { 0x0000, 0x0000 }, /* R703 */
+ { 0x0000, 0x0000 }, /* R704 */
+ { 0x0000, 0x0000 }, /* R705 */
+ { 0x0000, 0x0000 }, /* R706 */
+ { 0x0000, 0x0000 }, /* R707 */
+ { 0x0000, 0x0000 }, /* R708 */
+ { 0x0000, 0x0000 }, /* R709 */
+ { 0x0000, 0x0000 }, /* R710 */
+ { 0x0000, 0x0000 }, /* R711 */
+ { 0x0000, 0x0000 }, /* R712 */
+ { 0x0000, 0x0000 }, /* R713 */
+ { 0x0000, 0x0000 }, /* R714 */
+ { 0x0000, 0x0000 }, /* R715 */
+ { 0x0000, 0x0000 }, /* R716 */
+ { 0x0000, 0x0000 }, /* R717 */
+ { 0x0000, 0x0000 }, /* R718 */
+ { 0x0000, 0x0000 }, /* R719 */
+ { 0x0000, 0x0000 }, /* R720 */
+ { 0x0000, 0x0000 }, /* R721 */
+ { 0x0000, 0x0000 }, /* R722 */
+ { 0x0000, 0x0000 }, /* R723 */
+ { 0x0000, 0x0000 }, /* R724 */
+ { 0x0000, 0x0000 }, /* R725 */
+ { 0x0000, 0x0000 }, /* R726 */
+ { 0x0000, 0x0000 }, /* R727 */
+ { 0x0000, 0x0000 }, /* R728 */
+ { 0x0000, 0x0000 }, /* R729 */
+ { 0x0000, 0x0000 }, /* R730 */
+ { 0x0000, 0x0000 }, /* R731 */
+ { 0x0000, 0x0000 }, /* R732 */
+ { 0x0000, 0x0000 }, /* R733 */
+ { 0x0000, 0x0000 }, /* R734 */
+ { 0x0000, 0x0000 }, /* R735 */
+ { 0x0000, 0x0000 }, /* R736 */
+ { 0x0000, 0x0000 }, /* R737 */
+ { 0x0000, 0x0000 }, /* R738 */
+ { 0x0000, 0x0000 }, /* R739 */
+ { 0x0000, 0x0000 }, /* R740 */
+ { 0x0000, 0x0000 }, /* R741 */
+ { 0x0000, 0x0000 }, /* R742 */
+ { 0x0000, 0x0000 }, /* R743 */
+ { 0x0000, 0x0000 }, /* R744 */
+ { 0x0000, 0x0000 }, /* R745 */
+ { 0x0000, 0x0000 }, /* R746 */
+ { 0x0000, 0x0000 }, /* R747 */
+ { 0x0000, 0x0000 }, /* R748 */
+ { 0x0000, 0x0000 }, /* R749 */
+ { 0x0000, 0x0000 }, /* R750 */
+ { 0x0000, 0x0000 }, /* R751 */
+ { 0x0000, 0x0000 }, /* R752 */
+ { 0x0000, 0x0000 }, /* R753 */
+ { 0x0000, 0x0000 }, /* R754 */
+ { 0x0000, 0x0000 }, /* R755 */
+ { 0x0000, 0x0000 }, /* R756 */
+ { 0x0000, 0x0000 }, /* R757 */
+ { 0x0000, 0x0000 }, /* R758 */
+ { 0x0000, 0x0000 }, /* R759 */
+ { 0x0000, 0x0000 }, /* R760 */
+ { 0x0000, 0x0000 }, /* R761 */
+ { 0x0000, 0x0000 }, /* R762 */
+ { 0x0000, 0x0000 }, /* R763 */
+ { 0x0000, 0x0000 }, /* R764 */
+ { 0x0000, 0x0000 }, /* R765 */
+ { 0x0000, 0x0000 }, /* R766 */
+ { 0x0000, 0x0000 }, /* R767 */
+ { 0xE1F8, 0xE1F8 }, /* R768 - AIF1 Control (1) */
+ { 0xCD1F, 0xCD1F }, /* R769 - AIF1 Control (2) */
+ { 0xF000, 0xF000 }, /* R770 - AIF1 Master/Slave */
+ { 0x01F0, 0x01F0 }, /* R771 - AIF1 BCLK */
+ { 0x0FFF, 0x0FFF }, /* R772 - AIF1ADC LRCLK */
+ { 0x0FFF, 0x0FFF }, /* R773 - AIF1DAC LRCLK */
+ { 0x0003, 0x0003 }, /* R774 - AIF1DAC Data */
+ { 0x0003, 0x0003 }, /* R775 - AIF1ADC Data */
+ { 0x0000, 0x0000 }, /* R776 */
+ { 0x0000, 0x0000 }, /* R777 */
+ { 0x0000, 0x0000 }, /* R778 */
+ { 0x0000, 0x0000 }, /* R779 */
+ { 0x0000, 0x0000 }, /* R780 */
+ { 0x0000, 0x0000 }, /* R781 */
+ { 0x0000, 0x0000 }, /* R782 */
+ { 0x0000, 0x0000 }, /* R783 */
+ { 0xF1F8, 0xF1F8 }, /* R784 - AIF2 Control (1) */
+ { 0xFD1F, 0xFD1F }, /* R785 - AIF2 Control (2) */
+ { 0xF000, 0xF000 }, /* R786 - AIF2 Master/Slave */
+ { 0x01F0, 0x01F0 }, /* R787 - AIF2 BCLK */
+ { 0x0FFF, 0x0FFF }, /* R788 - AIF2ADC LRCLK */
+ { 0x0FFF, 0x0FFF }, /* R789 - AIF2DAC LRCLK */
+ { 0x0003, 0x0003 }, /* R790 - AIF2DAC Data */
+ { 0x0003, 0x0003 }, /* R791 - AIF2ADC Data */
+ { 0x0000, 0x0000 }, /* R792 */
+ { 0x0000, 0x0000 }, /* R793 */
+ { 0x0000, 0x0000 }, /* R794 */
+ { 0x0000, 0x0000 }, /* R795 */
+ { 0x0000, 0x0000 }, /* R796 */
+ { 0x0000, 0x0000 }, /* R797 */
+ { 0x0000, 0x0000 }, /* R798 */
+ { 0x0000, 0x0000 }, /* R799 */
+ { 0x0000, 0x0000 }, /* R800 */
+ { 0x0000, 0x0000 }, /* R801 */
+ { 0x0000, 0x0000 }, /* R802 */
+ { 0x0000, 0x0000 }, /* R803 */
+ { 0x0000, 0x0000 }, /* R804 */
+ { 0x0000, 0x0000 }, /* R805 */
+ { 0x0000, 0x0000 }, /* R806 */
+ { 0x0000, 0x0000 }, /* R807 */
+ { 0x0000, 0x0000 }, /* R808 */
+ { 0x0000, 0x0000 }, /* R809 */
+ { 0x0000, 0x0000 }, /* R810 */
+ { 0x0000, 0x0000 }, /* R811 */
+ { 0x0000, 0x0000 }, /* R812 */
+ { 0x0000, 0x0000 }, /* R813 */
+ { 0x0000, 0x0000 }, /* R814 */
+ { 0x0000, 0x0000 }, /* R815 */
+ { 0x0000, 0x0000 }, /* R816 */
+ { 0x0000, 0x0000 }, /* R817 */
+ { 0x0000, 0x0000 }, /* R818 */
+ { 0x0000, 0x0000 }, /* R819 */
+ { 0x0000, 0x0000 }, /* R820 */
+ { 0x0000, 0x0000 }, /* R821 */
+ { 0x0000, 0x0000 }, /* R822 */
+ { 0x0000, 0x0000 }, /* R823 */
+ { 0x0000, 0x0000 }, /* R824 */
+ { 0x0000, 0x0000 }, /* R825 */
+ { 0x0000, 0x0000 }, /* R826 */
+ { 0x0000, 0x0000 }, /* R827 */
+ { 0x0000, 0x0000 }, /* R828 */
+ { 0x0000, 0x0000 }, /* R829 */
+ { 0x0000, 0x0000 }, /* R830 */
+ { 0x0000, 0x0000 }, /* R831 */
+ { 0x0000, 0x0000 }, /* R832 */
+ { 0x0000, 0x0000 }, /* R833 */
+ { 0x0000, 0x0000 }, /* R834 */
+ { 0x0000, 0x0000 }, /* R835 */
+ { 0x0000, 0x0000 }, /* R836 */
+ { 0x0000, 0x0000 }, /* R837 */
+ { 0x0000, 0x0000 }, /* R838 */
+ { 0x0000, 0x0000 }, /* R839 */
+ { 0x0000, 0x0000 }, /* R840 */
+ { 0x0000, 0x0000 }, /* R841 */
+ { 0x0000, 0x0000 }, /* R842 */
+ { 0x0000, 0x0000 }, /* R843 */
+ { 0x0000, 0x0000 }, /* R844 */
+ { 0x0000, 0x0000 }, /* R845 */
+ { 0x0000, 0x0000 }, /* R846 */
+ { 0x0000, 0x0000 }, /* R847 */
+ { 0x0000, 0x0000 }, /* R848 */
+ { 0x0000, 0x0000 }, /* R849 */
+ { 0x0000, 0x0000 }, /* R850 */
+ { 0x0000, 0x0000 }, /* R851 */
+ { 0x0000, 0x0000 }, /* R852 */
+ { 0x0000, 0x0000 }, /* R853 */
+ { 0x0000, 0x0000 }, /* R854 */
+ { 0x0000, 0x0000 }, /* R855 */
+ { 0x0000, 0x0000 }, /* R856 */
+ { 0x0000, 0x0000 }, /* R857 */
+ { 0x0000, 0x0000 }, /* R858 */
+ { 0x0000, 0x0000 }, /* R859 */
+ { 0x0000, 0x0000 }, /* R860 */
+ { 0x0000, 0x0000 }, /* R861 */
+ { 0x0000, 0x0000 }, /* R862 */
+ { 0x0000, 0x0000 }, /* R863 */
+ { 0x0000, 0x0000 }, /* R864 */
+ { 0x0000, 0x0000 }, /* R865 */
+ { 0x0000, 0x0000 }, /* R866 */
+ { 0x0000, 0x0000 }, /* R867 */
+ { 0x0000, 0x0000 }, /* R868 */
+ { 0x0000, 0x0000 }, /* R869 */
+ { 0x0000, 0x0000 }, /* R870 */
+ { 0x0000, 0x0000 }, /* R871 */
+ { 0x0000, 0x0000 }, /* R872 */
+ { 0x0000, 0x0000 }, /* R873 */
+ { 0x0000, 0x0000 }, /* R874 */
+ { 0x0000, 0x0000 }, /* R875 */
+ { 0x0000, 0x0000 }, /* R876 */
+ { 0x0000, 0x0000 }, /* R877 */
+ { 0x0000, 0x0000 }, /* R878 */
+ { 0x0000, 0x0000 }, /* R879 */
+ { 0x0000, 0x0000 }, /* R880 */
+ { 0x0000, 0x0000 }, /* R881 */
+ { 0x0000, 0x0000 }, /* R882 */
+ { 0x0000, 0x0000 }, /* R883 */
+ { 0x0000, 0x0000 }, /* R884 */
+ { 0x0000, 0x0000 }, /* R885 */
+ { 0x0000, 0x0000 }, /* R886 */
+ { 0x0000, 0x0000 }, /* R887 */
+ { 0x0000, 0x0000 }, /* R888 */
+ { 0x0000, 0x0000 }, /* R889 */
+ { 0x0000, 0x0000 }, /* R890 */
+ { 0x0000, 0x0000 }, /* R891 */
+ { 0x0000, 0x0000 }, /* R892 */
+ { 0x0000, 0x0000 }, /* R893 */
+ { 0x0000, 0x0000 }, /* R894 */
+ { 0x0000, 0x0000 }, /* R895 */
+ { 0x0000, 0x0000 }, /* R896 */
+ { 0x0000, 0x0000 }, /* R897 */
+ { 0x0000, 0x0000 }, /* R898 */
+ { 0x0000, 0x0000 }, /* R899 */
+ { 0x0000, 0x0000 }, /* R900 */
+ { 0x0000, 0x0000 }, /* R901 */
+ { 0x0000, 0x0000 }, /* R902 */
+ { 0x0000, 0x0000 }, /* R903 */
+ { 0x0000, 0x0000 }, /* R904 */
+ { 0x0000, 0x0000 }, /* R905 */
+ { 0x0000, 0x0000 }, /* R906 */
+ { 0x0000, 0x0000 }, /* R907 */
+ { 0x0000, 0x0000 }, /* R908 */
+ { 0x0000, 0x0000 }, /* R909 */
+ { 0x0000, 0x0000 }, /* R910 */
+ { 0x0000, 0x0000 }, /* R911 */
+ { 0x0000, 0x0000 }, /* R912 */
+ { 0x0000, 0x0000 }, /* R913 */
+ { 0x0000, 0x0000 }, /* R914 */
+ { 0x0000, 0x0000 }, /* R915 */
+ { 0x0000, 0x0000 }, /* R916 */
+ { 0x0000, 0x0000 }, /* R917 */
+ { 0x0000, 0x0000 }, /* R918 */
+ { 0x0000, 0x0000 }, /* R919 */
+ { 0x0000, 0x0000 }, /* R920 */
+ { 0x0000, 0x0000 }, /* R921 */
+ { 0x0000, 0x0000 }, /* R922 */
+ { 0x0000, 0x0000 }, /* R923 */
+ { 0x0000, 0x0000 }, /* R924 */
+ { 0x0000, 0x0000 }, /* R925 */
+ { 0x0000, 0x0000 }, /* R926 */
+ { 0x0000, 0x0000 }, /* R927 */
+ { 0x0000, 0x0000 }, /* R928 */
+ { 0x0000, 0x0000 }, /* R929 */
+ { 0x0000, 0x0000 }, /* R930 */
+ { 0x0000, 0x0000 }, /* R931 */
+ { 0x0000, 0x0000 }, /* R932 */
+ { 0x0000, 0x0000 }, /* R933 */
+ { 0x0000, 0x0000 }, /* R934 */
+ { 0x0000, 0x0000 }, /* R935 */
+ { 0x0000, 0x0000 }, /* R936 */
+ { 0x0000, 0x0000 }, /* R937 */
+ { 0x0000, 0x0000 }, /* R938 */
+ { 0x0000, 0x0000 }, /* R939 */
+ { 0x0000, 0x0000 }, /* R940 */
+ { 0x0000, 0x0000 }, /* R941 */
+ { 0x0000, 0x0000 }, /* R942 */
+ { 0x0000, 0x0000 }, /* R943 */
+ { 0x0000, 0x0000 }, /* R944 */
+ { 0x0000, 0x0000 }, /* R945 */
+ { 0x0000, 0x0000 }, /* R946 */
+ { 0x0000, 0x0000 }, /* R947 */
+ { 0x0000, 0x0000 }, /* R948 */
+ { 0x0000, 0x0000 }, /* R949 */
+ { 0x0000, 0x0000 }, /* R950 */
+ { 0x0000, 0x0000 }, /* R951 */
+ { 0x0000, 0x0000 }, /* R952 */
+ { 0x0000, 0x0000 }, /* R953 */
+ { 0x0000, 0x0000 }, /* R954 */
+ { 0x0000, 0x0000 }, /* R955 */
+ { 0x0000, 0x0000 }, /* R956 */
+ { 0x0000, 0x0000 }, /* R957 */
+ { 0x0000, 0x0000 }, /* R958 */
+ { 0x0000, 0x0000 }, /* R959 */
+ { 0x0000, 0x0000 }, /* R960 */
+ { 0x0000, 0x0000 }, /* R961 */
+ { 0x0000, 0x0000 }, /* R962 */
+ { 0x0000, 0x0000 }, /* R963 */
+ { 0x0000, 0x0000 }, /* R964 */
+ { 0x0000, 0x0000 }, /* R965 */
+ { 0x0000, 0x0000 }, /* R966 */
+ { 0x0000, 0x0000 }, /* R967 */
+ { 0x0000, 0x0000 }, /* R968 */
+ { 0x0000, 0x0000 }, /* R969 */
+ { 0x0000, 0x0000 }, /* R970 */
+ { 0x0000, 0x0000 }, /* R971 */
+ { 0x0000, 0x0000 }, /* R972 */
+ { 0x0000, 0x0000 }, /* R973 */
+ { 0x0000, 0x0000 }, /* R974 */
+ { 0x0000, 0x0000 }, /* R975 */
+ { 0x0000, 0x0000 }, /* R976 */
+ { 0x0000, 0x0000 }, /* R977 */
+ { 0x0000, 0x0000 }, /* R978 */
+ { 0x0000, 0x0000 }, /* R979 */
+ { 0x0000, 0x0000 }, /* R980 */
+ { 0x0000, 0x0000 }, /* R981 */
+ { 0x0000, 0x0000 }, /* R982 */
+ { 0x0000, 0x0000 }, /* R983 */
+ { 0x0000, 0x0000 }, /* R984 */
+ { 0x0000, 0x0000 }, /* R985 */
+ { 0x0000, 0x0000 }, /* R986 */
+ { 0x0000, 0x0000 }, /* R987 */
+ { 0x0000, 0x0000 }, /* R988 */
+ { 0x0000, 0x0000 }, /* R989 */
+ { 0x0000, 0x0000 }, /* R990 */
+ { 0x0000, 0x0000 }, /* R991 */
+ { 0x0000, 0x0000 }, /* R992 */
+ { 0x0000, 0x0000 }, /* R993 */
+ { 0x0000, 0x0000 }, /* R994 */
+ { 0x0000, 0x0000 }, /* R995 */
+ { 0x0000, 0x0000 }, /* R996 */
+ { 0x0000, 0x0000 }, /* R997 */
+ { 0x0000, 0x0000 }, /* R998 */
+ { 0x0000, 0x0000 }, /* R999 */
+ { 0x0000, 0x0000 }, /* R1000 */
+ { 0x0000, 0x0000 }, /* R1001 */
+ { 0x0000, 0x0000 }, /* R1002 */
+ { 0x0000, 0x0000 }, /* R1003 */
+ { 0x0000, 0x0000 }, /* R1004 */
+ { 0x0000, 0x0000 }, /* R1005 */
+ { 0x0000, 0x0000 }, /* R1006 */
+ { 0x0000, 0x0000 }, /* R1007 */
+ { 0x0000, 0x0000 }, /* R1008 */
+ { 0x0000, 0x0000 }, /* R1009 */
+ { 0x0000, 0x0000 }, /* R1010 */
+ { 0x0000, 0x0000 }, /* R1011 */
+ { 0x0000, 0x0000 }, /* R1012 */
+ { 0x0000, 0x0000 }, /* R1013 */
+ { 0x0000, 0x0000 }, /* R1014 */
+ { 0x0000, 0x0000 }, /* R1015 */
+ { 0x0000, 0x0000 }, /* R1016 */
+ { 0x0000, 0x0000 }, /* R1017 */
+ { 0x0000, 0x0000 }, /* R1018 */
+ { 0x0000, 0x0000 }, /* R1019 */
+ { 0x0000, 0x0000 }, /* R1020 */
+ { 0x0000, 0x0000 }, /* R1021 */
+ { 0x0000, 0x0000 }, /* R1022 */
+ { 0x0000, 0x0000 }, /* R1023 */
+ { 0x00FF, 0x01FF }, /* R1024 - AIF1 ADC1 Left Volume */
+ { 0x00FF, 0x01FF }, /* R1025 - AIF1 ADC1 Right Volume */
+ { 0x00FF, 0x01FF }, /* R1026 - AIF1 DAC1 Left Volume */
+ { 0x00FF, 0x01FF }, /* R1027 - AIF1 DAC1 Right Volume */
+ { 0x00FF, 0x01FF }, /* R1028 - AIF1 ADC2 Left Volume */
+ { 0x00FF, 0x01FF }, /* R1029 - AIF1 ADC2 Right Volume */
+ { 0x00FF, 0x01FF }, /* R1030 - AIF1 DAC2 Left Volume */
+ { 0x00FF, 0x01FF }, /* R1031 - AIF1 DAC2 Right Volume */
+ { 0x0000, 0x0000 }, /* R1032 */
+ { 0x0000, 0x0000 }, /* R1033 */
+ { 0x0000, 0x0000 }, /* R1034 */
+ { 0x0000, 0x0000 }, /* R1035 */
+ { 0x0000, 0x0000 }, /* R1036 */
+ { 0x0000, 0x0000 }, /* R1037 */
+ { 0x0000, 0x0000 }, /* R1038 */
+ { 0x0000, 0x0000 }, /* R1039 */
+ { 0xF800, 0xF800 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x7800, 0x7800 }, /* R1041 - AIF1 ADC2 Filters */
+ { 0x0000, 0x0000 }, /* R1042 */
+ { 0x0000, 0x0000 }, /* R1043 */
+ { 0x0000, 0x0000 }, /* R1044 */
+ { 0x0000, 0x0000 }, /* R1045 */
+ { 0x0000, 0x0000 }, /* R1046 */
+ { 0x0000, 0x0000 }, /* R1047 */
+ { 0x0000, 0x0000 }, /* R1048 */
+ { 0x0000, 0x0000 }, /* R1049 */
+ { 0x0000, 0x0000 }, /* R1050 */
+ { 0x0000, 0x0000 }, /* R1051 */
+ { 0x0000, 0x0000 }, /* R1052 */
+ { 0x0000, 0x0000 }, /* R1053 */
+ { 0x0000, 0x0000 }, /* R1054 */
+ { 0x0000, 0x0000 }, /* R1055 */
+ { 0x02B6, 0x02B6 }, /* R1056 - AIF1 DAC1 Filters (1) */
+ { 0x3F00, 0x3F00 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x02B6, 0x02B6 }, /* R1058 - AIF1 DAC2 Filters (1) */
+ { 0x3F00, 0x3F00 }, /* R1059 - AIF1 DAC2 Filters (2) */
+ { 0x0000, 0x0000 }, /* R1060 */
+ { 0x0000, 0x0000 }, /* R1061 */
+ { 0x0000, 0x0000 }, /* R1062 */
+ { 0x0000, 0x0000 }, /* R1063 */
+ { 0x0000, 0x0000 }, /* R1064 */
+ { 0x0000, 0x0000 }, /* R1065 */
+ { 0x0000, 0x0000 }, /* R1066 */
+ { 0x0000, 0x0000 }, /* R1067 */
+ { 0x0000, 0x0000 }, /* R1068 */
+ { 0x0000, 0x0000 }, /* R1069 */
+ { 0x0000, 0x0000 }, /* R1070 */
+ { 0x0000, 0x0000 }, /* R1071 */
+ { 0x0000, 0x0000 }, /* R1072 */
+ { 0x0000, 0x0000 }, /* R1073 */
+ { 0x0000, 0x0000 }, /* R1074 */
+ { 0x0000, 0x0000 }, /* R1075 */
+ { 0x0000, 0x0000 }, /* R1076 */
+ { 0x0000, 0x0000 }, /* R1077 */
+ { 0x0000, 0x0000 }, /* R1078 */
+ { 0x0000, 0x0000 }, /* R1079 */
+ { 0x0000, 0x0000 }, /* R1080 */
+ { 0x0000, 0x0000 }, /* R1081 */
+ { 0x0000, 0x0000 }, /* R1082 */
+ { 0x0000, 0x0000 }, /* R1083 */
+ { 0x0000, 0x0000 }, /* R1084 */
+ { 0x0000, 0x0000 }, /* R1085 */
+ { 0x0000, 0x0000 }, /* R1086 */
+ { 0x0000, 0x0000 }, /* R1087 */
+ { 0xFFFF, 0xFFFF }, /* R1088 - AIF1 DRC1 (1) */
+ { 0x1FFF, 0x1FFF }, /* R1089 - AIF1 DRC1 (2) */
+ { 0xFFFF, 0xFFFF }, /* R1090 - AIF1 DRC1 (3) */
+ { 0x07FF, 0x07FF }, /* R1091 - AIF1 DRC1 (4) */
+ { 0x03FF, 0x03FF }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0000, 0x0000 }, /* R1093 */
+ { 0x0000, 0x0000 }, /* R1094 */
+ { 0x0000, 0x0000 }, /* R1095 */
+ { 0x0000, 0x0000 }, /* R1096 */
+ { 0x0000, 0x0000 }, /* R1097 */
+ { 0x0000, 0x0000 }, /* R1098 */
+ { 0x0000, 0x0000 }, /* R1099 */
+ { 0x0000, 0x0000 }, /* R1100 */
+ { 0x0000, 0x0000 }, /* R1101 */
+ { 0x0000, 0x0000 }, /* R1102 */
+ { 0x0000, 0x0000 }, /* R1103 */
+ { 0xFFFF, 0xFFFF }, /* R1104 - AIF1 DRC2 (1) */
+ { 0x1FFF, 0x1FFF }, /* R1105 - AIF1 DRC2 (2) */
+ { 0xFFFF, 0xFFFF }, /* R1106 - AIF1 DRC2 (3) */
+ { 0x07FF, 0x07FF }, /* R1107 - AIF1 DRC2 (4) */
+ { 0x03FF, 0x03FF }, /* R1108 - AIF1 DRC2 (5) */
+ { 0x0000, 0x0000 }, /* R1109 */
+ { 0x0000, 0x0000 }, /* R1110 */
+ { 0x0000, 0x0000 }, /* R1111 */
+ { 0x0000, 0x0000 }, /* R1112 */
+ { 0x0000, 0x0000 }, /* R1113 */
+ { 0x0000, 0x0000 }, /* R1114 */
+ { 0x0000, 0x0000 }, /* R1115 */
+ { 0x0000, 0x0000 }, /* R1116 */
+ { 0x0000, 0x0000 }, /* R1117 */
+ { 0x0000, 0x0000 }, /* R1118 */
+ { 0x0000, 0x0000 }, /* R1119 */
+ { 0x0000, 0x0000 }, /* R1120 */
+ { 0x0000, 0x0000 }, /* R1121 */
+ { 0x0000, 0x0000 }, /* R1122 */
+ { 0x0000, 0x0000 }, /* R1123 */
+ { 0x0000, 0x0000 }, /* R1124 */
+ { 0x0000, 0x0000 }, /* R1125 */
+ { 0x0000, 0x0000 }, /* R1126 */
+ { 0x0000, 0x0000 }, /* R1127 */
+ { 0x0000, 0x0000 }, /* R1128 */
+ { 0x0000, 0x0000 }, /* R1129 */
+ { 0x0000, 0x0000 }, /* R1130 */
+ { 0x0000, 0x0000 }, /* R1131 */
+ { 0x0000, 0x0000 }, /* R1132 */
+ { 0x0000, 0x0000 }, /* R1133 */
+ { 0x0000, 0x0000 }, /* R1134 */
+ { 0x0000, 0x0000 }, /* R1135 */
+ { 0x0000, 0x0000 }, /* R1136 */
+ { 0x0000, 0x0000 }, /* R1137 */
+ { 0x0000, 0x0000 }, /* R1138 */
+ { 0x0000, 0x0000 }, /* R1139 */
+ { 0x0000, 0x0000 }, /* R1140 */
+ { 0x0000, 0x0000 }, /* R1141 */
+ { 0x0000, 0x0000 }, /* R1142 */
+ { 0x0000, 0x0000 }, /* R1143 */
+ { 0x0000, 0x0000 }, /* R1144 */
+ { 0x0000, 0x0000 }, /* R1145 */
+ { 0x0000, 0x0000 }, /* R1146 */
+ { 0x0000, 0x0000 }, /* R1147 */
+ { 0x0000, 0x0000 }, /* R1148 */
+ { 0x0000, 0x0000 }, /* R1149 */
+ { 0x0000, 0x0000 }, /* R1150 */
+ { 0x0000, 0x0000 }, /* R1151 */
+ { 0xFFFF, 0xFFFF }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
+ { 0xFFC0, 0xFFC0 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
+ { 0xFFFF, 0xFFFF }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
+ { 0xFFFF, 0xFFFF }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
+ { 0xFFFF, 0xFFFF }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
+ { 0xFFFF, 0xFFFF }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
+ { 0xFFFF, 0xFFFF }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
+ { 0xFFFF, 0xFFFF }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
+ { 0xFFFF, 0xFFFF }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
+ { 0xFFFF, 0xFFFF }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
+ { 0xFFFF, 0xFFFF }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
+ { 0xFFFF, 0xFFFF }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
+ { 0xFFFF, 0xFFFF }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
+ { 0xFFFF, 0xFFFF }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
+ { 0xFFFF, 0xFFFF }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
+ { 0xFFFF, 0xFFFF }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
+ { 0xFFFF, 0xFFFF }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
+ { 0xFFFF, 0xFFFF }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
+ { 0xFFFF, 0xFFFF }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
+ { 0xFFFF, 0xFFFF }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
+ { 0x0000, 0x0000 }, /* R1172 */
+ { 0x0000, 0x0000 }, /* R1173 */
+ { 0x0000, 0x0000 }, /* R1174 */
+ { 0x0000, 0x0000 }, /* R1175 */
+ { 0x0000, 0x0000 }, /* R1176 */
+ { 0x0000, 0x0000 }, /* R1177 */
+ { 0x0000, 0x0000 }, /* R1178 */
+ { 0x0000, 0x0000 }, /* R1179 */
+ { 0x0000, 0x0000 }, /* R1180 */
+ { 0x0000, 0x0000 }, /* R1181 */
+ { 0x0000, 0x0000 }, /* R1182 */
+ { 0x0000, 0x0000 }, /* R1183 */
+ { 0xFFFF, 0xFFFF }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
+ { 0xFFC0, 0xFFC0 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
+ { 0xFFFF, 0xFFFF }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
+ { 0xFFFF, 0xFFFF }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
+ { 0xFFFF, 0xFFFF }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+ { 0xFFFF, 0xFFFF }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
+ { 0xFFFF, 0xFFFF }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
+ { 0xFFFF, 0xFFFF }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
+ { 0xFFFF, 0xFFFF }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+ { 0xFFFF, 0xFFFF }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
+ { 0xFFFF, 0xFFFF }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
+ { 0xFFFF, 0xFFFF }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
+ { 0xFFFF, 0xFFFF }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+ { 0xFFFF, 0xFFFF }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
+ { 0xFFFF, 0xFFFF }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
+ { 0xFFFF, 0xFFFF }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
+ { 0xFFFF, 0xFFFF }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+ { 0xFFFF, 0xFFFF }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
+ { 0xFFFF, 0xFFFF }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
+ { 0xFFFF, 0xFFFF }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+ { 0x0000, 0x0000 }, /* R1204 */
+ { 0x0000, 0x0000 }, /* R1205 */
+ { 0x0000, 0x0000 }, /* R1206 */
+ { 0x0000, 0x0000 }, /* R1207 */
+ { 0x0000, 0x0000 }, /* R1208 */
+ { 0x0000, 0x0000 }, /* R1209 */
+ { 0x0000, 0x0000 }, /* R1210 */
+ { 0x0000, 0x0000 }, /* R1211 */
+ { 0x0000, 0x0000 }, /* R1212 */
+ { 0x0000, 0x0000 }, /* R1213 */
+ { 0x0000, 0x0000 }, /* R1214 */
+ { 0x0000, 0x0000 }, /* R1215 */
+ { 0x0000, 0x0000 }, /* R1216 */
+ { 0x0000, 0x0000 }, /* R1217 */
+ { 0x0000, 0x0000 }, /* R1218 */
+ { 0x0000, 0x0000 }, /* R1219 */
+ { 0x0000, 0x0000 }, /* R1220 */
+ { 0x0000, 0x0000 }, /* R1221 */
+ { 0x0000, 0x0000 }, /* R1222 */
+ { 0x0000, 0x0000 }, /* R1223 */
+ { 0x0000, 0x0000 }, /* R1224 */
+ { 0x0000, 0x0000 }, /* R1225 */
+ { 0x0000, 0x0000 }, /* R1226 */
+ { 0x0000, 0x0000 }, /* R1227 */
+ { 0x0000, 0x0000 }, /* R1228 */
+ { 0x0000, 0x0000 }, /* R1229 */
+ { 0x0000, 0x0000 }, /* R1230 */
+ { 0x0000, 0x0000 }, /* R1231 */
+ { 0x0000, 0x0000 }, /* R1232 */
+ { 0x0000, 0x0000 }, /* R1233 */
+ { 0x0000, 0x0000 }, /* R1234 */
+ { 0x0000, 0x0000 }, /* R1235 */
+ { 0x0000, 0x0000 }, /* R1236 */
+ { 0x0000, 0x0000 }, /* R1237 */
+ { 0x0000, 0x0000 }, /* R1238 */
+ { 0x0000, 0x0000 }, /* R1239 */
+ { 0x0000, 0x0000 }, /* R1240 */
+ { 0x0000, 0x0000 }, /* R1241 */
+ { 0x0000, 0x0000 }, /* R1242 */
+ { 0x0000, 0x0000 }, /* R1243 */
+ { 0x0000, 0x0000 }, /* R1244 */
+ { 0x0000, 0x0000 }, /* R1245 */
+ { 0x0000, 0x0000 }, /* R1246 */
+ { 0x0000, 0x0000 }, /* R1247 */
+ { 0x0000, 0x0000 }, /* R1248 */
+ { 0x0000, 0x0000 }, /* R1249 */
+ { 0x0000, 0x0000 }, /* R1250 */
+ { 0x0000, 0x0000 }, /* R1251 */
+ { 0x0000, 0x0000 }, /* R1252 */
+ { 0x0000, 0x0000 }, /* R1253 */
+ { 0x0000, 0x0000 }, /* R1254 */
+ { 0x0000, 0x0000 }, /* R1255 */
+ { 0x0000, 0x0000 }, /* R1256 */
+ { 0x0000, 0x0000 }, /* R1257 */
+ { 0x0000, 0x0000 }, /* R1258 */
+ { 0x0000, 0x0000 }, /* R1259 */
+ { 0x0000, 0x0000 }, /* R1260 */
+ { 0x0000, 0x0000 }, /* R1261 */
+ { 0x0000, 0x0000 }, /* R1262 */
+ { 0x0000, 0x0000 }, /* R1263 */
+ { 0x0000, 0x0000 }, /* R1264 */
+ { 0x0000, 0x0000 }, /* R1265 */
+ { 0x0000, 0x0000 }, /* R1266 */
+ { 0x0000, 0x0000 }, /* R1267 */
+ { 0x0000, 0x0000 }, /* R1268 */
+ { 0x0000, 0x0000 }, /* R1269 */
+ { 0x0000, 0x0000 }, /* R1270 */
+ { 0x0000, 0x0000 }, /* R1271 */
+ { 0x0000, 0x0000 }, /* R1272 */
+ { 0x0000, 0x0000 }, /* R1273 */
+ { 0x0000, 0x0000 }, /* R1274 */
+ { 0x0000, 0x0000 }, /* R1275 */
+ { 0x0000, 0x0000 }, /* R1276 */
+ { 0x0000, 0x0000 }, /* R1277 */
+ { 0x0000, 0x0000 }, /* R1278 */
+ { 0x0000, 0x0000 }, /* R1279 */
+ { 0x00FF, 0x01FF }, /* R1280 - AIF2 ADC Left Volume */
+ { 0x00FF, 0x01FF }, /* R1281 - AIF2 ADC Right Volume */
+ { 0x00FF, 0x01FF }, /* R1282 - AIF2 DAC Left Volume */
+ { 0x00FF, 0x01FF }, /* R1283 - AIF2 DAC Right Volume */
+ { 0x0000, 0x0000 }, /* R1284 */
+ { 0x0000, 0x0000 }, /* R1285 */
+ { 0x0000, 0x0000 }, /* R1286 */
+ { 0x0000, 0x0000 }, /* R1287 */
+ { 0x0000, 0x0000 }, /* R1288 */
+ { 0x0000, 0x0000 }, /* R1289 */
+ { 0x0000, 0x0000 }, /* R1290 */
+ { 0x0000, 0x0000 }, /* R1291 */
+ { 0x0000, 0x0000 }, /* R1292 */
+ { 0x0000, 0x0000 }, /* R1293 */
+ { 0x0000, 0x0000 }, /* R1294 */
+ { 0x0000, 0x0000 }, /* R1295 */
+ { 0xF800, 0xF800 }, /* R1296 - AIF2 ADC Filters */
+ { 0x0000, 0x0000 }, /* R1297 */
+ { 0x0000, 0x0000 }, /* R1298 */
+ { 0x0000, 0x0000 }, /* R1299 */
+ { 0x0000, 0x0000 }, /* R1300 */
+ { 0x0000, 0x0000 }, /* R1301 */
+ { 0x0000, 0x0000 }, /* R1302 */
+ { 0x0000, 0x0000 }, /* R1303 */
+ { 0x0000, 0x0000 }, /* R1304 */
+ { 0x0000, 0x0000 }, /* R1305 */
+ { 0x0000, 0x0000 }, /* R1306 */
+ { 0x0000, 0x0000 }, /* R1307 */
+ { 0x0000, 0x0000 }, /* R1308 */
+ { 0x0000, 0x0000 }, /* R1309 */
+ { 0x0000, 0x0000 }, /* R1310 */
+ { 0x0000, 0x0000 }, /* R1311 */
+ { 0x02B6, 0x02B6 }, /* R1312 - AIF2 DAC Filters (1) */
+ { 0x3F00, 0x3F00 }, /* R1313 - AIF2 DAC Filters (2) */
+ { 0x0000, 0x0000 }, /* R1314 */
+ { 0x0000, 0x0000 }, /* R1315 */
+ { 0x0000, 0x0000 }, /* R1316 */
+ { 0x0000, 0x0000 }, /* R1317 */
+ { 0x0000, 0x0000 }, /* R1318 */
+ { 0x0000, 0x0000 }, /* R1319 */
+ { 0x0000, 0x0000 }, /* R1320 */
+ { 0x0000, 0x0000 }, /* R1321 */
+ { 0x0000, 0x0000 }, /* R1322 */
+ { 0x0000, 0x0000 }, /* R1323 */
+ { 0x0000, 0x0000 }, /* R1324 */
+ { 0x0000, 0x0000 }, /* R1325 */
+ { 0x0000, 0x0000 }, /* R1326 */
+ { 0x0000, 0x0000 }, /* R1327 */
+ { 0x0000, 0x0000 }, /* R1328 */
+ { 0x0000, 0x0000 }, /* R1329 */
+ { 0x0000, 0x0000 }, /* R1330 */
+ { 0x0000, 0x0000 }, /* R1331 */
+ { 0x0000, 0x0000 }, /* R1332 */
+ { 0x0000, 0x0000 }, /* R1333 */
+ { 0x0000, 0x0000 }, /* R1334 */
+ { 0x0000, 0x0000 }, /* R1335 */
+ { 0x0000, 0x0000 }, /* R1336 */
+ { 0x0000, 0x0000 }, /* R1337 */
+ { 0x0000, 0x0000 }, /* R1338 */
+ { 0x0000, 0x0000 }, /* R1339 */
+ { 0x0000, 0x0000 }, /* R1340 */
+ { 0x0000, 0x0000 }, /* R1341 */
+ { 0x0000, 0x0000 }, /* R1342 */
+ { 0x0000, 0x0000 }, /* R1343 */
+ { 0xFFFF, 0xFFFF }, /* R1344 - AIF2 DRC (1) */
+ { 0x1FFF, 0x1FFF }, /* R1345 - AIF2 DRC (2) */
+ { 0xFFFF, 0xFFFF }, /* R1346 - AIF2 DRC (3) */
+ { 0x07FF, 0x07FF }, /* R1347 - AIF2 DRC (4) */
+ { 0x03FF, 0x03FF }, /* R1348 - AIF2 DRC (5) */
+ { 0x0000, 0x0000 }, /* R1349 */
+ { 0x0000, 0x0000 }, /* R1350 */
+ { 0x0000, 0x0000 }, /* R1351 */
+ { 0x0000, 0x0000 }, /* R1352 */
+ { 0x0000, 0x0000 }, /* R1353 */
+ { 0x0000, 0x0000 }, /* R1354 */
+ { 0x0000, 0x0000 }, /* R1355 */
+ { 0x0000, 0x0000 }, /* R1356 */
+ { 0x0000, 0x0000 }, /* R1357 */
+ { 0x0000, 0x0000 }, /* R1358 */
+ { 0x0000, 0x0000 }, /* R1359 */
+ { 0x0000, 0x0000 }, /* R1360 */
+ { 0x0000, 0x0000 }, /* R1361 */
+ { 0x0000, 0x0000 }, /* R1362 */
+ { 0x0000, 0x0000 }, /* R1363 */
+ { 0x0000, 0x0000 }, /* R1364 */
+ { 0x0000, 0x0000 }, /* R1365 */
+ { 0x0000, 0x0000 }, /* R1366 */
+ { 0x0000, 0x0000 }, /* R1367 */
+ { 0x0000, 0x0000 }, /* R1368 */
+ { 0x0000, 0x0000 }, /* R1369 */
+ { 0x0000, 0x0000 }, /* R1370 */
+ { 0x0000, 0x0000 }, /* R1371 */
+ { 0x0000, 0x0000 }, /* R1372 */
+ { 0x0000, 0x0000 }, /* R1373 */
+ { 0x0000, 0x0000 }, /* R1374 */
+ { 0x0000, 0x0000 }, /* R1375 */
+ { 0x0000, 0x0000 }, /* R1376 */
+ { 0x0000, 0x0000 }, /* R1377 */
+ { 0x0000, 0x0000 }, /* R1378 */
+ { 0x0000, 0x0000 }, /* R1379 */
+ { 0x0000, 0x0000 }, /* R1380 */
+ { 0x0000, 0x0000 }, /* R1381 */
+ { 0x0000, 0x0000 }, /* R1382 */
+ { 0x0000, 0x0000 }, /* R1383 */
+ { 0x0000, 0x0000 }, /* R1384 */
+ { 0x0000, 0x0000 }, /* R1385 */
+ { 0x0000, 0x0000 }, /* R1386 */
+ { 0x0000, 0x0000 }, /* R1387 */
+ { 0x0000, 0x0000 }, /* R1388 */
+ { 0x0000, 0x0000 }, /* R1389 */
+ { 0x0000, 0x0000 }, /* R1390 */
+ { 0x0000, 0x0000 }, /* R1391 */
+ { 0x0000, 0x0000 }, /* R1392 */
+ { 0x0000, 0x0000 }, /* R1393 */
+ { 0x0000, 0x0000 }, /* R1394 */
+ { 0x0000, 0x0000 }, /* R1395 */
+ { 0x0000, 0x0000 }, /* R1396 */
+ { 0x0000, 0x0000 }, /* R1397 */
+ { 0x0000, 0x0000 }, /* R1398 */
+ { 0x0000, 0x0000 }, /* R1399 */
+ { 0x0000, 0x0000 }, /* R1400 */
+ { 0x0000, 0x0000 }, /* R1401 */
+ { 0x0000, 0x0000 }, /* R1402 */
+ { 0x0000, 0x0000 }, /* R1403 */
+ { 0x0000, 0x0000 }, /* R1404 */
+ { 0x0000, 0x0000 }, /* R1405 */
+ { 0x0000, 0x0000 }, /* R1406 */
+ { 0x0000, 0x0000 }, /* R1407 */
+ { 0xFFFF, 0xFFFF }, /* R1408 - AIF2 EQ Gains (1) */
+ { 0xFFC0, 0xFFC0 }, /* R1409 - AIF2 EQ Gains (2) */
+ { 0xFFFF, 0xFFFF }, /* R1410 - AIF2 EQ Band 1 A */
+ { 0xFFFF, 0xFFFF }, /* R1411 - AIF2 EQ Band 1 B */
+ { 0xFFFF, 0xFFFF }, /* R1412 - AIF2 EQ Band 1 PG */
+ { 0xFFFF, 0xFFFF }, /* R1413 - AIF2 EQ Band 2 A */
+ { 0xFFFF, 0xFFFF }, /* R1414 - AIF2 EQ Band 2 B */
+ { 0xFFFF, 0xFFFF }, /* R1415 - AIF2 EQ Band 2 C */
+ { 0xFFFF, 0xFFFF }, /* R1416 - AIF2 EQ Band 2 PG */
+ { 0xFFFF, 0xFFFF }, /* R1417 - AIF2 EQ Band 3 A */
+ { 0xFFFF, 0xFFFF }, /* R1418 - AIF2 EQ Band 3 B */
+ { 0xFFFF, 0xFFFF }, /* R1419 - AIF2 EQ Band 3 C */
+ { 0xFFFF, 0xFFFF }, /* R1420 - AIF2 EQ Band 3 PG */
+ { 0xFFFF, 0xFFFF }, /* R1421 - AIF2 EQ Band 4 A */
+ { 0xFFFF, 0xFFFF }, /* R1422 - AIF2 EQ Band 4 B */
+ { 0xFFFF, 0xFFFF }, /* R1423 - AIF2 EQ Band 4 C */
+ { 0xFFFF, 0xFFFF }, /* R1424 - AIF2 EQ Band 4 PG */
+ { 0xFFFF, 0xFFFF }, /* R1425 - AIF2 EQ Band 5 A */
+ { 0xFFFF, 0xFFFF }, /* R1426 - AIF2 EQ Band 5 B */
+ { 0xFFFF, 0xFFFF }, /* R1427 - AIF2 EQ Band 5 PG */
+ { 0x0000, 0x0000 }, /* R1428 */
+ { 0x0000, 0x0000 }, /* R1429 */
+ { 0x0000, 0x0000 }, /* R1430 */
+ { 0x0000, 0x0000 }, /* R1431 */
+ { 0x0000, 0x0000 }, /* R1432 */
+ { 0x0000, 0x0000 }, /* R1433 */
+ { 0x0000, 0x0000 }, /* R1434 */
+ { 0x0000, 0x0000 }, /* R1435 */
+ { 0x0000, 0x0000 }, /* R1436 */
+ { 0x0000, 0x0000 }, /* R1437 */
+ { 0x0000, 0x0000 }, /* R1438 */
+ { 0x0000, 0x0000 }, /* R1439 */
+ { 0x0000, 0x0000 }, /* R1440 */
+ { 0x0000, 0x0000 }, /* R1441 */
+ { 0x0000, 0x0000 }, /* R1442 */
+ { 0x0000, 0x0000 }, /* R1443 */
+ { 0x0000, 0x0000 }, /* R1444 */
+ { 0x0000, 0x0000 }, /* R1445 */
+ { 0x0000, 0x0000 }, /* R1446 */
+ { 0x0000, 0x0000 }, /* R1447 */
+ { 0x0000, 0x0000 }, /* R1448 */
+ { 0x0000, 0x0000 }, /* R1449 */
+ { 0x0000, 0x0000 }, /* R1450 */
+ { 0x0000, 0x0000 }, /* R1451 */
+ { 0x0000, 0x0000 }, /* R1452 */
+ { 0x0000, 0x0000 }, /* R1453 */
+ { 0x0000, 0x0000 }, /* R1454 */
+ { 0x0000, 0x0000 }, /* R1455 */
+ { 0x0000, 0x0000 }, /* R1456 */
+ { 0x0000, 0x0000 }, /* R1457 */
+ { 0x0000, 0x0000 }, /* R1458 */
+ { 0x0000, 0x0000 }, /* R1459 */
+ { 0x0000, 0x0000 }, /* R1460 */
+ { 0x0000, 0x0000 }, /* R1461 */
+ { 0x0000, 0x0000 }, /* R1462 */
+ { 0x0000, 0x0000 }, /* R1463 */
+ { 0x0000, 0x0000 }, /* R1464 */
+ { 0x0000, 0x0000 }, /* R1465 */
+ { 0x0000, 0x0000 }, /* R1466 */
+ { 0x0000, 0x0000 }, /* R1467 */
+ { 0x0000, 0x0000 }, /* R1468 */
+ { 0x0000, 0x0000 }, /* R1469 */
+ { 0x0000, 0x0000 }, /* R1470 */
+ { 0x0000, 0x0000 }, /* R1471 */
+ { 0x0000, 0x0000 }, /* R1472 */
+ { 0x0000, 0x0000 }, /* R1473 */
+ { 0x0000, 0x0000 }, /* R1474 */
+ { 0x0000, 0x0000 }, /* R1475 */
+ { 0x0000, 0x0000 }, /* R1476 */
+ { 0x0000, 0x0000 }, /* R1477 */
+ { 0x0000, 0x0000 }, /* R1478 */
+ { 0x0000, 0x0000 }, /* R1479 */
+ { 0x0000, 0x0000 }, /* R1480 */
+ { 0x0000, 0x0000 }, /* R1481 */
+ { 0x0000, 0x0000 }, /* R1482 */
+ { 0x0000, 0x0000 }, /* R1483 */
+ { 0x0000, 0x0000 }, /* R1484 */
+ { 0x0000, 0x0000 }, /* R1485 */
+ { 0x0000, 0x0000 }, /* R1486 */
+ { 0x0000, 0x0000 }, /* R1487 */
+ { 0x0000, 0x0000 }, /* R1488 */
+ { 0x0000, 0x0000 }, /* R1489 */
+ { 0x0000, 0x0000 }, /* R1490 */
+ { 0x0000, 0x0000 }, /* R1491 */
+ { 0x0000, 0x0000 }, /* R1492 */
+ { 0x0000, 0x0000 }, /* R1493 */
+ { 0x0000, 0x0000 }, /* R1494 */
+ { 0x0000, 0x0000 }, /* R1495 */
+ { 0x0000, 0x0000 }, /* R1496 */
+ { 0x0000, 0x0000 }, /* R1497 */
+ { 0x0000, 0x0000 }, /* R1498 */
+ { 0x0000, 0x0000 }, /* R1499 */
+ { 0x0000, 0x0000 }, /* R1500 */
+ { 0x0000, 0x0000 }, /* R1501 */
+ { 0x0000, 0x0000 }, /* R1502 */
+ { 0x0000, 0x0000 }, /* R1503 */
+ { 0x0000, 0x0000 }, /* R1504 */
+ { 0x0000, 0x0000 }, /* R1505 */
+ { 0x0000, 0x0000 }, /* R1506 */
+ { 0x0000, 0x0000 }, /* R1507 */
+ { 0x0000, 0x0000 }, /* R1508 */
+ { 0x0000, 0x0000 }, /* R1509 */
+ { 0x0000, 0x0000 }, /* R1510 */
+ { 0x0000, 0x0000 }, /* R1511 */
+ { 0x0000, 0x0000 }, /* R1512 */
+ { 0x0000, 0x0000 }, /* R1513 */
+ { 0x0000, 0x0000 }, /* R1514 */
+ { 0x0000, 0x0000 }, /* R1515 */
+ { 0x0000, 0x0000 }, /* R1516 */
+ { 0x0000, 0x0000 }, /* R1517 */
+ { 0x0000, 0x0000 }, /* R1518 */
+ { 0x0000, 0x0000 }, /* R1519 */
+ { 0x0000, 0x0000 }, /* R1520 */
+ { 0x0000, 0x0000 }, /* R1521 */
+ { 0x0000, 0x0000 }, /* R1522 */
+ { 0x0000, 0x0000 }, /* R1523 */
+ { 0x0000, 0x0000 }, /* R1524 */
+ { 0x0000, 0x0000 }, /* R1525 */
+ { 0x0000, 0x0000 }, /* R1526 */
+ { 0x0000, 0x0000 }, /* R1527 */
+ { 0x0000, 0x0000 }, /* R1528 */
+ { 0x0000, 0x0000 }, /* R1529 */
+ { 0x0000, 0x0000 }, /* R1530 */
+ { 0x0000, 0x0000 }, /* R1531 */
+ { 0x0000, 0x0000 }, /* R1532 */
+ { 0x0000, 0x0000 }, /* R1533 */
+ { 0x0000, 0x0000 }, /* R1534 */
+ { 0x0000, 0x0000 }, /* R1535 */
+ { 0x01EF, 0x01EF }, /* R1536 - DAC1 Mixer Volumes */
+ { 0x0037, 0x0037 }, /* R1537 - DAC1 Left Mixer Routing */
+ { 0x0037, 0x0037 }, /* R1538 - DAC1 Right Mixer Routing */
+ { 0x01EF, 0x01EF }, /* R1539 - DAC2 Mixer Volumes */
+ { 0x0037, 0x0037 }, /* R1540 - DAC2 Left Mixer Routing */
+ { 0x0037, 0x0037 }, /* R1541 - DAC2 Right Mixer Routing */
+ { 0x0003, 0x0003 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
+ { 0x0003, 0x0003 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0003, 0x0003 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
+ { 0x0003, 0x0003 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
+ { 0x0000, 0x0000 }, /* R1546 */
+ { 0x0000, 0x0000 }, /* R1547 */
+ { 0x0000, 0x0000 }, /* R1548 */
+ { 0x0000, 0x0000 }, /* R1549 */
+ { 0x0000, 0x0000 }, /* R1550 */
+ { 0x0000, 0x0000 }, /* R1551 */
+ { 0x02FF, 0x03FF }, /* R1552 - DAC1 Left Volume */
+ { 0x02FF, 0x03FF }, /* R1553 - DAC1 Right Volume */
+ { 0x02FF, 0x03FF }, /* R1554 - DAC2 Left Volume */
+ { 0x02FF, 0x03FF }, /* R1555 - DAC2 Right Volume */
+ { 0x0003, 0x0003 }, /* R1556 - DAC Softmute */
+ { 0x0000, 0x0000 }, /* R1557 */
+ { 0x0000, 0x0000 }, /* R1558 */
+ { 0x0000, 0x0000 }, /* R1559 */
+ { 0x0000, 0x0000 }, /* R1560 */
+ { 0x0000, 0x0000 }, /* R1561 */
+ { 0x0000, 0x0000 }, /* R1562 */
+ { 0x0000, 0x0000 }, /* R1563 */
+ { 0x0000, 0x0000 }, /* R1564 */
+ { 0x0000, 0x0000 }, /* R1565 */
+ { 0x0000, 0x0000 }, /* R1566 */
+ { 0x0000, 0x0000 }, /* R1567 */
+ { 0x0003, 0x0003 }, /* R1568 - Oversampling */
+ { 0x03C3, 0x03C3 }, /* R1569 - Sidetone */
};
static int wm8994_readable(unsigned int reg)
@@ -1902,8 +1900,6 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
return snd_soc_put_volsw(kcontrol, ucontrol);
}
-
-
static void wm8994_set_drc(struct snd_soc_codec *codec, int drc)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
@@ -1942,7 +1938,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994_pdata *pdata = wm8994->pdata;
int drc = wm8994_get_drc(kcontrol->id.name);
int value = ucontrol->value.integer.value[0];
@@ -2045,7 +2041,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994_pdata *pdata = wm8994->pdata;
int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
int value = ucontrol->value.integer.value[0];
@@ -2067,7 +2063,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec);
int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block];
@@ -2075,6 +2071,22 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
return 0;
}
+static const char *aifdac_src_text[] = {
+ "Left", "Right"
+};
+
+static const struct soc_enum aif1dacl_src =
+ SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aifdac_src_text);
+
+static const struct soc_enum aif1dacr_src =
+ SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aifdac_src_text);
+
+static const struct soc_enum aif2dacl_src =
+ SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aifdac_src_text);
+
+static const struct soc_enum aif2dacr_src =
+ SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aifdac_src_text);
+
static const struct snd_kcontrol_new wm8994_snd_controls[] = {
SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
WM8994_AIF1_ADC1_RIGHT_VOLUME,
@@ -2086,6 +2098,11 @@ SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME,
WM8994_AIF2_ADC_RIGHT_VOLUME,
1, 119, 0, digital_tlv),
+SOC_ENUM("AIF1DACL Source", aif1dacl_src),
+SOC_ENUM("AIF1DACR Source", aif1dacr_src),
+SOC_ENUM("AIF2DACL Source", aif1dacl_src),
+SOC_ENUM("AIF2DACR Source", aif1dacr_src),
+
SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME,
WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
@@ -2881,10 +2898,9 @@ static int wm8994_get_fll_config(struct fll_div *fll,
return 0;
}
-static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
+static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
unsigned int freq_in, unsigned int freq_out)
{
- struct snd_soc_codec *codec = dai->codec;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int reg_offset, ret;
struct fll_div fll;
@@ -2995,8 +3011,15 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
return 0;
}
+
static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
+static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
+ unsigned int freq_in, unsigned int freq_out)
+{
+ return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out);
+}
+
static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
@@ -3313,20 +3336,24 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
bclk_reg = WM8994_AIF1_BCLK;
rate_reg = WM8994_AIF1_RATE;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
- wm8994->lrclk_shared[0])
+ wm8994->lrclk_shared[0]) {
lrclk_reg = WM8994_AIF1DAC_LRCLK;
- else
+ } else {
lrclk_reg = WM8994_AIF1ADC_LRCLK;
+ dev_dbg(codec->dev, "AIF1 using split LRCLK\n");
+ }
break;
case 2:
aif1_reg = WM8994_AIF2_CONTROL_1;
bclk_reg = WM8994_AIF2_BCLK;
rate_reg = WM8994_AIF2_RATE;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
- wm8994->lrclk_shared[1])
+ wm8994->lrclk_shared[1]) {
lrclk_reg = WM8994_AIF2DAC_LRCLK;
- else
+ } else {
lrclk_reg = WM8994_AIF2ADC_LRCLK;
+ dev_dbg(codec->dev, "AIF2 using split LRCLK\n");
+ }
break;
default:
return -EINVAL;
@@ -3491,7 +3518,7 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate)
#define WM8994_RATES SNDRV_PCM_RATE_8000_96000
#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
- SNDRV_PCM_FMTBIT_S24_LE)
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
.set_sysclk = wm8994_set_dai_sysclk,
@@ -3515,9 +3542,9 @@ static struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
.set_tristate = wm8994_set_tristate,
};
-struct snd_soc_dai wm8994_dai[] = {
+static struct snd_soc_dai_driver wm8994_dai[] = {
{
- .name = "WM8994 AIF1",
+ .name = "wm8994-aif1",
.id = 1,
.playback = {
.stream_name = "AIF1 Playback",
@@ -3536,7 +3563,7 @@ struct snd_soc_dai wm8994_dai[] = {
.ops = &wm8994_aif1_dai_ops,
},
{
- .name = "WM8994 AIF2",
+ .name = "wm8994-aif2",
.id = 2,
.playback = {
.stream_name = "AIF2 Playback",
@@ -3555,7 +3582,7 @@ struct snd_soc_dai wm8994_dai[] = {
.ops = &wm8994_aif2_dai_ops,
},
{
- .name = "WM8994 AIF3",
+ .name = "wm8994-aif3",
.id = 3,
.playback = {
.stream_name = "AIF3 Playback",
@@ -3574,20 +3601,17 @@ struct snd_soc_dai wm8994_dai[] = {
.ops = &wm8994_aif3_dai_ops,
}
};
-EXPORT_SYMBOL_GPL(wm8994_dai);
#ifdef CONFIG_PM
-static int wm8994_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int i, ret;
for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i],
sizeof(struct fll_config));
- ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0);
+ ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0);
if (ret < 0)
dev_warn(codec->dev, "Failed to stop FLL%d: %d\n",
i + 1, ret);
@@ -3598,10 +3622,8 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int wm8994_resume(struct platform_device *pdev)
+static int wm8994_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int i, ret;
@@ -3630,7 +3652,7 @@ static int wm8994_resume(struct platform_device *pdev)
if (!wm8994->fll_suspend[i].out)
continue;
- ret = wm8994_set_fll(&codec->dai[0], i + 1,
+ ret = _wm8994_set_fll(codec, i + 1,
wm8994->fll_suspend[i].src,
wm8994->fll_suspend[i].in,
wm8994->fll_suspend[i].out);
@@ -3648,7 +3670,7 @@ static int wm8994_resume(struct platform_device *pdev)
static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
{
- struct snd_soc_codec *codec = &wm8994->codec;
+ struct snd_soc_codec *codec = wm8994->codec;
struct wm8994_pdata *pdata = wm8994->pdata;
struct snd_kcontrol_new controls[] = {
SOC_ENUM_EXT("AIF1.1 EQ Mode",
@@ -3706,16 +3728,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;
wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts;
- ret = snd_soc_add_controls(&wm8994->codec, controls,
+ ret = snd_soc_add_controls(wm8994->codec, controls,
ARRAY_SIZE(controls));
if (ret != 0)
- dev_err(wm8994->codec.dev,
+ dev_err(wm8994->codec->dev,
"Failed to add ReTune Mobile controls: %d\n", ret);
}
static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
{
- struct snd_soc_codec *codec = &wm8994->codec;
+ struct snd_soc_codec *codec = wm8994->codec;
struct wm8994_pdata *pdata = wm8994->pdata;
int ret, i;
@@ -3747,7 +3769,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
wm8994->drc_texts = kmalloc(sizeof(char *)
* pdata->num_drc_cfgs, GFP_KERNEL);
if (!wm8994->drc_texts) {
- dev_err(wm8994->codec.dev,
+ dev_err(wm8994->codec->dev,
"Failed to allocate %d DRC config texts\n",
pdata->num_drc_cfgs);
return;
@@ -3759,10 +3781,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
wm8994->drc_enum.max = pdata->num_drc_cfgs;
wm8994->drc_enum.texts = wm8994->drc_texts;
- ret = snd_soc_add_controls(&wm8994->codec, controls,
+ ret = snd_soc_add_controls(wm8994->codec, controls,
ARRAY_SIZE(controls));
if (ret != 0)
- dev_err(wm8994->codec.dev,
+ dev_err(wm8994->codec->dev,
"Failed to add DRC mode controls: %d\n", ret);
for (i = 0; i < WM8994_NUM_DRC; i++)
@@ -3775,62 +3797,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
if (pdata->num_retune_mobile_cfgs)
wm8994_handle_retune_mobile_pdata(wm8994);
else
- snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls,
+ snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
ARRAY_SIZE(wm8994_eq_controls));
}
-static int wm8994_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
-
- if (wm8994_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
- }
-
- socdev->card->codec = wm8994_codec;
- codec = wm8994_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- return ret;
- }
-
- wm8994_handle_pdata(snd_soc_codec_get_drvdata(codec));
-
- wm_hubs_add_analogue_controls(codec);
- snd_soc_add_controls(codec, wm8994_snd_controls,
- ARRAY_SIZE(wm8994_snd_controls));
- snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets,
- ARRAY_SIZE(wm8994_dapm_widgets));
- wm_hubs_add_analogue_routes(codec, 0, 0);
- snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
-
- return 0;
-}
-
-static int wm8994_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8994 = {
- .probe = wm8994_probe,
- .remove = wm8994_remove,
- .suspend = wm8994_suspend,
- .resume = wm8994_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
-
/**
* wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ
*
@@ -3842,7 +3812,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
*
* Enable microphone detection via IRQ on the WM8994. If GPIOs are
* being used to bring out signals to the processor then only platform
- * data configuration is needed for WM8903 and processor GPIOs should
+ * data configuration is needed for WM8994 and processor GPIOs should
* be configured using snd_soc_jack_add_gpios() instead.
*
* Configuration of detection levels is available via the micbias1_lvl
@@ -3889,7 +3859,7 @@ EXPORT_SYMBOL_GPL(wm8994_mic_detect);
static irqreturn_t wm8994_mic_irq(int irq, void *data)
{
struct wm8994_priv *priv = data;
- struct snd_soc_codec *codec = &priv->codec;
+ struct snd_soc_codec *codec = priv->codec;
int reg;
int report;
@@ -3921,46 +3891,22 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static int wm8994_codec_probe(struct platform_device *pdev)
+static int wm8994_codec_probe(struct snd_soc_codec *codec)
{
- int ret;
struct wm8994_priv *wm8994;
- struct snd_soc_codec *codec;
- int i;
+ int ret, i;
- if (wm8994_codec) {
- dev_err(&pdev->dev, "Another WM8994 is registered\n");
- return -EINVAL;
- }
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
- if (!wm8994) {
- dev_err(&pdev->dev, "Failed to allocate private data\n");
+ if (wm8994 == NULL)
return -ENOMEM;
- }
-
- codec = &wm8994->codec;
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
snd_soc_codec_set_drvdata(codec, wm8994);
- codec->control_data = dev_get_drvdata(pdev->dev.parent);
- codec->name = "WM8994";
- codec->owner = THIS_MODULE;
- codec->read = wm8994_read;
- codec->write = wm8994_write;
- codec->readable_register = wm8994_readable;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm8994_set_bias_level;
- codec->dai = &wm8994_dai[0];
- codec->num_dai = 3;
- codec->reg_cache_size = WM8994_MAX_REGISTER;
+
codec->reg_cache = &wm8994->reg_cache;
- codec->dev = &pdev->dev;
- wm8994->pdata = pdev->dev.parent->platform_data;
+ wm8994->pdata = dev_get_platdata(codec->dev->parent);
+ wm8994->codec = codec;
/* Fill the cache with physical values we inherited; don't reset */
ret = wm8994_bulk_read(codec->control_data, 0,
@@ -3996,25 +3942,25 @@ static int wm8994_codec_probe(struct platform_device *pdev)
ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
wm8994_mic_irq, "Mic 1 detect", wm8994);
if (ret != 0)
- dev_warn(&pdev->dev,
+ dev_warn(codec->dev,
"Failed to request Mic1 detect IRQ: %d\n", ret);
ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
wm8994_mic_irq, "Mic 1 short", wm8994);
if (ret != 0)
- dev_warn(&pdev->dev,
+ dev_warn(codec->dev,
"Failed to request Mic1 short IRQ: %d\n", ret);
ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
wm8994_mic_irq, "Mic 2 detect", wm8994);
if (ret != 0)
- dev_warn(&pdev->dev,
+ dev_warn(codec->dev,
"Failed to request Mic2 detect IRQ: %d\n", ret);
ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,
wm8994_mic_irq, "Mic 2 short", wm8994);
if (ret != 0)
- dev_warn(&pdev->dev,
+ dev_warn(codec->dev,
"Failed to request Mic2 short IRQ: %d\n", ret);
/* Remember if AIFnLRCLK is configured as a GPIO. This should be
@@ -4045,13 +3991,8 @@ static int wm8994_codec_probe(struct platform_device *pdev)
wm8994->lrclk_shared[1] = 0;
}
- for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++)
- wm8994_dai[i].dev = codec->dev;
-
wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- wm8994_codec = codec;
-
/* Latch volume updates (right only; we always do left then right). */
snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME,
WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU);
@@ -4088,24 +4029,18 @@ static int wm8994_codec_probe(struct platform_device *pdev)
wm8994_update_class_w(codec);
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err_irq;
- }
-
- ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
- goto err_codec;
- }
+ wm8994_handle_pdata(wm8994);
- platform_set_drvdata(pdev, wm8994);
+ wm_hubs_add_analogue_controls(codec);
+ snd_soc_add_controls(codec, wm8994_snd_controls,
+ ARRAY_SIZE(wm8994_snd_controls));
+ snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets,
+ ARRAY_SIZE(wm8994_dapm_widgets));
+ wm_hubs_add_analogue_routes(codec, 0, 0);
+ snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
return 0;
-err_codec:
- snd_soc_unregister_codec(codec);
err_irq:
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
@@ -4116,31 +4051,54 @@ err:
return ret;
}
-static int __devexit wm8994_codec_remove(struct platform_device *pdev)
+static int wm8994_codec_remove(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = &wm8994->codec;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
- snd_soc_unregister_codec(&wm8994->codec);
+
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
+ kfree(wm8994->retune_mobile_texts);
+ kfree(wm8994->drc_texts);
kfree(wm8994);
- wm8994_codec = NULL;
return 0;
}
+static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
+ .probe = wm8994_codec_probe,
+ .remove = wm8994_codec_remove,
+ .suspend = wm8994_suspend,
+ .resume = wm8994_resume,
+ .read = wm8994_read,
+ .write = wm8994_write,
+ .readable_register = wm8994_readable,
+ .volatile_register = wm8994_volatile,
+ .set_bias_level = wm8994_set_bias_level,
+};
+
+static int __devinit wm8994_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
+ wm8994_dai, ARRAY_SIZE(wm8994_dai));
+}
+
+static int __devexit wm8994_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
static struct platform_driver wm8994_codec_driver = {
.driver = {
.name = "wm8994-codec",
.owner = THIS_MODULE,
},
- .probe = wm8994_codec_probe,
- .remove = __devexit_p(wm8994_codec_remove),
+ .probe = wm8994_probe,
+ .remove = __devexit_p(wm8994_remove),
};
static __init int wm8994_init(void)
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 2e0ca67a8df7..d8dce260c430 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -11,9 +11,6 @@
#include <sound/soc.h>
-extern struct snd_soc_codec_device soc_codec_dev_wm8994;
-extern struct snd_soc_dai wm8994_dai[];
-
/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
#define WM8994_SYSCLK_MCLK1 1
#define WM8994_SYSCLK_MCLK2 2
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 76b37ff6c264..ecc7c37180c7 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -156,7 +156,8 @@ static struct {
};
struct wm9081_priv {
- struct snd_soc_codec codec;
+ enum snd_soc_control_type control_type;
+ void *control_data;
u16 reg_cache[WM9081_MAX_REGISTER + 1];
int sysclk_source;
int mclk_rate;
@@ -1212,8 +1213,8 @@ static struct snd_soc_dai_ops wm9081_dai_ops = {
/* We report two channels because the CODEC processes a stereo signal, even
* though it is only capable of handling a mono output.
*/
-struct snd_soc_dai wm9081_dai = {
- .name = "WM9081",
+static struct snd_soc_dai_driver wm9081_dai = {
+ .name = "wm9081-hifi",
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -1223,34 +1224,42 @@ struct snd_soc_dai wm9081_dai = {
},
.ops = &wm9081_dai_ops,
};
-EXPORT_SYMBOL_GPL(wm9081_dai);
-
-static struct snd_soc_codec *wm9081_codec;
-
-static int wm9081_probe(struct platform_device *pdev)
+static int wm9081_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct wm9081_priv *wm9081;
- int ret = 0;
+ struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+ u16 reg;
- if (wm9081_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
+ codec->control_data = wm9081->control_data;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
- socdev->card->codec = wm9081_codec;
- codec = wm9081_codec;
- wm9081 = snd_soc_codec_get_drvdata(codec);
+ reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
+ if (reg != 0x9081) {
+ dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
+ ret = -EINVAL;
+ return ret;
+ }
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+ ret = wm9081_reset(codec);
if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
+ dev_err(codec->dev, "Failed to issue reset\n");
+ return ret;
}
+ wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ /* Enable zero cross by default */
+ reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
+ snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
+ reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
+ snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
+ reg | WM9081_SPKPGAZC);
+
snd_soc_add_controls(codec, wm9081_snd_controls,
ARRAY_SIZE(wm9081_snd_controls));
if (!wm9081->retune) {
@@ -1265,40 +1274,28 @@ static int wm9081_probe(struct platform_device *pdev)
snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
return ret;
-
-pcm_err:
- return ret;
}
-static int wm9081_remove(struct platform_device *pdev)
+static int wm9081_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
+ wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
#ifdef CONFIG_PM
-static int wm9081_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm9081_resume(struct platform_device *pdev)
+static int wm9081_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
u16 *reg_cache = codec->reg_cache;
int i;
- for (i = 0; i < codec->reg_cache_size; i++) {
+ for (i = 0; i < codec->driver->reg_cache_size; i++) {
if (i == WM9081_SOFTWARE_RESET)
continue;
@@ -1314,133 +1311,43 @@ static int wm9081_resume(struct platform_device *pdev)
#define wm9081_resume NULL
#endif
-struct snd_soc_codec_device soc_codec_dev_wm9081 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
.probe = wm9081_probe,
.remove = wm9081_remove,
.suspend = wm9081_suspend,
.resume = wm9081_resume,
+ .set_bias_level = wm9081_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm9081_reg_defaults,
+ .volatile_register = wm9081_volatile_register,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081);
-
-static int wm9081_register(struct wm9081_priv *wm9081,
- enum snd_soc_control_type control)
-{
- struct snd_soc_codec *codec = &wm9081->codec;
- int ret;
- u16 reg;
-
- if (wm9081_codec) {
- dev_err(codec->dev, "Another WM9081 is registered\n");
- ret = -EINVAL;
- goto err;
- }
-
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- snd_soc_codec_set_drvdata(codec, wm9081);
- codec->name = "WM9081";
- codec->owner = THIS_MODULE;
- codec->dai = &wm9081_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache);
- codec->reg_cache = &wm9081->reg_cache;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm9081_set_bias_level;
- codec->volatile_register = wm9081_volatile_register;
-
- memcpy(codec->reg_cache, wm9081_reg_defaults,
- sizeof(wm9081_reg_defaults));
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
-
- reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
- if (reg != 0x9081) {
- dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
- ret = -EINVAL;
- goto err;
- }
-
- ret = wm9081_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- goto err;
- }
-
- wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- /* Enable zero cross by default */
- reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
- snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
- reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
- snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
- reg | WM9081_SPKPGAZC);
-
- wm9081_dai.dev = codec->dev;
-
- wm9081_codec = codec;
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
- }
-
- ret = snd_soc_register_dai(&wm9081_dai);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
- goto err_codec;
- }
-
- return 0;
-
-err_codec:
- snd_soc_unregister_codec(codec);
-err:
- kfree(wm9081);
- return ret;
-}
-
-static void wm9081_unregister(struct wm9081_priv *wm9081)
-{
- wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF);
- snd_soc_unregister_dai(&wm9081_dai);
- snd_soc_unregister_codec(&wm9081->codec);
- kfree(wm9081);
- wm9081_codec = NULL;
-}
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm9081_priv *wm9081;
- struct snd_soc_codec *codec;
+ int ret;
wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
if (wm9081 == NULL)
return -ENOMEM;
- codec = &wm9081->codec;
- codec->hw_write = (hw_write_t)i2c_master_send;
- wm9081->retune = i2c->dev.platform_data;
-
i2c_set_clientdata(i2c, wm9081);
- codec->control_data = i2c;
-
- codec->dev = &i2c->dev;
+ wm9081->control_data = i2c;
- return wm9081_register(wm9081, SND_SOC_I2C);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm9081, &wm9081_dai, 1);
+ if (ret < 0)
+ kfree(wm9081);
+ return ret;
}
static __devexit int wm9081_i2c_remove(struct i2c_client *client)
{
- struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
- wm9081_unregister(wm9081);
+ snd_soc_unregister_codec(&client->dev);
+ kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1452,31 +1359,34 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
static struct i2c_driver wm9081_i2c_driver = {
.driver = {
- .name = "wm9081",
+ .name = "wm9081-codec",
.owner = THIS_MODULE,
},
.probe = wm9081_i2c_probe,
.remove = __devexit_p(wm9081_i2c_remove),
.id_table = wm9081_i2c_id,
};
+#endif
static int __init wm9081_modinit(void)
{
- int ret;
-
+ int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm9081_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
ret);
}
-
+#endif
return ret;
}
module_init(wm9081_modinit);
static void __exit wm9081_exit(void)
{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm9081_i2c_driver);
+#endif
}
module_exit(wm9081_exit);
diff --git a/sound/soc/codecs/wm9081.h b/sound/soc/codecs/wm9081.h
index 42d3bc757021..871cccb066dc 100644
--- a/sound/soc/codecs/wm9081.h
+++ b/sound/soc/codecs/wm9081.h
@@ -15,9 +15,6 @@
#include <sound/soc.h>
-extern struct snd_soc_dai wm9081_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm9081;
-
/*
* SYSCLK sources
*/
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 1592250daec0..99c046ba46bb 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -34,8 +34,6 @@
#include "wm9090.h"
-static struct snd_soc_codec *wm9090_codec;
-
static const u16 wm9090_reg_defaults[] = {
0x9093, /* R0 - Software Reset */
0x0006, /* R1 - Power Management (1) */
@@ -142,15 +140,10 @@ static const u16 wm9090_reg_defaults[] = {
/* This struct is used to save the context */
struct wm9090_priv {
- /* We're not really registering as a CODEC since ASoC core
- * does not yet support multiple CODECs but having the CODEC
- * structure means we can reuse some of the ASoC core
- * features.
- */
- struct snd_soc_codec codec;
struct mutex mutex;
u16 reg_cache[WM9090_MAX_REGISTER + 1];
struct wm9090_platform_data pdata;
+ void *control_data;
};
static int wm9090_volatile(unsigned int reg)
@@ -523,7 +516,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) {
/* Restore the register cache */
- for (i = 1; i < codec->reg_cache_size; i++) {
+ for (i = 1; i < codec->driver->reg_cache_size; i++) {
if (reg_cache[i] == wm9090_reg_defaults[i])
continue;
if (wm9090_volatile(i))
@@ -556,51 +549,67 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm9090_probe(struct platform_device *pdev)
+static int wm9090_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- int ret = 0;
+ struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
+ int ret;
- if (wm9090_codec == NULL) {
- dev_err(&pdev->dev, "Codec device not registered\n");
- return -ENODEV;
+ codec->control_data = wm9090->control_data;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
}
- socdev->card->codec = wm9090_codec;
- codec = wm9090_codec;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- dev_err(codec->dev, "failed to create pcms: %d\n", ret);
- goto pcm_err;
+ ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
+ if (ret < 0)
+ return ret;
+ if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
+ dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
+ return -EINVAL;
}
+ ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
+ if (ret < 0)
+ return ret;
+
+ /* Configure some defaults; they will be written out when we
+ * bring the bias up.
+ */
+ wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
+ | WM9090_IN1A_ZC;
+ wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
+ | WM9090_IN1B_ZC;
+ wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
+ | WM9090_IN2A_ZC;
+ wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
+ | WM9090_IN2B_ZC;
+ wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
+ WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
+ wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
+ WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
+ wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
+ WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
+
+ wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
+
+ wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
wm9090_add_controls(codec);
return 0;
-
-pcm_err:
- return ret;
}
#ifdef CONFIG_PM
-static int wm9090_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm9090_resume(struct platform_device *pdev)
+static int wm9090_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -610,29 +619,29 @@ static int wm9090_resume(struct platform_device *pdev)
#define wm9090_resume NULL
#endif
-static int wm9090_remove(struct platform_device *pdev)
+static int wm9090_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_wm9090 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
.probe = wm9090_probe,
.remove = wm9090_remove,
.suspend = wm9090_suspend,
.resume = wm9090_resume,
+ .set_bias_level = wm9090_set_bias_level,
+ .reg_cache_size = (WM9090_MAX_REGISTER + 1),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = wm9090_reg_defaults,
+ .volatile_register = wm9090_volatile,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9090);
static int wm9090_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm9090_priv *wm9090;
- struct snd_soc_codec *codec;
int ret;
wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL);
@@ -640,102 +649,28 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
dev_err(&i2c->dev, "Can not allocate memory\n");
return -ENOMEM;
}
- codec = &wm9090->codec;
if (i2c->dev.platform_data)
memcpy(&wm9090->pdata, i2c->dev.platform_data,
sizeof(wm9090->pdata));
- wm9090_codec = codec;
-
i2c_set_clientdata(i2c, wm9090);
+ wm9090->control_data = i2c;
+ mutex_init(&wm9090->mutex);
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->control_data = i2c;
- snd_soc_codec_set_drvdata(codec, wm9090);
- codec->dev = &i2c->dev;
- codec->name = "WM9090";
- codec->owner = THIS_MODULE;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->set_bias_level = wm9090_set_bias_level,
- codec->reg_cache_size = WM9090_MAX_REGISTER + 1;
- codec->reg_cache = &wm9090->reg_cache;
- codec->volatile_register = wm9090_volatile;
-
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
-
- memcpy(&wm9090->reg_cache, wm9090_reg_defaults,
- sizeof(wm9090->reg_cache));
-
- ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
- if (ret < 0)
- goto err;
- if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
- dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret);
- ret = -EINVAL;
- goto err;
- }
-
- ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm9090, NULL, 0);
if (ret < 0)
- goto err;
-
- /* Configure some defaults; they will be written out when we
- * bring the bias up.
- */
- wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
- | WM9090_IN1A_ZC;
- wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
- | WM9090_IN1B_ZC;
- wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
- | WM9090_IN2A_ZC;
- wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
- | WM9090_IN2B_ZC;
- wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
- WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
- wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
- WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
- wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
- WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
-
- wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
-
- wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- ret = snd_soc_register_codec(codec);
- if (ret != 0) {
- dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- goto err_bias;
- }
-
- return 0;
-
-err_bias:
- wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
-err:
- kfree(wm9090);
- i2c_set_clientdata(i2c, NULL);
- wm9090_codec = NULL;
-
+ kfree(wm9090);
return ret;
}
-static int wm9090_i2c_remove(struct i2c_client *i2c)
+static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
{
struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
- struct snd_soc_codec *codec = &wm9090->codec;
- snd_soc_unregister_codec(codec);
- wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ snd_soc_unregister_codec(&i2c->dev);
kfree(wm9090);
- wm9090_codec = NULL;
return 0;
}
@@ -748,7 +683,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id);
static struct i2c_driver wm9090_i2c_driver = {
.driver = {
- .name = "wm9090",
+ .name = "wm9090-codec",
.owner = THIS_MODULE,
},
.probe = wm9090_i2c_probe,
diff --git a/sound/soc/codecs/wm9090.h b/sound/soc/codecs/wm9090.h
index b08eab932a5b..29b9d9fc70b4 100644
--- a/sound/soc/codecs/wm9090.h
+++ b/sound/soc/codecs/wm9090.h
@@ -23,8 +23,6 @@
#ifndef __WM9090_H
#define __WM9090_H
-extern struct snd_soc_codec_device soc_codec_dev_wm9090;
-
/*
* Register values.
*/
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 8793341849d1..a144acda751c 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -248,8 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
int reg;
u16 vra;
@@ -273,9 +272,9 @@ static struct snd_soc_dai_ops wm9705_dai_ops = {
.prepare = ac97_prepare,
};
-struct snd_soc_dai wm9705_dai[] = {
+static struct snd_soc_dai_driver wm9705_dai[] = {
{
- .name = "AC97 HiFi",
+ .name = "wm9705-hifi",
.ac97_control = 1,
.playback = {
.stream_name = "HiFi Playback",
@@ -294,7 +293,7 @@ struct snd_soc_dai wm9705_dai[] = {
.ops = &wm9705_dai_ops,
},
{
- .name = "AC97 Aux",
+ .name = "wm9705-aux",
.playback = {
.stream_name = "Aux Playback",
.channels_min = 1,
@@ -304,7 +303,6 @@ struct snd_soc_dai wm9705_dai[] = {
},
}
};
-EXPORT_SYMBOL_GPL(wm9705_dai);
static int wm9705_reset(struct snd_soc_codec *codec)
{
@@ -318,20 +316,15 @@ static int wm9705_reset(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
return 0;
}
-static int wm9705_soc_resume(struct platform_device *pdev)
+static int wm9705_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i, ret;
u16 *cache = codec->reg_cache;
@@ -352,49 +345,18 @@ static int wm9705_soc_resume(struct platform_device *pdev)
#define wm9705_soc_resume NULL
#endif
-static int wm9705_soc_probe(struct platform_device *pdev)
+static int wm9705_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
int ret = 0;
printk(KERN_INFO "WM9705 SoC Audio Codec\n");
- socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
- GFP_KERNEL);
- if (socdev->card->codec == NULL)
- return -ENOMEM;
- codec = socdev->card->codec;
- mutex_init(&codec->mutex);
-
- codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- ret = -ENOMEM;
- goto cache_err;
- }
- codec->reg_cache_size = sizeof(wm9705_reg);
- codec->reg_cache_step = 2;
-
- codec->name = "WM9705";
- codec->owner = THIS_MODULE;
- codec->dai = wm9705_dai;
- codec->num_dai = ARRAY_SIZE(wm9705_dai);
- codec->write = ac97_write;
- codec->read = ac97_read;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0) {
printk(KERN_ERR "wm9705: failed to register AC97 codec\n");
- goto codec_err;
+ return ret;
}
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0)
- goto pcm_err;
-
ret = wm9705_reset(codec);
if (ret)
goto reset_err;
@@ -406,40 +368,62 @@ static int wm9705_soc_probe(struct platform_device *pdev)
return 0;
reset_err:
- snd_soc_free_pcms(socdev);
-pcm_err:
snd_soc_free_ac97_codec(codec);
-codec_err:
- kfree(codec->reg_cache);
-cache_err:
- kfree(socdev->card->codec);
- socdev->card->codec = NULL;
return ret;
}
-static int wm9705_soc_remove(struct platform_device *pdev)
+static int wm9705_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec == NULL)
- return 0;
-
- snd_soc_dapm_free(socdev);
- snd_soc_free_pcms(socdev);
snd_soc_free_ac97_codec(codec);
- kfree(codec->reg_cache);
- kfree(codec);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_wm9705 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9705 = {
.probe = wm9705_soc_probe,
.remove = wm9705_soc_remove,
.suspend = wm9705_soc_suspend,
.resume = wm9705_soc_resume,
+ .read = ac97_read,
+ .write = ac97_write,
+ .reg_cache_size = ARRAY_SIZE(wm9705_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_step = 2,
+ .reg_cache_default = wm9705_reg,
+};
+
+static __devinit int wm9705_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai));
+}
+
+static int __devexit wm9705_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver wm9705_codec_driver = {
+ .driver = {
+ .name = "wm9705-codec",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = wm9705_probe,
+ .remove = __devexit_p(wm9705_remove),
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705);
+
+static int __init wm9705_init(void)
+{
+ return platform_driver_register(&wm9705_codec_driver);
+}
+module_init(wm9705_init);
+
+static void __exit wm9705_exit(void)
+{
+ platform_driver_unregister(&wm9705_codec_driver);
+}
+module_exit(wm9705_exit);
MODULE_DESCRIPTION("ASoC WM9705 driver");
MODULE_AUTHOR("Ian Molton");
diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h
index d380f110f9e2..23ea9ce47359 100644
--- a/sound/soc/codecs/wm9705.h
+++ b/sound/soc/codecs/wm9705.h
@@ -8,7 +8,4 @@
#define WM9705_DAI_AC97_HIFI 0
#define WM9705_DAI_AC97_AUX 1
-extern struct snd_soc_dai wm9705_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_wm9705;
-
#endif
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 28790a2ffe8d..d2f224d62744 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -478,8 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec =rtd->codec;
int reg;
u16 vra;
@@ -499,8 +498,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->card->codec;
+ struct snd_soc_codec *codec = rtd->codec;
u16 vra, xsle;
vra = ac97_read(codec, AC97_EXTENDED_STATUS);
@@ -526,9 +524,9 @@ static struct snd_soc_dai_ops wm9712_dai_ops_aux = {
.prepare = ac97_aux_prepare,
};
-struct snd_soc_dai wm9712_dai[] = {
+static struct snd_soc_dai_driver wm9712_dai[] = {
{
- .name = "AC97 HiFi",
+ .name = "wm9712-hifi",
.ac97_control = 1,
.playback = {
.stream_name = "HiFi Playback",
@@ -545,7 +543,7 @@ struct snd_soc_dai wm9712_dai[] = {
.ops = &wm9712_dai_ops_hifi,
},
{
- .name = "AC97 Aux",
+ .name = "wm9712-aux",
.playback = {
.stream_name = "Aux Playback",
.channels_min = 1,
@@ -555,7 +553,6 @@ struct snd_soc_dai wm9712_dai[] = {
.ops = &wm9712_dai_ops_aux,
}
};
-EXPORT_SYMBOL_GPL(wm9712_dai);
static int wm9712_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
@@ -597,20 +594,15 @@ err:
return -EIO;
}
-static int wm9712_soc_suspend(struct platform_device *pdev,
+static int wm9712_soc_suspend(struct snd_soc_codec *codec,
pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
-static int wm9712_soc_resume(struct platform_device *pdev)
+static int wm9712_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
int i, ret;
u16 *cache = codec->reg_cache;
@@ -635,51 +627,18 @@ static int wm9712_soc_resume(struct platform_device *pdev)
return ret;
}
-static int wm9712_soc_probe(struct platform_device *pdev)
+static int wm9712_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
int ret = 0;
printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
- socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
- GFP_KERNEL);
- if (socdev->card->codec == NULL)
- return -ENOMEM;
- codec = socdev->card->codec;
- mutex_init(&codec->mutex);
-
- codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL);
-
- if (codec->reg_cache == NULL) {
- ret = -ENOMEM;
- goto cache_err;
- }
- codec->reg_cache_size = sizeof(wm9712_reg);
- codec->reg_cache_step = 2;
-
- codec->name = "WM9712";
- codec->owner = THIS_MODULE;
- codec->dai = wm9712_dai;
- codec->num_dai = ARRAY_SIZE(wm9712_dai);
- codec->write = ac97_write;
- codec->read = ac97_read;
- codec->set_bias_level = wm9712_set_bias_level;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0) {
printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
- goto codec_err;
+ return ret;
}
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0)
- goto pcm_err;
-
ret = wm9712_reset(codec, 0);
if (ret < 0) {
printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n");
@@ -697,42 +656,63 @@ static int wm9712_soc_probe(struct platform_device *pdev)
return 0;
reset_err:
- snd_soc_free_pcms(socdev);
-pcm_err:
snd_soc_free_ac97_codec(codec);
-
-codec_err:
- kfree(codec->reg_cache);
-
-cache_err:
- kfree(socdev->card->codec);
- socdev->card->codec = NULL;
return ret;
}
-static int wm9712_soc_remove(struct platform_device *pdev)
+static int wm9712_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec == NULL)
- return 0;
-
- snd_soc_dapm_free(socdev);
- snd_soc_free_pcms(socdev);
snd_soc_free_ac97_codec(codec);
- kfree(codec->reg_cache);
- kfree(codec);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_wm9712 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
.probe = wm9712_soc_probe,
.remove = wm9712_soc_remove,
.suspend = wm9712_soc_suspend,
.resume = wm9712_soc_resume,
+ .read = ac97_read,
+ .write = ac97_write,
+ .set_bias_level = wm9712_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm9712_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_step = 2,
+ .reg_cache_default = wm9712_reg,
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
+
+static __devinit int wm9712_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai));
+}
+
+static int __devexit wm9712_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver wm9712_codec_driver = {
+ .driver = {
+ .name = "wm9712-codec",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = wm9712_probe,
+ .remove = __devexit_p(wm9712_remove),
+};
+
+static int __init wm9712_init(void)
+{
+ return platform_driver_register(&wm9712_codec_driver);
+}
+module_init(wm9712_init);
+
+static void __exit wm9712_exit(void)
+{
+ platform_driver_unregister(&wm9712_codec_driver);
+}
+module_exit(wm9712_exit);
MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h
index d29e8a18ca6d..fb69c3aa4ed0 100644
--- a/sound/soc/codecs/wm9712.h
+++ b/sound/soc/codecs/wm9712.h
@@ -8,7 +8,4 @@
#define WM9712_DAI_AC97_HIFI 0
#define WM9712_DAI_AC97_AUX 1
-extern struct snd_soc_dai wm9712_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_wm9712;
-
#endif
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 34e0c91092fa..7da13b07a53d 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1057,9 +1057,9 @@ static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
.set_tristate = wm9713_set_dai_tristate,
};
-struct snd_soc_dai wm9713_dai[] = {
+static struct snd_soc_dai_driver wm9713_dai[] = {
{
- .name = "AC97 HiFi",
+ .name = "wm9713-hifi",
.ac97_control = 1,
.playback = {
.stream_name = "HiFi Playback",
@@ -1076,7 +1076,7 @@ struct snd_soc_dai wm9713_dai[] = {
.ops = &wm9713_dai_ops_hifi,
},
{
- .name = "AC97 Aux",
+ .name = "wm9713-aux",
.playback = {
.stream_name = "Aux Playback",
.channels_min = 1,
@@ -1086,7 +1086,7 @@ struct snd_soc_dai wm9713_dai[] = {
.ops = &wm9713_dai_ops_aux,
},
{
- .name = "WM9713 Voice",
+ .name = "wm9713-voice",
.playback = {
.stream_name = "Voice Playback",
.channels_min = 1,
@@ -1103,7 +1103,6 @@ struct snd_soc_dai wm9713_dai[] = {
.symmetric_rates = 1,
},
};
-EXPORT_SYMBOL_GPL(wm9713_dai);
int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
{
@@ -1152,11 +1151,9 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm9713_soc_suspend(struct platform_device *pdev,
+static int wm9713_soc_suspend(struct snd_soc_codec *codec,
pm_message_t state)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
u16 reg;
/* Disable everything except touchpanel - that will be handled
@@ -1171,10 +1168,8 @@ static int wm9713_soc_suspend(struct platform_device *pdev,
return 0;
}
-static int wm9713_soc_resume(struct platform_device *pdev)
+static int wm9713_soc_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
int i, ret;
u16 *cache = codec->reg_cache;
@@ -1204,53 +1199,20 @@ static int wm9713_soc_resume(struct platform_device *pdev)
return ret;
}
-static int wm9713_soc_probe(struct platform_device *pdev)
+static int wm9713_soc_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
+ struct wm9713_priv *wm9713;
int ret = 0, reg;
- socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
- GFP_KERNEL);
- if (socdev->card->codec == NULL)
+ wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL);
+ if (wm9713 == NULL)
return -ENOMEM;
- codec = socdev->card->codec;
- mutex_init(&codec->mutex);
-
- codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL);
- if (codec->reg_cache == NULL) {
- ret = -ENOMEM;
- goto cache_err;
- }
- codec->reg_cache_size = sizeof(wm9713_reg);
- codec->reg_cache_step = 2;
-
- snd_soc_codec_set_drvdata(codec, kzalloc(sizeof(struct wm9713_priv),
- GFP_KERNEL));
- if (snd_soc_codec_get_drvdata(codec) == NULL) {
- ret = -ENOMEM;
- goto priv_err;
- }
-
- codec->name = "WM9713";
- codec->owner = THIS_MODULE;
- codec->dai = wm9713_dai;
- codec->num_dai = ARRAY_SIZE(wm9713_dai);
- codec->write = ac97_write;
- codec->read = ac97_read;
- codec->set_bias_level = wm9713_set_bias_level;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
+ snd_soc_codec_set_drvdata(codec, wm9713);
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0)
goto codec_err;
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0)
- goto pcm_err;
-
/* do a cold reset for the controller and then try
* a warm reset followed by an optional cold reset for codec */
wm9713_reset(codec, 0);
@@ -1273,46 +1235,67 @@ static int wm9713_soc_probe(struct platform_device *pdev)
return 0;
reset_err:
- snd_soc_free_pcms(socdev);
-pcm_err:
snd_soc_free_ac97_codec(codec);
-
codec_err:
- kfree(snd_soc_codec_get_drvdata(codec));
-
-priv_err:
- kfree(codec->reg_cache);
-
-cache_err:
- kfree(socdev->card->codec);
- socdev->card->codec = NULL;
+ kfree(wm9713);
return ret;
}
-static int wm9713_soc_remove(struct platform_device *pdev)
+static int wm9713_soc_remove(struct snd_soc_codec *codec)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->card->codec;
-
- if (codec == NULL)
- return 0;
-
- snd_soc_dapm_free(socdev);
- snd_soc_free_pcms(socdev);
+ struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
snd_soc_free_ac97_codec(codec);
- kfree(snd_soc_codec_get_drvdata(codec));
- kfree(codec->reg_cache);
- kfree(codec);
+ kfree(wm9713);
return 0;
}
-struct snd_soc_codec_device soc_codec_dev_wm9713 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
.probe = wm9713_soc_probe,
.remove = wm9713_soc_remove,
.suspend = wm9713_soc_suspend,
.resume = wm9713_soc_resume,
+ .read = ac97_read,
+ .write = ac97_write,
+ .set_bias_level = wm9713_set_bias_level,
+ .reg_cache_size = ARRAY_SIZE(wm9713_reg),
+ .reg_word_size = sizeof(u16),
+ .reg_cache_step = 2,
+ .reg_cache_default = wm9713_reg,
+};
+
+static __devinit int wm9713_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
+}
+
+static int __devexit wm9713_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver wm9713_codec_driver = {
+ .driver = {
+ .name = "wm9713-codec",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = wm9713_probe,
+ .remove = __devexit_p(wm9713_remove),
};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713);
+
+static int __init wm9713_init(void)
+{
+ return platform_driver_register(&wm9713_codec_driver);
+}
+module_init(wm9713_init);
+
+static void __exit wm9713_exit(void)
+{
+ platform_driver_unregister(&wm9713_codec_driver);
+}
+module_exit(wm9713_exit);
MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
index 63b8d81756e3..793da863a03d 100644
--- a/sound/soc/codecs/wm9713.h
+++ b/sound/soc/codecs/wm9713.h
@@ -45,9 +45,6 @@
#define WM9713_DAI_AC97_AUX 1
#define WM9713_DAI_PCM_VOICE 2
-extern struct snd_soc_codec_device soc_codec_dev_wm9713;
-extern struct snd_soc_dai wm9713_dai[3];
-
int wm9713_reset(struct snd_soc_codec *codec, int try_warm);
#endif
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 2cb81538cd91..19ca782ac970 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -123,7 +123,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
break;
default:
- WARN(1, "Unknown DCS readback method");
+ WARN(1, "Unknown DCS readback method\n");
break;
}