1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2d5315a23SMark Brown /* 3d5315a23SMark Brown * wm2200.c -- WM2200 ALSA SoC Audio driver 4d5315a23SMark Brown * 5d5315a23SMark Brown * Copyright 2012 Wolfson Microelectronics plc 6d5315a23SMark Brown * 7d5315a23SMark Brown * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 8d5315a23SMark Brown */ 9d5315a23SMark Brown 10d5315a23SMark Brown #include <linux/module.h> 11d5315a23SMark Brown #include <linux/moduleparam.h> 12d5315a23SMark Brown #include <linux/init.h> 13d5315a23SMark Brown #include <linux/delay.h> 14d5315a23SMark Brown #include <linux/pm.h> 15e10f8711SMark Brown #include <linux/firmware.h> 16d5315a23SMark Brown #include <linux/gcd.h> 17d5315a23SMark Brown #include <linux/gpio.h> 18d5315a23SMark Brown #include <linux/i2c.h> 19d5315a23SMark Brown #include <linux/pm_runtime.h> 20d5315a23SMark Brown #include <linux/regulator/consumer.h> 21d5315a23SMark Brown #include <linux/regulator/fixed.h> 22d5315a23SMark Brown #include <linux/slab.h> 23d5315a23SMark Brown #include <sound/core.h> 24d5315a23SMark Brown #include <sound/pcm.h> 25d5315a23SMark Brown #include <sound/pcm_params.h> 26d5315a23SMark Brown #include <sound/soc.h> 27d5315a23SMark Brown #include <sound/jack.h> 28d5315a23SMark Brown #include <sound/initval.h> 29d5315a23SMark Brown #include <sound/tlv.h> 30d5315a23SMark Brown #include <sound/wm2200.h> 31d5315a23SMark Brown 32d5315a23SMark Brown #include "wm2200.h" 33f017eb29SMark Brown #include "wm_adsp.h" 34e10f8711SMark Brown 35e10f8711SMark Brown #define WM2200_DSP_CONTROL_1 0x00 36e10f8711SMark Brown #define WM2200_DSP_CONTROL_2 0x02 37e10f8711SMark Brown #define WM2200_DSP_CONTROL_3 0x03 38e10f8711SMark Brown #define WM2200_DSP_CONTROL_4 0x04 39e10f8711SMark Brown #define WM2200_DSP_CONTROL_5 0x06 40e10f8711SMark Brown #define WM2200_DSP_CONTROL_6 0x07 41e10f8711SMark Brown #define WM2200_DSP_CONTROL_7 0x08 42e10f8711SMark Brown #define WM2200_DSP_CONTROL_8 0x09 43e10f8711SMark Brown #define WM2200_DSP_CONTROL_9 0x0A 44e10f8711SMark Brown #define WM2200_DSP_CONTROL_10 0x0B 45e10f8711SMark Brown #define WM2200_DSP_CONTROL_11 0x0C 46e10f8711SMark Brown #define WM2200_DSP_CONTROL_12 0x0D 47e10f8711SMark Brown #define WM2200_DSP_CONTROL_13 0x0F 48e10f8711SMark Brown #define WM2200_DSP_CONTROL_14 0x10 49e10f8711SMark Brown #define WM2200_DSP_CONTROL_15 0x11 50e10f8711SMark Brown #define WM2200_DSP_CONTROL_16 0x12 51e10f8711SMark Brown #define WM2200_DSP_CONTROL_17 0x13 52e10f8711SMark Brown #define WM2200_DSP_CONTROL_18 0x14 53e10f8711SMark Brown #define WM2200_DSP_CONTROL_19 0x16 54e10f8711SMark Brown #define WM2200_DSP_CONTROL_20 0x17 55e10f8711SMark Brown #define WM2200_DSP_CONTROL_21 0x18 56e10f8711SMark Brown #define WM2200_DSP_CONTROL_22 0x1A 57e10f8711SMark Brown #define WM2200_DSP_CONTROL_23 0x1B 58e10f8711SMark Brown #define WM2200_DSP_CONTROL_24 0x1C 59e10f8711SMark Brown #define WM2200_DSP_CONTROL_25 0x1E 60e10f8711SMark Brown #define WM2200_DSP_CONTROL_26 0x20 61e10f8711SMark Brown #define WM2200_DSP_CONTROL_27 0x21 62e10f8711SMark Brown #define WM2200_DSP_CONTROL_28 0x22 63e10f8711SMark Brown #define WM2200_DSP_CONTROL_29 0x23 64e10f8711SMark Brown #define WM2200_DSP_CONTROL_30 0x24 65e10f8711SMark Brown #define WM2200_DSP_CONTROL_31 0x26 66d5315a23SMark Brown 67d5315a23SMark Brown /* The code assumes DCVDD is generated internally */ 68d5315a23SMark Brown #define WM2200_NUM_CORE_SUPPLIES 2 69d5315a23SMark Brown static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = { 70d5315a23SMark Brown "DBVDD", 71d5315a23SMark Brown "LDOVDD", 72d5315a23SMark Brown }; 73d5315a23SMark Brown 74d5315a23SMark Brown /* codec private data */ 75d5315a23SMark Brown struct wm2200_priv { 76f017eb29SMark Brown struct wm_adsp dsp[2]; 77d5315a23SMark Brown struct regmap *regmap; 78d5315a23SMark Brown struct device *dev; 79908b5308SKuninori Morimoto struct snd_soc_component *component; 80d5315a23SMark Brown struct wm2200_pdata pdata; 81d5315a23SMark Brown struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES]; 82d5315a23SMark Brown 83d5315a23SMark Brown struct completion fll_lock; 84d5315a23SMark Brown int fll_fout; 85d5315a23SMark Brown int fll_fref; 86d5315a23SMark Brown int fll_src; 87d5315a23SMark Brown 88d5315a23SMark Brown int rev; 89d5315a23SMark Brown int sysclk; 900e2d95aaSKuninori Morimoto 910e2d95aaSKuninori Morimoto unsigned int symmetric_rates:1; 92d5315a23SMark Brown }; 93d5315a23SMark Brown 94eae2328dSMark Brown #define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1) 95eae2328dSMark Brown #define WM2200_DSP_SPACING 12288 96eae2328dSMark Brown 97eae2328dSMark Brown #define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING)) 98eae2328dSMark Brown #define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING)) 99eae2328dSMark Brown #define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING)) 100eae2328dSMark Brown #define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING)) 101eae2328dSMark Brown #define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING)) 102eae2328dSMark Brown #define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING)) 103eae2328dSMark Brown 104eae2328dSMark Brown static const struct regmap_range_cfg wm2200_ranges[] = { 10598744829SMark Brown { .name = "DSP1DM", .range_min = WM2200_DSP1_DM_BASE, 106eae2328dSMark Brown .range_max = WM2200_DSP1_DM_BASE + 12287, 107eae2328dSMark Brown .selector_reg = WM2200_DSP1_CONTROL_3, 108eae2328dSMark Brown .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK, 109eae2328dSMark Brown .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT, 110eae2328dSMark Brown .window_start = WM2200_DSP1_DM_0, .window_len = 2048, }, 111eae2328dSMark Brown 11298744829SMark Brown { .name = "DSP1PM", .range_min = WM2200_DSP1_PM_BASE, 113eae2328dSMark Brown .range_max = WM2200_DSP1_PM_BASE + 12287, 114eae2328dSMark Brown .selector_reg = WM2200_DSP1_CONTROL_2, 115eae2328dSMark Brown .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK, 116eae2328dSMark Brown .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT, 117eae2328dSMark Brown .window_start = WM2200_DSP1_PM_0, .window_len = 768, }, 118eae2328dSMark Brown 11998744829SMark Brown { .name = "DSP1ZM", .range_min = WM2200_DSP1_ZM_BASE, 120eae2328dSMark Brown .range_max = WM2200_DSP1_ZM_BASE + 2047, 121eae2328dSMark Brown .selector_reg = WM2200_DSP1_CONTROL_4, 122eae2328dSMark Brown .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK, 123eae2328dSMark Brown .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT, 124eae2328dSMark Brown .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, }, 125eae2328dSMark Brown 12698744829SMark Brown { .name = "DSP2DM", .range_min = WM2200_DSP2_DM_BASE, 127eae2328dSMark Brown .range_max = WM2200_DSP2_DM_BASE + 4095, 128eae2328dSMark Brown .selector_reg = WM2200_DSP2_CONTROL_3, 129eae2328dSMark Brown .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK, 130eae2328dSMark Brown .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT, 131eae2328dSMark Brown .window_start = WM2200_DSP2_DM_0, .window_len = 2048, }, 132eae2328dSMark Brown 13398744829SMark Brown { .name = "DSP2PM", .range_min = WM2200_DSP2_PM_BASE, 134eae2328dSMark Brown .range_max = WM2200_DSP2_PM_BASE + 11287, 135eae2328dSMark Brown .selector_reg = WM2200_DSP2_CONTROL_2, 136eae2328dSMark Brown .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK, 137eae2328dSMark Brown .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT, 138eae2328dSMark Brown .window_start = WM2200_DSP2_PM_0, .window_len = 768, }, 139eae2328dSMark Brown 14098744829SMark Brown { .name = "DSP2ZM", .range_min = WM2200_DSP2_ZM_BASE, 141eae2328dSMark Brown .range_max = WM2200_DSP2_ZM_BASE + 2047, 142eae2328dSMark Brown .selector_reg = WM2200_DSP2_CONTROL_4, 143eae2328dSMark Brown .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK, 144eae2328dSMark Brown .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT, 145eae2328dSMark Brown .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, }, 146eae2328dSMark Brown }; 147eae2328dSMark Brown 1485beb8eeaSSimon Trimmer static const struct cs_dsp_region wm2200_dsp1_regions[] = { 149f017eb29SMark Brown { .type = WMFW_ADSP1_PM, .base = WM2200_DSP1_PM_BASE }, 150f017eb29SMark Brown { .type = WMFW_ADSP1_DM, .base = WM2200_DSP1_DM_BASE }, 151f017eb29SMark Brown { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP1_ZM_BASE }, 152f017eb29SMark Brown }; 153f017eb29SMark Brown 1545beb8eeaSSimon Trimmer static const struct cs_dsp_region wm2200_dsp2_regions[] = { 155f017eb29SMark Brown { .type = WMFW_ADSP1_PM, .base = WM2200_DSP2_PM_BASE }, 156f017eb29SMark Brown { .type = WMFW_ADSP1_DM, .base = WM2200_DSP2_DM_BASE }, 157f017eb29SMark Brown { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE }, 158f017eb29SMark Brown }; 159f017eb29SMark Brown 160c418a84aSAxel Lin static const struct reg_default wm2200_reg_defaults[] = { 161d5315a23SMark Brown { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */ 162d5315a23SMark Brown { 0x0102, 0x0000 }, /* R258 - Clocking 3 */ 163d5315a23SMark Brown { 0x0103, 0x0011 }, /* R259 - Clocking 4 */ 164d5315a23SMark Brown { 0x0111, 0x0000 }, /* R273 - FLL Control 1 */ 165d5315a23SMark Brown { 0x0112, 0x0000 }, /* R274 - FLL Control 2 */ 166d5315a23SMark Brown { 0x0113, 0x0000 }, /* R275 - FLL Control 3 */ 167d5315a23SMark Brown { 0x0114, 0x0000 }, /* R276 - FLL Control 4 */ 168d5315a23SMark Brown { 0x0116, 0x0177 }, /* R278 - FLL Control 6 */ 169d5315a23SMark Brown { 0x0117, 0x0004 }, /* R279 - FLL Control 7 */ 170d5315a23SMark Brown { 0x0119, 0x0000 }, /* R281 - FLL EFS 1 */ 171d5315a23SMark Brown { 0x011A, 0x0002 }, /* R282 - FLL EFS 2 */ 172d5315a23SMark Brown { 0x0200, 0x0000 }, /* R512 - Mic Charge Pump 1 */ 173d5315a23SMark Brown { 0x0201, 0x03FF }, /* R513 - Mic Charge Pump 2 */ 174d5315a23SMark Brown { 0x0202, 0x9BDE }, /* R514 - DM Charge Pump 1 */ 175d5315a23SMark Brown { 0x020C, 0x0000 }, /* R524 - Mic Bias Ctrl 1 */ 176d5315a23SMark Brown { 0x020D, 0x0000 }, /* R525 - Mic Bias Ctrl 2 */ 177d5315a23SMark Brown { 0x020F, 0x0000 }, /* R527 - Ear Piece Ctrl 1 */ 178d5315a23SMark Brown { 0x0210, 0x0000 }, /* R528 - Ear Piece Ctrl 2 */ 179d5315a23SMark Brown { 0x0301, 0x0000 }, /* R769 - Input Enables */ 180d5315a23SMark Brown { 0x0302, 0x2240 }, /* R770 - IN1L Control */ 181d5315a23SMark Brown { 0x0303, 0x0040 }, /* R771 - IN1R Control */ 182d5315a23SMark Brown { 0x0304, 0x2240 }, /* R772 - IN2L Control */ 183d5315a23SMark Brown { 0x0305, 0x0040 }, /* R773 - IN2R Control */ 184d5315a23SMark Brown { 0x0306, 0x2240 }, /* R774 - IN3L Control */ 185d5315a23SMark Brown { 0x0307, 0x0040 }, /* R775 - IN3R Control */ 186d5315a23SMark Brown { 0x030A, 0x0000 }, /* R778 - RXANC_SRC */ 187d5315a23SMark Brown { 0x030B, 0x0022 }, /* R779 - Input Volume Ramp */ 188d5315a23SMark Brown { 0x030C, 0x0180 }, /* R780 - ADC Digital Volume 1L */ 189d5315a23SMark Brown { 0x030D, 0x0180 }, /* R781 - ADC Digital Volume 1R */ 190d5315a23SMark Brown { 0x030E, 0x0180 }, /* R782 - ADC Digital Volume 2L */ 191d5315a23SMark Brown { 0x030F, 0x0180 }, /* R783 - ADC Digital Volume 2R */ 192d5315a23SMark Brown { 0x0310, 0x0180 }, /* R784 - ADC Digital Volume 3L */ 193d5315a23SMark Brown { 0x0311, 0x0180 }, /* R785 - ADC Digital Volume 3R */ 194d5315a23SMark Brown { 0x0400, 0x0000 }, /* R1024 - Output Enables */ 195d5315a23SMark Brown { 0x0401, 0x0000 }, /* R1025 - DAC Volume Limit 1L */ 196d5315a23SMark Brown { 0x0402, 0x0000 }, /* R1026 - DAC Volume Limit 1R */ 197d5315a23SMark Brown { 0x0403, 0x0000 }, /* R1027 - DAC Volume Limit 2L */ 198d5315a23SMark Brown { 0x0404, 0x0000 }, /* R1028 - DAC Volume Limit 2R */ 199d5315a23SMark Brown { 0x0409, 0x0000 }, /* R1033 - DAC AEC Control 1 */ 200d5315a23SMark Brown { 0x040A, 0x0022 }, /* R1034 - Output Volume Ramp */ 201d5315a23SMark Brown { 0x040B, 0x0180 }, /* R1035 - DAC Digital Volume 1L */ 202d5315a23SMark Brown { 0x040C, 0x0180 }, /* R1036 - DAC Digital Volume 1R */ 203d5315a23SMark Brown { 0x040D, 0x0180 }, /* R1037 - DAC Digital Volume 2L */ 204d5315a23SMark Brown { 0x040E, 0x0180 }, /* R1038 - DAC Digital Volume 2R */ 205d5315a23SMark Brown { 0x0417, 0x0069 }, /* R1047 - PDM 1 */ 206d5315a23SMark Brown { 0x0418, 0x0000 }, /* R1048 - PDM 2 */ 207d5315a23SMark Brown { 0x0500, 0x0000 }, /* R1280 - Audio IF 1_1 */ 208d5315a23SMark Brown { 0x0501, 0x0008 }, /* R1281 - Audio IF 1_2 */ 209d5315a23SMark Brown { 0x0502, 0x0000 }, /* R1282 - Audio IF 1_3 */ 210d5315a23SMark Brown { 0x0503, 0x0000 }, /* R1283 - Audio IF 1_4 */ 211d5315a23SMark Brown { 0x0504, 0x0000 }, /* R1284 - Audio IF 1_5 */ 212d5315a23SMark Brown { 0x0505, 0x0001 }, /* R1285 - Audio IF 1_6 */ 213d5315a23SMark Brown { 0x0506, 0x0001 }, /* R1286 - Audio IF 1_7 */ 214d5315a23SMark Brown { 0x0507, 0x0000 }, /* R1287 - Audio IF 1_8 */ 215d5315a23SMark Brown { 0x0508, 0x0000 }, /* R1288 - Audio IF 1_9 */ 216d5315a23SMark Brown { 0x0509, 0x0000 }, /* R1289 - Audio IF 1_10 */ 217d5315a23SMark Brown { 0x050A, 0x0000 }, /* R1290 - Audio IF 1_11 */ 218d5315a23SMark Brown { 0x050B, 0x0000 }, /* R1291 - Audio IF 1_12 */ 219d5315a23SMark Brown { 0x050C, 0x0000 }, /* R1292 - Audio IF 1_13 */ 220d5315a23SMark Brown { 0x050D, 0x0000 }, /* R1293 - Audio IF 1_14 */ 221d5315a23SMark Brown { 0x050E, 0x0000 }, /* R1294 - Audio IF 1_15 */ 222d5315a23SMark Brown { 0x050F, 0x0000 }, /* R1295 - Audio IF 1_16 */ 223d5315a23SMark Brown { 0x0510, 0x0000 }, /* R1296 - Audio IF 1_17 */ 224d5315a23SMark Brown { 0x0511, 0x0000 }, /* R1297 - Audio IF 1_18 */ 225d5315a23SMark Brown { 0x0512, 0x0000 }, /* R1298 - Audio IF 1_19 */ 226d5315a23SMark Brown { 0x0513, 0x0000 }, /* R1299 - Audio IF 1_20 */ 227d5315a23SMark Brown { 0x0514, 0x0000 }, /* R1300 - Audio IF 1_21 */ 228d5315a23SMark Brown { 0x0515, 0x0001 }, /* R1301 - Audio IF 1_22 */ 229d5315a23SMark Brown { 0x0600, 0x0000 }, /* R1536 - OUT1LMIX Input 1 Source */ 230d5315a23SMark Brown { 0x0601, 0x0080 }, /* R1537 - OUT1LMIX Input 1 Volume */ 231d5315a23SMark Brown { 0x0602, 0x0000 }, /* R1538 - OUT1LMIX Input 2 Source */ 232d5315a23SMark Brown { 0x0603, 0x0080 }, /* R1539 - OUT1LMIX Input 2 Volume */ 233d5315a23SMark Brown { 0x0604, 0x0000 }, /* R1540 - OUT1LMIX Input 3 Source */ 234d5315a23SMark Brown { 0x0605, 0x0080 }, /* R1541 - OUT1LMIX Input 3 Volume */ 235d5315a23SMark Brown { 0x0606, 0x0000 }, /* R1542 - OUT1LMIX Input 4 Source */ 236d5315a23SMark Brown { 0x0607, 0x0080 }, /* R1543 - OUT1LMIX Input 4 Volume */ 237d5315a23SMark Brown { 0x0608, 0x0000 }, /* R1544 - OUT1RMIX Input 1 Source */ 238d5315a23SMark Brown { 0x0609, 0x0080 }, /* R1545 - OUT1RMIX Input 1 Volume */ 239d5315a23SMark Brown { 0x060A, 0x0000 }, /* R1546 - OUT1RMIX Input 2 Source */ 240d5315a23SMark Brown { 0x060B, 0x0080 }, /* R1547 - OUT1RMIX Input 2 Volume */ 241d5315a23SMark Brown { 0x060C, 0x0000 }, /* R1548 - OUT1RMIX Input 3 Source */ 242d5315a23SMark Brown { 0x060D, 0x0080 }, /* R1549 - OUT1RMIX Input 3 Volume */ 243d5315a23SMark Brown { 0x060E, 0x0000 }, /* R1550 - OUT1RMIX Input 4 Source */ 244d5315a23SMark Brown { 0x060F, 0x0080 }, /* R1551 - OUT1RMIX Input 4 Volume */ 245d5315a23SMark Brown { 0x0610, 0x0000 }, /* R1552 - OUT2LMIX Input 1 Source */ 246d5315a23SMark Brown { 0x0611, 0x0080 }, /* R1553 - OUT2LMIX Input 1 Volume */ 247d5315a23SMark Brown { 0x0612, 0x0000 }, /* R1554 - OUT2LMIX Input 2 Source */ 248d5315a23SMark Brown { 0x0613, 0x0080 }, /* R1555 - OUT2LMIX Input 2 Volume */ 249d5315a23SMark Brown { 0x0614, 0x0000 }, /* R1556 - OUT2LMIX Input 3 Source */ 250d5315a23SMark Brown { 0x0615, 0x0080 }, /* R1557 - OUT2LMIX Input 3 Volume */ 251d5315a23SMark Brown { 0x0616, 0x0000 }, /* R1558 - OUT2LMIX Input 4 Source */ 252d5315a23SMark Brown { 0x0617, 0x0080 }, /* R1559 - OUT2LMIX Input 4 Volume */ 253d5315a23SMark Brown { 0x0618, 0x0000 }, /* R1560 - OUT2RMIX Input 1 Source */ 254d5315a23SMark Brown { 0x0619, 0x0080 }, /* R1561 - OUT2RMIX Input 1 Volume */ 255d5315a23SMark Brown { 0x061A, 0x0000 }, /* R1562 - OUT2RMIX Input 2 Source */ 256d5315a23SMark Brown { 0x061B, 0x0080 }, /* R1563 - OUT2RMIX Input 2 Volume */ 257d5315a23SMark Brown { 0x061C, 0x0000 }, /* R1564 - OUT2RMIX Input 3 Source */ 258d5315a23SMark Brown { 0x061D, 0x0080 }, /* R1565 - OUT2RMIX Input 3 Volume */ 259d5315a23SMark Brown { 0x061E, 0x0000 }, /* R1566 - OUT2RMIX Input 4 Source */ 260d5315a23SMark Brown { 0x061F, 0x0080 }, /* R1567 - OUT2RMIX Input 4 Volume */ 261d5315a23SMark Brown { 0x0620, 0x0000 }, /* R1568 - AIF1TX1MIX Input 1 Source */ 262d5315a23SMark Brown { 0x0621, 0x0080 }, /* R1569 - AIF1TX1MIX Input 1 Volume */ 263d5315a23SMark Brown { 0x0622, 0x0000 }, /* R1570 - AIF1TX1MIX Input 2 Source */ 264d5315a23SMark Brown { 0x0623, 0x0080 }, /* R1571 - AIF1TX1MIX Input 2 Volume */ 265d5315a23SMark Brown { 0x0624, 0x0000 }, /* R1572 - AIF1TX1MIX Input 3 Source */ 266d5315a23SMark Brown { 0x0625, 0x0080 }, /* R1573 - AIF1TX1MIX Input 3 Volume */ 267d5315a23SMark Brown { 0x0626, 0x0000 }, /* R1574 - AIF1TX1MIX Input 4 Source */ 268d5315a23SMark Brown { 0x0627, 0x0080 }, /* R1575 - AIF1TX1MIX Input 4 Volume */ 269d5315a23SMark Brown { 0x0628, 0x0000 }, /* R1576 - AIF1TX2MIX Input 1 Source */ 270d5315a23SMark Brown { 0x0629, 0x0080 }, /* R1577 - AIF1TX2MIX Input 1 Volume */ 271d5315a23SMark Brown { 0x062A, 0x0000 }, /* R1578 - AIF1TX2MIX Input 2 Source */ 272d5315a23SMark Brown { 0x062B, 0x0080 }, /* R1579 - AIF1TX2MIX Input 2 Volume */ 273d5315a23SMark Brown { 0x062C, 0x0000 }, /* R1580 - AIF1TX2MIX Input 3 Source */ 274d5315a23SMark Brown { 0x062D, 0x0080 }, /* R1581 - AIF1TX2MIX Input 3 Volume */ 275d5315a23SMark Brown { 0x062E, 0x0000 }, /* R1582 - AIF1TX2MIX Input 4 Source */ 276d5315a23SMark Brown { 0x062F, 0x0080 }, /* R1583 - AIF1TX2MIX Input 4 Volume */ 277d5315a23SMark Brown { 0x0630, 0x0000 }, /* R1584 - AIF1TX3MIX Input 1 Source */ 278d5315a23SMark Brown { 0x0631, 0x0080 }, /* R1585 - AIF1TX3MIX Input 1 Volume */ 279d5315a23SMark Brown { 0x0632, 0x0000 }, /* R1586 - AIF1TX3MIX Input 2 Source */ 280d5315a23SMark Brown { 0x0633, 0x0080 }, /* R1587 - AIF1TX3MIX Input 2 Volume */ 281d5315a23SMark Brown { 0x0634, 0x0000 }, /* R1588 - AIF1TX3MIX Input 3 Source */ 282d5315a23SMark Brown { 0x0635, 0x0080 }, /* R1589 - AIF1TX3MIX Input 3 Volume */ 283d5315a23SMark Brown { 0x0636, 0x0000 }, /* R1590 - AIF1TX3MIX Input 4 Source */ 284d5315a23SMark Brown { 0x0637, 0x0080 }, /* R1591 - AIF1TX3MIX Input 4 Volume */ 285d5315a23SMark Brown { 0x0638, 0x0000 }, /* R1592 - AIF1TX4MIX Input 1 Source */ 286d5315a23SMark Brown { 0x0639, 0x0080 }, /* R1593 - AIF1TX4MIX Input 1 Volume */ 287d5315a23SMark Brown { 0x063A, 0x0000 }, /* R1594 - AIF1TX4MIX Input 2 Source */ 288d5315a23SMark Brown { 0x063B, 0x0080 }, /* R1595 - AIF1TX4MIX Input 2 Volume */ 289d5315a23SMark Brown { 0x063C, 0x0000 }, /* R1596 - AIF1TX4MIX Input 3 Source */ 290d5315a23SMark Brown { 0x063D, 0x0080 }, /* R1597 - AIF1TX4MIX Input 3 Volume */ 291d5315a23SMark Brown { 0x063E, 0x0000 }, /* R1598 - AIF1TX4MIX Input 4 Source */ 292d5315a23SMark Brown { 0x063F, 0x0080 }, /* R1599 - AIF1TX4MIX Input 4 Volume */ 293d5315a23SMark Brown { 0x0640, 0x0000 }, /* R1600 - AIF1TX5MIX Input 1 Source */ 294d5315a23SMark Brown { 0x0641, 0x0080 }, /* R1601 - AIF1TX5MIX Input 1 Volume */ 295d5315a23SMark Brown { 0x0642, 0x0000 }, /* R1602 - AIF1TX5MIX Input 2 Source */ 296d5315a23SMark Brown { 0x0643, 0x0080 }, /* R1603 - AIF1TX5MIX Input 2 Volume */ 297d5315a23SMark Brown { 0x0644, 0x0000 }, /* R1604 - AIF1TX5MIX Input 3 Source */ 298d5315a23SMark Brown { 0x0645, 0x0080 }, /* R1605 - AIF1TX5MIX Input 3 Volume */ 299d5315a23SMark Brown { 0x0646, 0x0000 }, /* R1606 - AIF1TX5MIX Input 4 Source */ 300d5315a23SMark Brown { 0x0647, 0x0080 }, /* R1607 - AIF1TX5MIX Input 4 Volume */ 301d5315a23SMark Brown { 0x0648, 0x0000 }, /* R1608 - AIF1TX6MIX Input 1 Source */ 302d5315a23SMark Brown { 0x0649, 0x0080 }, /* R1609 - AIF1TX6MIX Input 1 Volume */ 303d5315a23SMark Brown { 0x064A, 0x0000 }, /* R1610 - AIF1TX6MIX Input 2 Source */ 304d5315a23SMark Brown { 0x064B, 0x0080 }, /* R1611 - AIF1TX6MIX Input 2 Volume */ 305d5315a23SMark Brown { 0x064C, 0x0000 }, /* R1612 - AIF1TX6MIX Input 3 Source */ 306d5315a23SMark Brown { 0x064D, 0x0080 }, /* R1613 - AIF1TX6MIX Input 3 Volume */ 307d5315a23SMark Brown { 0x064E, 0x0000 }, /* R1614 - AIF1TX6MIX Input 4 Source */ 308d5315a23SMark Brown { 0x064F, 0x0080 }, /* R1615 - AIF1TX6MIX Input 4 Volume */ 309d5315a23SMark Brown { 0x0650, 0x0000 }, /* R1616 - EQLMIX Input 1 Source */ 310d5315a23SMark Brown { 0x0651, 0x0080 }, /* R1617 - EQLMIX Input 1 Volume */ 311d5315a23SMark Brown { 0x0652, 0x0000 }, /* R1618 - EQLMIX Input 2 Source */ 312d5315a23SMark Brown { 0x0653, 0x0080 }, /* R1619 - EQLMIX Input 2 Volume */ 313d5315a23SMark Brown { 0x0654, 0x0000 }, /* R1620 - EQLMIX Input 3 Source */ 314d5315a23SMark Brown { 0x0655, 0x0080 }, /* R1621 - EQLMIX Input 3 Volume */ 315d5315a23SMark Brown { 0x0656, 0x0000 }, /* R1622 - EQLMIX Input 4 Source */ 316d5315a23SMark Brown { 0x0657, 0x0080 }, /* R1623 - EQLMIX Input 4 Volume */ 317d5315a23SMark Brown { 0x0658, 0x0000 }, /* R1624 - EQRMIX Input 1 Source */ 318d5315a23SMark Brown { 0x0659, 0x0080 }, /* R1625 - EQRMIX Input 1 Volume */ 319d5315a23SMark Brown { 0x065A, 0x0000 }, /* R1626 - EQRMIX Input 2 Source */ 320d5315a23SMark Brown { 0x065B, 0x0080 }, /* R1627 - EQRMIX Input 2 Volume */ 321d5315a23SMark Brown { 0x065C, 0x0000 }, /* R1628 - EQRMIX Input 3 Source */ 322d5315a23SMark Brown { 0x065D, 0x0080 }, /* R1629 - EQRMIX Input 3 Volume */ 323d5315a23SMark Brown { 0x065E, 0x0000 }, /* R1630 - EQRMIX Input 4 Source */ 324d5315a23SMark Brown { 0x065F, 0x0080 }, /* R1631 - EQRMIX Input 4 Volume */ 325d5315a23SMark Brown { 0x0660, 0x0000 }, /* R1632 - LHPF1MIX Input 1 Source */ 326d5315a23SMark Brown { 0x0661, 0x0080 }, /* R1633 - LHPF1MIX Input 1 Volume */ 327d5315a23SMark Brown { 0x0662, 0x0000 }, /* R1634 - LHPF1MIX Input 2 Source */ 328d5315a23SMark Brown { 0x0663, 0x0080 }, /* R1635 - LHPF1MIX Input 2 Volume */ 329d5315a23SMark Brown { 0x0664, 0x0000 }, /* R1636 - LHPF1MIX Input 3 Source */ 330d5315a23SMark Brown { 0x0665, 0x0080 }, /* R1637 - LHPF1MIX Input 3 Volume */ 331d5315a23SMark Brown { 0x0666, 0x0000 }, /* R1638 - LHPF1MIX Input 4 Source */ 332d5315a23SMark Brown { 0x0667, 0x0080 }, /* R1639 - LHPF1MIX Input 4 Volume */ 333d5315a23SMark Brown { 0x0668, 0x0000 }, /* R1640 - LHPF2MIX Input 1 Source */ 334d5315a23SMark Brown { 0x0669, 0x0080 }, /* R1641 - LHPF2MIX Input 1 Volume */ 335d5315a23SMark Brown { 0x066A, 0x0000 }, /* R1642 - LHPF2MIX Input 2 Source */ 336d5315a23SMark Brown { 0x066B, 0x0080 }, /* R1643 - LHPF2MIX Input 2 Volume */ 337d5315a23SMark Brown { 0x066C, 0x0000 }, /* R1644 - LHPF2MIX Input 3 Source */ 338d5315a23SMark Brown { 0x066D, 0x0080 }, /* R1645 - LHPF2MIX Input 3 Volume */ 339d5315a23SMark Brown { 0x066E, 0x0000 }, /* R1646 - LHPF2MIX Input 4 Source */ 340d5315a23SMark Brown { 0x066F, 0x0080 }, /* R1647 - LHPF2MIX Input 4 Volume */ 341d5315a23SMark Brown { 0x0670, 0x0000 }, /* R1648 - DSP1LMIX Input 1 Source */ 342d5315a23SMark Brown { 0x0671, 0x0080 }, /* R1649 - DSP1LMIX Input 1 Volume */ 343d5315a23SMark Brown { 0x0672, 0x0000 }, /* R1650 - DSP1LMIX Input 2 Source */ 344d5315a23SMark Brown { 0x0673, 0x0080 }, /* R1651 - DSP1LMIX Input 2 Volume */ 345d5315a23SMark Brown { 0x0674, 0x0000 }, /* R1652 - DSP1LMIX Input 3 Source */ 346d5315a23SMark Brown { 0x0675, 0x0080 }, /* R1653 - DSP1LMIX Input 3 Volume */ 347d5315a23SMark Brown { 0x0676, 0x0000 }, /* R1654 - DSP1LMIX Input 4 Source */ 348d5315a23SMark Brown { 0x0677, 0x0080 }, /* R1655 - DSP1LMIX Input 4 Volume */ 349d5315a23SMark Brown { 0x0678, 0x0000 }, /* R1656 - DSP1RMIX Input 1 Source */ 350d5315a23SMark Brown { 0x0679, 0x0080 }, /* R1657 - DSP1RMIX Input 1 Volume */ 351d5315a23SMark Brown { 0x067A, 0x0000 }, /* R1658 - DSP1RMIX Input 2 Source */ 352d5315a23SMark Brown { 0x067B, 0x0080 }, /* R1659 - DSP1RMIX Input 2 Volume */ 353d5315a23SMark Brown { 0x067C, 0x0000 }, /* R1660 - DSP1RMIX Input 3 Source */ 354d5315a23SMark Brown { 0x067D, 0x0080 }, /* R1661 - DSP1RMIX Input 3 Volume */ 355d5315a23SMark Brown { 0x067E, 0x0000 }, /* R1662 - DSP1RMIX Input 4 Source */ 356d5315a23SMark Brown { 0x067F, 0x0080 }, /* R1663 - DSP1RMIX Input 4 Volume */ 357d5315a23SMark Brown { 0x0680, 0x0000 }, /* R1664 - DSP1AUX1MIX Input 1 Source */ 358d5315a23SMark Brown { 0x0681, 0x0000 }, /* R1665 - DSP1AUX2MIX Input 1 Source */ 359d5315a23SMark Brown { 0x0682, 0x0000 }, /* R1666 - DSP1AUX3MIX Input 1 Source */ 360d5315a23SMark Brown { 0x0683, 0x0000 }, /* R1667 - DSP1AUX4MIX Input 1 Source */ 361d5315a23SMark Brown { 0x0684, 0x0000 }, /* R1668 - DSP1AUX5MIX Input 1 Source */ 362d5315a23SMark Brown { 0x0685, 0x0000 }, /* R1669 - DSP1AUX6MIX Input 1 Source */ 363d5315a23SMark Brown { 0x0686, 0x0000 }, /* R1670 - DSP2LMIX Input 1 Source */ 364d5315a23SMark Brown { 0x0687, 0x0080 }, /* R1671 - DSP2LMIX Input 1 Volume */ 365d5315a23SMark Brown { 0x0688, 0x0000 }, /* R1672 - DSP2LMIX Input 2 Source */ 366d5315a23SMark Brown { 0x0689, 0x0080 }, /* R1673 - DSP2LMIX Input 2 Volume */ 367d5315a23SMark Brown { 0x068A, 0x0000 }, /* R1674 - DSP2LMIX Input 3 Source */ 368d5315a23SMark Brown { 0x068B, 0x0080 }, /* R1675 - DSP2LMIX Input 3 Volume */ 369d5315a23SMark Brown { 0x068C, 0x0000 }, /* R1676 - DSP2LMIX Input 4 Source */ 370d5315a23SMark Brown { 0x068D, 0x0080 }, /* R1677 - DSP2LMIX Input 4 Volume */ 371d5315a23SMark Brown { 0x068E, 0x0000 }, /* R1678 - DSP2RMIX Input 1 Source */ 372d5315a23SMark Brown { 0x068F, 0x0080 }, /* R1679 - DSP2RMIX Input 1 Volume */ 373d5315a23SMark Brown { 0x0690, 0x0000 }, /* R1680 - DSP2RMIX Input 2 Source */ 374d5315a23SMark Brown { 0x0691, 0x0080 }, /* R1681 - DSP2RMIX Input 2 Volume */ 375d5315a23SMark Brown { 0x0692, 0x0000 }, /* R1682 - DSP2RMIX Input 3 Source */ 376d5315a23SMark Brown { 0x0693, 0x0080 }, /* R1683 - DSP2RMIX Input 3 Volume */ 377d5315a23SMark Brown { 0x0694, 0x0000 }, /* R1684 - DSP2RMIX Input 4 Source */ 378d5315a23SMark Brown { 0x0695, 0x0080 }, /* R1685 - DSP2RMIX Input 4 Volume */ 379d5315a23SMark Brown { 0x0696, 0x0000 }, /* R1686 - DSP2AUX1MIX Input 1 Source */ 380d5315a23SMark Brown { 0x0697, 0x0000 }, /* R1687 - DSP2AUX2MIX Input 1 Source */ 381d5315a23SMark Brown { 0x0698, 0x0000 }, /* R1688 - DSP2AUX3MIX Input 1 Source */ 382d5315a23SMark Brown { 0x0699, 0x0000 }, /* R1689 - DSP2AUX4MIX Input 1 Source */ 383d5315a23SMark Brown { 0x069A, 0x0000 }, /* R1690 - DSP2AUX5MIX Input 1 Source */ 384d5315a23SMark Brown { 0x069B, 0x0000 }, /* R1691 - DSP2AUX6MIX Input 1 Source */ 385d5315a23SMark Brown { 0x0700, 0xA101 }, /* R1792 - GPIO CTRL 1 */ 386d5315a23SMark Brown { 0x0701, 0xA101 }, /* R1793 - GPIO CTRL 2 */ 387d5315a23SMark Brown { 0x0702, 0xA101 }, /* R1794 - GPIO CTRL 3 */ 388d5315a23SMark Brown { 0x0703, 0xA101 }, /* R1795 - GPIO CTRL 4 */ 389d5315a23SMark Brown { 0x0709, 0x0000 }, /* R1801 - Misc Pad Ctrl 1 */ 390d5315a23SMark Brown { 0x0801, 0x00FF }, /* R2049 - Interrupt Status 1 Mask */ 391d5315a23SMark Brown { 0x0804, 0xFFFF }, /* R2052 - Interrupt Status 2 Mask */ 392d5315a23SMark Brown { 0x0808, 0x0000 }, /* R2056 - Interrupt Control */ 393d5315a23SMark Brown { 0x0900, 0x0000 }, /* R2304 - EQL_1 */ 394d5315a23SMark Brown { 0x0901, 0x0000 }, /* R2305 - EQL_2 */ 395d5315a23SMark Brown { 0x0902, 0x0000 }, /* R2306 - EQL_3 */ 396d5315a23SMark Brown { 0x0903, 0x0000 }, /* R2307 - EQL_4 */ 397d5315a23SMark Brown { 0x0904, 0x0000 }, /* R2308 - EQL_5 */ 398d5315a23SMark Brown { 0x0905, 0x0000 }, /* R2309 - EQL_6 */ 399d5315a23SMark Brown { 0x0906, 0x0000 }, /* R2310 - EQL_7 */ 400d5315a23SMark Brown { 0x0907, 0x0000 }, /* R2311 - EQL_8 */ 401d5315a23SMark Brown { 0x0908, 0x0000 }, /* R2312 - EQL_9 */ 402d5315a23SMark Brown { 0x0909, 0x0000 }, /* R2313 - EQL_10 */ 403d5315a23SMark Brown { 0x090A, 0x0000 }, /* R2314 - EQL_11 */ 404d5315a23SMark Brown { 0x090B, 0x0000 }, /* R2315 - EQL_12 */ 405d5315a23SMark Brown { 0x090C, 0x0000 }, /* R2316 - EQL_13 */ 406d5315a23SMark Brown { 0x090D, 0x0000 }, /* R2317 - EQL_14 */ 407d5315a23SMark Brown { 0x090E, 0x0000 }, /* R2318 - EQL_15 */ 408d5315a23SMark Brown { 0x090F, 0x0000 }, /* R2319 - EQL_16 */ 409d5315a23SMark Brown { 0x0910, 0x0000 }, /* R2320 - EQL_17 */ 410d5315a23SMark Brown { 0x0911, 0x0000 }, /* R2321 - EQL_18 */ 411d5315a23SMark Brown { 0x0912, 0x0000 }, /* R2322 - EQL_19 */ 412d5315a23SMark Brown { 0x0913, 0x0000 }, /* R2323 - EQL_20 */ 413d5315a23SMark Brown { 0x0916, 0x0000 }, /* R2326 - EQR_1 */ 414d5315a23SMark Brown { 0x0917, 0x0000 }, /* R2327 - EQR_2 */ 415d5315a23SMark Brown { 0x0918, 0x0000 }, /* R2328 - EQR_3 */ 416d5315a23SMark Brown { 0x0919, 0x0000 }, /* R2329 - EQR_4 */ 417d5315a23SMark Brown { 0x091A, 0x0000 }, /* R2330 - EQR_5 */ 418d5315a23SMark Brown { 0x091B, 0x0000 }, /* R2331 - EQR_6 */ 419d5315a23SMark Brown { 0x091C, 0x0000 }, /* R2332 - EQR_7 */ 420d5315a23SMark Brown { 0x091D, 0x0000 }, /* R2333 - EQR_8 */ 421d5315a23SMark Brown { 0x091E, 0x0000 }, /* R2334 - EQR_9 */ 422d5315a23SMark Brown { 0x091F, 0x0000 }, /* R2335 - EQR_10 */ 423d5315a23SMark Brown { 0x0920, 0x0000 }, /* R2336 - EQR_11 */ 424d5315a23SMark Brown { 0x0921, 0x0000 }, /* R2337 - EQR_12 */ 425d5315a23SMark Brown { 0x0922, 0x0000 }, /* R2338 - EQR_13 */ 426d5315a23SMark Brown { 0x0923, 0x0000 }, /* R2339 - EQR_14 */ 427d5315a23SMark Brown { 0x0924, 0x0000 }, /* R2340 - EQR_15 */ 428d5315a23SMark Brown { 0x0925, 0x0000 }, /* R2341 - EQR_16 */ 429d5315a23SMark Brown { 0x0926, 0x0000 }, /* R2342 - EQR_17 */ 430d5315a23SMark Brown { 0x0927, 0x0000 }, /* R2343 - EQR_18 */ 431d5315a23SMark Brown { 0x0928, 0x0000 }, /* R2344 - EQR_19 */ 432d5315a23SMark Brown { 0x0929, 0x0000 }, /* R2345 - EQR_20 */ 433d5315a23SMark Brown { 0x093E, 0x0000 }, /* R2366 - HPLPF1_1 */ 434d5315a23SMark Brown { 0x093F, 0x0000 }, /* R2367 - HPLPF1_2 */ 435d5315a23SMark Brown { 0x0942, 0x0000 }, /* R2370 - HPLPF2_1 */ 436d5315a23SMark Brown { 0x0943, 0x0000 }, /* R2371 - HPLPF2_2 */ 437d5315a23SMark Brown { 0x0A00, 0x0000 }, /* R2560 - DSP1 Control 1 */ 438d5315a23SMark Brown { 0x0A02, 0x0000 }, /* R2562 - DSP1 Control 2 */ 439d5315a23SMark Brown { 0x0A03, 0x0000 }, /* R2563 - DSP1 Control 3 */ 440d5315a23SMark Brown { 0x0A04, 0x0000 }, /* R2564 - DSP1 Control 4 */ 441d5315a23SMark Brown { 0x0A06, 0x0000 }, /* R2566 - DSP1 Control 5 */ 442d5315a23SMark Brown { 0x0A07, 0x0000 }, /* R2567 - DSP1 Control 6 */ 443d5315a23SMark Brown { 0x0A08, 0x0000 }, /* R2568 - DSP1 Control 7 */ 444d5315a23SMark Brown { 0x0A09, 0x0000 }, /* R2569 - DSP1 Control 8 */ 445d5315a23SMark Brown { 0x0A0A, 0x0000 }, /* R2570 - DSP1 Control 9 */ 446d5315a23SMark Brown { 0x0A0B, 0x0000 }, /* R2571 - DSP1 Control 10 */ 447d5315a23SMark Brown { 0x0A0C, 0x0000 }, /* R2572 - DSP1 Control 11 */ 448d5315a23SMark Brown { 0x0A0D, 0x0000 }, /* R2573 - DSP1 Control 12 */ 449d5315a23SMark Brown { 0x0A0F, 0x0000 }, /* R2575 - DSP1 Control 13 */ 450d5315a23SMark Brown { 0x0A10, 0x0000 }, /* R2576 - DSP1 Control 14 */ 451d5315a23SMark Brown { 0x0A11, 0x0000 }, /* R2577 - DSP1 Control 15 */ 452d5315a23SMark Brown { 0x0A12, 0x0000 }, /* R2578 - DSP1 Control 16 */ 453d5315a23SMark Brown { 0x0A13, 0x0000 }, /* R2579 - DSP1 Control 17 */ 454d5315a23SMark Brown { 0x0A14, 0x0000 }, /* R2580 - DSP1 Control 18 */ 455d5315a23SMark Brown { 0x0A16, 0x0000 }, /* R2582 - DSP1 Control 19 */ 456d5315a23SMark Brown { 0x0A17, 0x0000 }, /* R2583 - DSP1 Control 20 */ 457d5315a23SMark Brown { 0x0A18, 0x0000 }, /* R2584 - DSP1 Control 21 */ 458d5315a23SMark Brown { 0x0A1A, 0x1800 }, /* R2586 - DSP1 Control 22 */ 459d5315a23SMark Brown { 0x0A1B, 0x1000 }, /* R2587 - DSP1 Control 23 */ 460d5315a23SMark Brown { 0x0A1C, 0x0400 }, /* R2588 - DSP1 Control 24 */ 461d5315a23SMark Brown { 0x0A1E, 0x0000 }, /* R2590 - DSP1 Control 25 */ 462d5315a23SMark Brown { 0x0A20, 0x0000 }, /* R2592 - DSP1 Control 26 */ 463d5315a23SMark Brown { 0x0A21, 0x0000 }, /* R2593 - DSP1 Control 27 */ 464d5315a23SMark Brown { 0x0A22, 0x0000 }, /* R2594 - DSP1 Control 28 */ 465d5315a23SMark Brown { 0x0A23, 0x0000 }, /* R2595 - DSP1 Control 29 */ 466d5315a23SMark Brown { 0x0A24, 0x0000 }, /* R2596 - DSP1 Control 30 */ 467d5315a23SMark Brown { 0x0A26, 0x0000 }, /* R2598 - DSP1 Control 31 */ 468d5315a23SMark Brown { 0x0B00, 0x0000 }, /* R2816 - DSP2 Control 1 */ 469d5315a23SMark Brown { 0x0B02, 0x0000 }, /* R2818 - DSP2 Control 2 */ 470d5315a23SMark Brown { 0x0B03, 0x0000 }, /* R2819 - DSP2 Control 3 */ 471d5315a23SMark Brown { 0x0B04, 0x0000 }, /* R2820 - DSP2 Control 4 */ 472d5315a23SMark Brown { 0x0B06, 0x0000 }, /* R2822 - DSP2 Control 5 */ 473d5315a23SMark Brown { 0x0B07, 0x0000 }, /* R2823 - DSP2 Control 6 */ 474d5315a23SMark Brown { 0x0B08, 0x0000 }, /* R2824 - DSP2 Control 7 */ 475d5315a23SMark Brown { 0x0B09, 0x0000 }, /* R2825 - DSP2 Control 8 */ 476d5315a23SMark Brown { 0x0B0A, 0x0000 }, /* R2826 - DSP2 Control 9 */ 477d5315a23SMark Brown { 0x0B0B, 0x0000 }, /* R2827 - DSP2 Control 10 */ 478d5315a23SMark Brown { 0x0B0C, 0x0000 }, /* R2828 - DSP2 Control 11 */ 479d5315a23SMark Brown { 0x0B0D, 0x0000 }, /* R2829 - DSP2 Control 12 */ 480d5315a23SMark Brown { 0x0B0F, 0x0000 }, /* R2831 - DSP2 Control 13 */ 481d5315a23SMark Brown { 0x0B10, 0x0000 }, /* R2832 - DSP2 Control 14 */ 482d5315a23SMark Brown { 0x0B11, 0x0000 }, /* R2833 - DSP2 Control 15 */ 483d5315a23SMark Brown { 0x0B12, 0x0000 }, /* R2834 - DSP2 Control 16 */ 484d5315a23SMark Brown { 0x0B13, 0x0000 }, /* R2835 - DSP2 Control 17 */ 485d5315a23SMark Brown { 0x0B14, 0x0000 }, /* R2836 - DSP2 Control 18 */ 486d5315a23SMark Brown { 0x0B16, 0x0000 }, /* R2838 - DSP2 Control 19 */ 487d5315a23SMark Brown { 0x0B17, 0x0000 }, /* R2839 - DSP2 Control 20 */ 488d5315a23SMark Brown { 0x0B18, 0x0000 }, /* R2840 - DSP2 Control 21 */ 489d5315a23SMark Brown { 0x0B1A, 0x0800 }, /* R2842 - DSP2 Control 22 */ 490d5315a23SMark Brown { 0x0B1B, 0x1000 }, /* R2843 - DSP2 Control 23 */ 491d5315a23SMark Brown { 0x0B1C, 0x0400 }, /* R2844 - DSP2 Control 24 */ 492d5315a23SMark Brown { 0x0B1E, 0x0000 }, /* R2846 - DSP2 Control 25 */ 493d5315a23SMark Brown { 0x0B20, 0x0000 }, /* R2848 - DSP2 Control 26 */ 494d5315a23SMark Brown { 0x0B21, 0x0000 }, /* R2849 - DSP2 Control 27 */ 495d5315a23SMark Brown { 0x0B22, 0x0000 }, /* R2850 - DSP2 Control 28 */ 496d5315a23SMark Brown { 0x0B23, 0x0000 }, /* R2851 - DSP2 Control 29 */ 497d5315a23SMark Brown { 0x0B24, 0x0000 }, /* R2852 - DSP2 Control 30 */ 498d5315a23SMark Brown { 0x0B26, 0x0000 }, /* R2854 - DSP2 Control 31 */ 499d5315a23SMark Brown }; 500d5315a23SMark Brown 501d5315a23SMark Brown static bool wm2200_volatile_register(struct device *dev, unsigned int reg) 502d5315a23SMark Brown { 503eae2328dSMark Brown int i; 504eae2328dSMark Brown 505eae2328dSMark Brown for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++) 506eae2328dSMark Brown if ((reg >= wm2200_ranges[i].window_start && 507eae2328dSMark Brown reg <= wm2200_ranges[i].window_start + 508eae2328dSMark Brown wm2200_ranges[i].window_len) || 509eae2328dSMark Brown (reg >= wm2200_ranges[i].range_min && 510eae2328dSMark Brown reg <= wm2200_ranges[i].range_max)) 511eae2328dSMark Brown return true; 512eae2328dSMark Brown 513d5315a23SMark Brown switch (reg) { 514d5315a23SMark Brown case WM2200_SOFTWARE_RESET: 515d5315a23SMark Brown case WM2200_DEVICE_REVISION: 516d5315a23SMark Brown case WM2200_ADPS1_IRQ0: 517d5315a23SMark Brown case WM2200_ADPS1_IRQ1: 518d5315a23SMark Brown case WM2200_INTERRUPT_STATUS_1: 519d5315a23SMark Brown case WM2200_INTERRUPT_STATUS_2: 520d5315a23SMark Brown case WM2200_INTERRUPT_RAW_STATUS_2: 521d5315a23SMark Brown return true; 522d5315a23SMark Brown default: 523d5315a23SMark Brown return false; 524d5315a23SMark Brown } 525d5315a23SMark Brown } 526d5315a23SMark Brown 527d5315a23SMark Brown static bool wm2200_readable_register(struct device *dev, unsigned int reg) 528d5315a23SMark Brown { 529eae2328dSMark Brown int i; 530eae2328dSMark Brown 531eae2328dSMark Brown for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++) 532eae2328dSMark Brown if ((reg >= wm2200_ranges[i].window_start && 533eae2328dSMark Brown reg <= wm2200_ranges[i].window_start + 534eae2328dSMark Brown wm2200_ranges[i].window_len) || 535eae2328dSMark Brown (reg >= wm2200_ranges[i].range_min && 536eae2328dSMark Brown reg <= wm2200_ranges[i].range_max)) 537eae2328dSMark Brown return true; 538eae2328dSMark Brown 539d5315a23SMark Brown switch (reg) { 540d5315a23SMark Brown case WM2200_SOFTWARE_RESET: 541d5315a23SMark Brown case WM2200_DEVICE_REVISION: 542d5315a23SMark Brown case WM2200_TONE_GENERATOR_1: 543d5315a23SMark Brown case WM2200_CLOCKING_3: 544d5315a23SMark Brown case WM2200_CLOCKING_4: 545d5315a23SMark Brown case WM2200_FLL_CONTROL_1: 546d5315a23SMark Brown case WM2200_FLL_CONTROL_2: 547d5315a23SMark Brown case WM2200_FLL_CONTROL_3: 548d5315a23SMark Brown case WM2200_FLL_CONTROL_4: 549d5315a23SMark Brown case WM2200_FLL_CONTROL_6: 550d5315a23SMark Brown case WM2200_FLL_CONTROL_7: 551d5315a23SMark Brown case WM2200_FLL_EFS_1: 552d5315a23SMark Brown case WM2200_FLL_EFS_2: 553d5315a23SMark Brown case WM2200_MIC_CHARGE_PUMP_1: 554d5315a23SMark Brown case WM2200_MIC_CHARGE_PUMP_2: 555d5315a23SMark Brown case WM2200_DM_CHARGE_PUMP_1: 556d5315a23SMark Brown case WM2200_MIC_BIAS_CTRL_1: 557d5315a23SMark Brown case WM2200_MIC_BIAS_CTRL_2: 558d5315a23SMark Brown case WM2200_EAR_PIECE_CTRL_1: 559d5315a23SMark Brown case WM2200_EAR_PIECE_CTRL_2: 560d5315a23SMark Brown case WM2200_INPUT_ENABLES: 561d5315a23SMark Brown case WM2200_IN1L_CONTROL: 562d5315a23SMark Brown case WM2200_IN1R_CONTROL: 563d5315a23SMark Brown case WM2200_IN2L_CONTROL: 564d5315a23SMark Brown case WM2200_IN2R_CONTROL: 565d5315a23SMark Brown case WM2200_IN3L_CONTROL: 566d5315a23SMark Brown case WM2200_IN3R_CONTROL: 567d5315a23SMark Brown case WM2200_RXANC_SRC: 568d5315a23SMark Brown case WM2200_INPUT_VOLUME_RAMP: 569d5315a23SMark Brown case WM2200_ADC_DIGITAL_VOLUME_1L: 570d5315a23SMark Brown case WM2200_ADC_DIGITAL_VOLUME_1R: 571d5315a23SMark Brown case WM2200_ADC_DIGITAL_VOLUME_2L: 572d5315a23SMark Brown case WM2200_ADC_DIGITAL_VOLUME_2R: 573d5315a23SMark Brown case WM2200_ADC_DIGITAL_VOLUME_3L: 574d5315a23SMark Brown case WM2200_ADC_DIGITAL_VOLUME_3R: 575d5315a23SMark Brown case WM2200_OUTPUT_ENABLES: 576d5315a23SMark Brown case WM2200_DAC_VOLUME_LIMIT_1L: 577d5315a23SMark Brown case WM2200_DAC_VOLUME_LIMIT_1R: 578d5315a23SMark Brown case WM2200_DAC_VOLUME_LIMIT_2L: 579d5315a23SMark Brown case WM2200_DAC_VOLUME_LIMIT_2R: 580d5315a23SMark Brown case WM2200_DAC_AEC_CONTROL_1: 581d5315a23SMark Brown case WM2200_OUTPUT_VOLUME_RAMP: 582d5315a23SMark Brown case WM2200_DAC_DIGITAL_VOLUME_1L: 583d5315a23SMark Brown case WM2200_DAC_DIGITAL_VOLUME_1R: 584d5315a23SMark Brown case WM2200_DAC_DIGITAL_VOLUME_2L: 585d5315a23SMark Brown case WM2200_DAC_DIGITAL_VOLUME_2R: 586d5315a23SMark Brown case WM2200_PDM_1: 587d5315a23SMark Brown case WM2200_PDM_2: 588d5315a23SMark Brown case WM2200_AUDIO_IF_1_1: 589d5315a23SMark Brown case WM2200_AUDIO_IF_1_2: 590d5315a23SMark Brown case WM2200_AUDIO_IF_1_3: 591d5315a23SMark Brown case WM2200_AUDIO_IF_1_4: 592d5315a23SMark Brown case WM2200_AUDIO_IF_1_5: 593d5315a23SMark Brown case WM2200_AUDIO_IF_1_6: 594d5315a23SMark Brown case WM2200_AUDIO_IF_1_7: 595d5315a23SMark Brown case WM2200_AUDIO_IF_1_8: 596d5315a23SMark Brown case WM2200_AUDIO_IF_1_9: 597d5315a23SMark Brown case WM2200_AUDIO_IF_1_10: 598d5315a23SMark Brown case WM2200_AUDIO_IF_1_11: 599d5315a23SMark Brown case WM2200_AUDIO_IF_1_12: 600d5315a23SMark Brown case WM2200_AUDIO_IF_1_13: 601d5315a23SMark Brown case WM2200_AUDIO_IF_1_14: 602d5315a23SMark Brown case WM2200_AUDIO_IF_1_15: 603d5315a23SMark Brown case WM2200_AUDIO_IF_1_16: 604d5315a23SMark Brown case WM2200_AUDIO_IF_1_17: 605d5315a23SMark Brown case WM2200_AUDIO_IF_1_18: 606d5315a23SMark Brown case WM2200_AUDIO_IF_1_19: 607d5315a23SMark Brown case WM2200_AUDIO_IF_1_20: 608d5315a23SMark Brown case WM2200_AUDIO_IF_1_21: 609d5315a23SMark Brown case WM2200_AUDIO_IF_1_22: 610d5315a23SMark Brown case WM2200_OUT1LMIX_INPUT_1_SOURCE: 611d5315a23SMark Brown case WM2200_OUT1LMIX_INPUT_1_VOLUME: 612d5315a23SMark Brown case WM2200_OUT1LMIX_INPUT_2_SOURCE: 613d5315a23SMark Brown case WM2200_OUT1LMIX_INPUT_2_VOLUME: 614d5315a23SMark Brown case WM2200_OUT1LMIX_INPUT_3_SOURCE: 615d5315a23SMark Brown case WM2200_OUT1LMIX_INPUT_3_VOLUME: 616d5315a23SMark Brown case WM2200_OUT1LMIX_INPUT_4_SOURCE: 617d5315a23SMark Brown case WM2200_OUT1LMIX_INPUT_4_VOLUME: 618d5315a23SMark Brown case WM2200_OUT1RMIX_INPUT_1_SOURCE: 619d5315a23SMark Brown case WM2200_OUT1RMIX_INPUT_1_VOLUME: 620d5315a23SMark Brown case WM2200_OUT1RMIX_INPUT_2_SOURCE: 621d5315a23SMark Brown case WM2200_OUT1RMIX_INPUT_2_VOLUME: 622d5315a23SMark Brown case WM2200_OUT1RMIX_INPUT_3_SOURCE: 623d5315a23SMark Brown case WM2200_OUT1RMIX_INPUT_3_VOLUME: 624d5315a23SMark Brown case WM2200_OUT1RMIX_INPUT_4_SOURCE: 625d5315a23SMark Brown case WM2200_OUT1RMIX_INPUT_4_VOLUME: 626d5315a23SMark Brown case WM2200_OUT2LMIX_INPUT_1_SOURCE: 627d5315a23SMark Brown case WM2200_OUT2LMIX_INPUT_1_VOLUME: 628d5315a23SMark Brown case WM2200_OUT2LMIX_INPUT_2_SOURCE: 629d5315a23SMark Brown case WM2200_OUT2LMIX_INPUT_2_VOLUME: 630d5315a23SMark Brown case WM2200_OUT2LMIX_INPUT_3_SOURCE: 631d5315a23SMark Brown case WM2200_OUT2LMIX_INPUT_3_VOLUME: 632d5315a23SMark Brown case WM2200_OUT2LMIX_INPUT_4_SOURCE: 633d5315a23SMark Brown case WM2200_OUT2LMIX_INPUT_4_VOLUME: 634d5315a23SMark Brown case WM2200_OUT2RMIX_INPUT_1_SOURCE: 635d5315a23SMark Brown case WM2200_OUT2RMIX_INPUT_1_VOLUME: 636d5315a23SMark Brown case WM2200_OUT2RMIX_INPUT_2_SOURCE: 637d5315a23SMark Brown case WM2200_OUT2RMIX_INPUT_2_VOLUME: 638d5315a23SMark Brown case WM2200_OUT2RMIX_INPUT_3_SOURCE: 639d5315a23SMark Brown case WM2200_OUT2RMIX_INPUT_3_VOLUME: 640d5315a23SMark Brown case WM2200_OUT2RMIX_INPUT_4_SOURCE: 641d5315a23SMark Brown case WM2200_OUT2RMIX_INPUT_4_VOLUME: 642d5315a23SMark Brown case WM2200_AIF1TX1MIX_INPUT_1_SOURCE: 643d5315a23SMark Brown case WM2200_AIF1TX1MIX_INPUT_1_VOLUME: 644d5315a23SMark Brown case WM2200_AIF1TX1MIX_INPUT_2_SOURCE: 645d5315a23SMark Brown case WM2200_AIF1TX1MIX_INPUT_2_VOLUME: 646d5315a23SMark Brown case WM2200_AIF1TX1MIX_INPUT_3_SOURCE: 647d5315a23SMark Brown case WM2200_AIF1TX1MIX_INPUT_3_VOLUME: 648d5315a23SMark Brown case WM2200_AIF1TX1MIX_INPUT_4_SOURCE: 649d5315a23SMark Brown case WM2200_AIF1TX1MIX_INPUT_4_VOLUME: 650d5315a23SMark Brown case WM2200_AIF1TX2MIX_INPUT_1_SOURCE: 651d5315a23SMark Brown case WM2200_AIF1TX2MIX_INPUT_1_VOLUME: 652d5315a23SMark Brown case WM2200_AIF1TX2MIX_INPUT_2_SOURCE: 653d5315a23SMark Brown case WM2200_AIF1TX2MIX_INPUT_2_VOLUME: 654d5315a23SMark Brown case WM2200_AIF1TX2MIX_INPUT_3_SOURCE: 655d5315a23SMark Brown case WM2200_AIF1TX2MIX_INPUT_3_VOLUME: 656d5315a23SMark Brown case WM2200_AIF1TX2MIX_INPUT_4_SOURCE: 657d5315a23SMark Brown case WM2200_AIF1TX2MIX_INPUT_4_VOLUME: 658d5315a23SMark Brown case WM2200_AIF1TX3MIX_INPUT_1_SOURCE: 659d5315a23SMark Brown case WM2200_AIF1TX3MIX_INPUT_1_VOLUME: 660d5315a23SMark Brown case WM2200_AIF1TX3MIX_INPUT_2_SOURCE: 661d5315a23SMark Brown case WM2200_AIF1TX3MIX_INPUT_2_VOLUME: 662d5315a23SMark Brown case WM2200_AIF1TX3MIX_INPUT_3_SOURCE: 663d5315a23SMark Brown case WM2200_AIF1TX3MIX_INPUT_3_VOLUME: 664d5315a23SMark Brown case WM2200_AIF1TX3MIX_INPUT_4_SOURCE: 665d5315a23SMark Brown case WM2200_AIF1TX3MIX_INPUT_4_VOLUME: 666d5315a23SMark Brown case WM2200_AIF1TX4MIX_INPUT_1_SOURCE: 667d5315a23SMark Brown case WM2200_AIF1TX4MIX_INPUT_1_VOLUME: 668d5315a23SMark Brown case WM2200_AIF1TX4MIX_INPUT_2_SOURCE: 669d5315a23SMark Brown case WM2200_AIF1TX4MIX_INPUT_2_VOLUME: 670d5315a23SMark Brown case WM2200_AIF1TX4MIX_INPUT_3_SOURCE: 671d5315a23SMark Brown case WM2200_AIF1TX4MIX_INPUT_3_VOLUME: 672d5315a23SMark Brown case WM2200_AIF1TX4MIX_INPUT_4_SOURCE: 673d5315a23SMark Brown case WM2200_AIF1TX4MIX_INPUT_4_VOLUME: 674d5315a23SMark Brown case WM2200_AIF1TX5MIX_INPUT_1_SOURCE: 675d5315a23SMark Brown case WM2200_AIF1TX5MIX_INPUT_1_VOLUME: 676d5315a23SMark Brown case WM2200_AIF1TX5MIX_INPUT_2_SOURCE: 677d5315a23SMark Brown case WM2200_AIF1TX5MIX_INPUT_2_VOLUME: 678d5315a23SMark Brown case WM2200_AIF1TX5MIX_INPUT_3_SOURCE: 679d5315a23SMark Brown case WM2200_AIF1TX5MIX_INPUT_3_VOLUME: 680d5315a23SMark Brown case WM2200_AIF1TX5MIX_INPUT_4_SOURCE: 681d5315a23SMark Brown case WM2200_AIF1TX5MIX_INPUT_4_VOLUME: 682d5315a23SMark Brown case WM2200_AIF1TX6MIX_INPUT_1_SOURCE: 683d5315a23SMark Brown case WM2200_AIF1TX6MIX_INPUT_1_VOLUME: 684d5315a23SMark Brown case WM2200_AIF1TX6MIX_INPUT_2_SOURCE: 685d5315a23SMark Brown case WM2200_AIF1TX6MIX_INPUT_2_VOLUME: 686d5315a23SMark Brown case WM2200_AIF1TX6MIX_INPUT_3_SOURCE: 687d5315a23SMark Brown case WM2200_AIF1TX6MIX_INPUT_3_VOLUME: 688d5315a23SMark Brown case WM2200_AIF1TX6MIX_INPUT_4_SOURCE: 689d5315a23SMark Brown case WM2200_AIF1TX6MIX_INPUT_4_VOLUME: 690d5315a23SMark Brown case WM2200_EQLMIX_INPUT_1_SOURCE: 691d5315a23SMark Brown case WM2200_EQLMIX_INPUT_1_VOLUME: 692d5315a23SMark Brown case WM2200_EQLMIX_INPUT_2_SOURCE: 693d5315a23SMark Brown case WM2200_EQLMIX_INPUT_2_VOLUME: 694d5315a23SMark Brown case WM2200_EQLMIX_INPUT_3_SOURCE: 695d5315a23SMark Brown case WM2200_EQLMIX_INPUT_3_VOLUME: 696d5315a23SMark Brown case WM2200_EQLMIX_INPUT_4_SOURCE: 697d5315a23SMark Brown case WM2200_EQLMIX_INPUT_4_VOLUME: 698d5315a23SMark Brown case WM2200_EQRMIX_INPUT_1_SOURCE: 699d5315a23SMark Brown case WM2200_EQRMIX_INPUT_1_VOLUME: 700d5315a23SMark Brown case WM2200_EQRMIX_INPUT_2_SOURCE: 701d5315a23SMark Brown case WM2200_EQRMIX_INPUT_2_VOLUME: 702d5315a23SMark Brown case WM2200_EQRMIX_INPUT_3_SOURCE: 703d5315a23SMark Brown case WM2200_EQRMIX_INPUT_3_VOLUME: 704d5315a23SMark Brown case WM2200_EQRMIX_INPUT_4_SOURCE: 705d5315a23SMark Brown case WM2200_EQRMIX_INPUT_4_VOLUME: 706d5315a23SMark Brown case WM2200_LHPF1MIX_INPUT_1_SOURCE: 707d5315a23SMark Brown case WM2200_LHPF1MIX_INPUT_1_VOLUME: 708d5315a23SMark Brown case WM2200_LHPF1MIX_INPUT_2_SOURCE: 709d5315a23SMark Brown case WM2200_LHPF1MIX_INPUT_2_VOLUME: 710d5315a23SMark Brown case WM2200_LHPF1MIX_INPUT_3_SOURCE: 711d5315a23SMark Brown case WM2200_LHPF1MIX_INPUT_3_VOLUME: 712d5315a23SMark Brown case WM2200_LHPF1MIX_INPUT_4_SOURCE: 713d5315a23SMark Brown case WM2200_LHPF1MIX_INPUT_4_VOLUME: 714d5315a23SMark Brown case WM2200_LHPF2MIX_INPUT_1_SOURCE: 715d5315a23SMark Brown case WM2200_LHPF2MIX_INPUT_1_VOLUME: 716d5315a23SMark Brown case WM2200_LHPF2MIX_INPUT_2_SOURCE: 717d5315a23SMark Brown case WM2200_LHPF2MIX_INPUT_2_VOLUME: 718d5315a23SMark Brown case WM2200_LHPF2MIX_INPUT_3_SOURCE: 719d5315a23SMark Brown case WM2200_LHPF2MIX_INPUT_3_VOLUME: 720d5315a23SMark Brown case WM2200_LHPF2MIX_INPUT_4_SOURCE: 721d5315a23SMark Brown case WM2200_LHPF2MIX_INPUT_4_VOLUME: 722d5315a23SMark Brown case WM2200_DSP1LMIX_INPUT_1_SOURCE: 723d5315a23SMark Brown case WM2200_DSP1LMIX_INPUT_1_VOLUME: 724d5315a23SMark Brown case WM2200_DSP1LMIX_INPUT_2_SOURCE: 725d5315a23SMark Brown case WM2200_DSP1LMIX_INPUT_2_VOLUME: 726d5315a23SMark Brown case WM2200_DSP1LMIX_INPUT_3_SOURCE: 727d5315a23SMark Brown case WM2200_DSP1LMIX_INPUT_3_VOLUME: 728d5315a23SMark Brown case WM2200_DSP1LMIX_INPUT_4_SOURCE: 729d5315a23SMark Brown case WM2200_DSP1LMIX_INPUT_4_VOLUME: 730d5315a23SMark Brown case WM2200_DSP1RMIX_INPUT_1_SOURCE: 731d5315a23SMark Brown case WM2200_DSP1RMIX_INPUT_1_VOLUME: 732d5315a23SMark Brown case WM2200_DSP1RMIX_INPUT_2_SOURCE: 733d5315a23SMark Brown case WM2200_DSP1RMIX_INPUT_2_VOLUME: 734d5315a23SMark Brown case WM2200_DSP1RMIX_INPUT_3_SOURCE: 735d5315a23SMark Brown case WM2200_DSP1RMIX_INPUT_3_VOLUME: 736d5315a23SMark Brown case WM2200_DSP1RMIX_INPUT_4_SOURCE: 737d5315a23SMark Brown case WM2200_DSP1RMIX_INPUT_4_VOLUME: 738d5315a23SMark Brown case WM2200_DSP1AUX1MIX_INPUT_1_SOURCE: 739d5315a23SMark Brown case WM2200_DSP1AUX2MIX_INPUT_1_SOURCE: 740d5315a23SMark Brown case WM2200_DSP1AUX3MIX_INPUT_1_SOURCE: 741d5315a23SMark Brown case WM2200_DSP1AUX4MIX_INPUT_1_SOURCE: 742d5315a23SMark Brown case WM2200_DSP1AUX5MIX_INPUT_1_SOURCE: 743d5315a23SMark Brown case WM2200_DSP1AUX6MIX_INPUT_1_SOURCE: 744d5315a23SMark Brown case WM2200_DSP2LMIX_INPUT_1_SOURCE: 745d5315a23SMark Brown case WM2200_DSP2LMIX_INPUT_1_VOLUME: 746d5315a23SMark Brown case WM2200_DSP2LMIX_INPUT_2_SOURCE: 747d5315a23SMark Brown case WM2200_DSP2LMIX_INPUT_2_VOLUME: 748d5315a23SMark Brown case WM2200_DSP2LMIX_INPUT_3_SOURCE: 749d5315a23SMark Brown case WM2200_DSP2LMIX_INPUT_3_VOLUME: 750d5315a23SMark Brown case WM2200_DSP2LMIX_INPUT_4_SOURCE: 751d5315a23SMark Brown case WM2200_DSP2LMIX_INPUT_4_VOLUME: 752d5315a23SMark Brown case WM2200_DSP2RMIX_INPUT_1_SOURCE: 753d5315a23SMark Brown case WM2200_DSP2RMIX_INPUT_1_VOLUME: 754d5315a23SMark Brown case WM2200_DSP2RMIX_INPUT_2_SOURCE: 755d5315a23SMark Brown case WM2200_DSP2RMIX_INPUT_2_VOLUME: 756d5315a23SMark Brown case WM2200_DSP2RMIX_INPUT_3_SOURCE: 757d5315a23SMark Brown case WM2200_DSP2RMIX_INPUT_3_VOLUME: 758d5315a23SMark Brown case WM2200_DSP2RMIX_INPUT_4_SOURCE: 759d5315a23SMark Brown case WM2200_DSP2RMIX_INPUT_4_VOLUME: 760d5315a23SMark Brown case WM2200_DSP2AUX1MIX_INPUT_1_SOURCE: 761d5315a23SMark Brown case WM2200_DSP2AUX2MIX_INPUT_1_SOURCE: 762d5315a23SMark Brown case WM2200_DSP2AUX3MIX_INPUT_1_SOURCE: 763d5315a23SMark Brown case WM2200_DSP2AUX4MIX_INPUT_1_SOURCE: 764d5315a23SMark Brown case WM2200_DSP2AUX5MIX_INPUT_1_SOURCE: 765d5315a23SMark Brown case WM2200_DSP2AUX6MIX_INPUT_1_SOURCE: 766d5315a23SMark Brown case WM2200_GPIO_CTRL_1: 767d5315a23SMark Brown case WM2200_GPIO_CTRL_2: 768d5315a23SMark Brown case WM2200_GPIO_CTRL_3: 769d5315a23SMark Brown case WM2200_GPIO_CTRL_4: 770d5315a23SMark Brown case WM2200_ADPS1_IRQ0: 771d5315a23SMark Brown case WM2200_ADPS1_IRQ1: 772d5315a23SMark Brown case WM2200_MISC_PAD_CTRL_1: 773d5315a23SMark Brown case WM2200_INTERRUPT_STATUS_1: 774d5315a23SMark Brown case WM2200_INTERRUPT_STATUS_1_MASK: 775d5315a23SMark Brown case WM2200_INTERRUPT_STATUS_2: 776d5315a23SMark Brown case WM2200_INTERRUPT_RAW_STATUS_2: 777d5315a23SMark Brown case WM2200_INTERRUPT_STATUS_2_MASK: 778d5315a23SMark Brown case WM2200_INTERRUPT_CONTROL: 779d5315a23SMark Brown case WM2200_EQL_1: 780d5315a23SMark Brown case WM2200_EQL_2: 781d5315a23SMark Brown case WM2200_EQL_3: 782d5315a23SMark Brown case WM2200_EQL_4: 783d5315a23SMark Brown case WM2200_EQL_5: 784d5315a23SMark Brown case WM2200_EQL_6: 785d5315a23SMark Brown case WM2200_EQL_7: 786d5315a23SMark Brown case WM2200_EQL_8: 787d5315a23SMark Brown case WM2200_EQL_9: 788d5315a23SMark Brown case WM2200_EQL_10: 789d5315a23SMark Brown case WM2200_EQL_11: 790d5315a23SMark Brown case WM2200_EQL_12: 791d5315a23SMark Brown case WM2200_EQL_13: 792d5315a23SMark Brown case WM2200_EQL_14: 793d5315a23SMark Brown case WM2200_EQL_15: 794d5315a23SMark Brown case WM2200_EQL_16: 795d5315a23SMark Brown case WM2200_EQL_17: 796d5315a23SMark Brown case WM2200_EQL_18: 797d5315a23SMark Brown case WM2200_EQL_19: 798d5315a23SMark Brown case WM2200_EQL_20: 799d5315a23SMark Brown case WM2200_EQR_1: 800d5315a23SMark Brown case WM2200_EQR_2: 801d5315a23SMark Brown case WM2200_EQR_3: 802d5315a23SMark Brown case WM2200_EQR_4: 803d5315a23SMark Brown case WM2200_EQR_5: 804d5315a23SMark Brown case WM2200_EQR_6: 805d5315a23SMark Brown case WM2200_EQR_7: 806d5315a23SMark Brown case WM2200_EQR_8: 807d5315a23SMark Brown case WM2200_EQR_9: 808d5315a23SMark Brown case WM2200_EQR_10: 809d5315a23SMark Brown case WM2200_EQR_11: 810d5315a23SMark Brown case WM2200_EQR_12: 811d5315a23SMark Brown case WM2200_EQR_13: 812d5315a23SMark Brown case WM2200_EQR_14: 813d5315a23SMark Brown case WM2200_EQR_15: 814d5315a23SMark Brown case WM2200_EQR_16: 815d5315a23SMark Brown case WM2200_EQR_17: 816d5315a23SMark Brown case WM2200_EQR_18: 817d5315a23SMark Brown case WM2200_EQR_19: 818d5315a23SMark Brown case WM2200_EQR_20: 819d5315a23SMark Brown case WM2200_HPLPF1_1: 820d5315a23SMark Brown case WM2200_HPLPF1_2: 821d5315a23SMark Brown case WM2200_HPLPF2_1: 822d5315a23SMark Brown case WM2200_HPLPF2_2: 823d5315a23SMark Brown case WM2200_DSP1_CONTROL_1: 824d5315a23SMark Brown case WM2200_DSP1_CONTROL_2: 825d5315a23SMark Brown case WM2200_DSP1_CONTROL_3: 826d5315a23SMark Brown case WM2200_DSP1_CONTROL_4: 827d5315a23SMark Brown case WM2200_DSP1_CONTROL_5: 828d5315a23SMark Brown case WM2200_DSP1_CONTROL_6: 829d5315a23SMark Brown case WM2200_DSP1_CONTROL_7: 830d5315a23SMark Brown case WM2200_DSP1_CONTROL_8: 831d5315a23SMark Brown case WM2200_DSP1_CONTROL_9: 832d5315a23SMark Brown case WM2200_DSP1_CONTROL_10: 833d5315a23SMark Brown case WM2200_DSP1_CONTROL_11: 834d5315a23SMark Brown case WM2200_DSP1_CONTROL_12: 835d5315a23SMark Brown case WM2200_DSP1_CONTROL_13: 836d5315a23SMark Brown case WM2200_DSP1_CONTROL_14: 837d5315a23SMark Brown case WM2200_DSP1_CONTROL_15: 838d5315a23SMark Brown case WM2200_DSP1_CONTROL_16: 839d5315a23SMark Brown case WM2200_DSP1_CONTROL_17: 840d5315a23SMark Brown case WM2200_DSP1_CONTROL_18: 841d5315a23SMark Brown case WM2200_DSP1_CONTROL_19: 842d5315a23SMark Brown case WM2200_DSP1_CONTROL_20: 843d5315a23SMark Brown case WM2200_DSP1_CONTROL_21: 844d5315a23SMark Brown case WM2200_DSP1_CONTROL_22: 845d5315a23SMark Brown case WM2200_DSP1_CONTROL_23: 846d5315a23SMark Brown case WM2200_DSP1_CONTROL_24: 847d5315a23SMark Brown case WM2200_DSP1_CONTROL_25: 848d5315a23SMark Brown case WM2200_DSP1_CONTROL_26: 849d5315a23SMark Brown case WM2200_DSP1_CONTROL_27: 850d5315a23SMark Brown case WM2200_DSP1_CONTROL_28: 851d5315a23SMark Brown case WM2200_DSP1_CONTROL_29: 852d5315a23SMark Brown case WM2200_DSP1_CONTROL_30: 853d5315a23SMark Brown case WM2200_DSP1_CONTROL_31: 854d5315a23SMark Brown case WM2200_DSP2_CONTROL_1: 855d5315a23SMark Brown case WM2200_DSP2_CONTROL_2: 856d5315a23SMark Brown case WM2200_DSP2_CONTROL_3: 857d5315a23SMark Brown case WM2200_DSP2_CONTROL_4: 858d5315a23SMark Brown case WM2200_DSP2_CONTROL_5: 859d5315a23SMark Brown case WM2200_DSP2_CONTROL_6: 860d5315a23SMark Brown case WM2200_DSP2_CONTROL_7: 861d5315a23SMark Brown case WM2200_DSP2_CONTROL_8: 862d5315a23SMark Brown case WM2200_DSP2_CONTROL_9: 863d5315a23SMark Brown case WM2200_DSP2_CONTROL_10: 864d5315a23SMark Brown case WM2200_DSP2_CONTROL_11: 865d5315a23SMark Brown case WM2200_DSP2_CONTROL_12: 866d5315a23SMark Brown case WM2200_DSP2_CONTROL_13: 867d5315a23SMark Brown case WM2200_DSP2_CONTROL_14: 868d5315a23SMark Brown case WM2200_DSP2_CONTROL_15: 869d5315a23SMark Brown case WM2200_DSP2_CONTROL_16: 870d5315a23SMark Brown case WM2200_DSP2_CONTROL_17: 871d5315a23SMark Brown case WM2200_DSP2_CONTROL_18: 872d5315a23SMark Brown case WM2200_DSP2_CONTROL_19: 873d5315a23SMark Brown case WM2200_DSP2_CONTROL_20: 874d5315a23SMark Brown case WM2200_DSP2_CONTROL_21: 875d5315a23SMark Brown case WM2200_DSP2_CONTROL_22: 876d5315a23SMark Brown case WM2200_DSP2_CONTROL_23: 877d5315a23SMark Brown case WM2200_DSP2_CONTROL_24: 878d5315a23SMark Brown case WM2200_DSP2_CONTROL_25: 879d5315a23SMark Brown case WM2200_DSP2_CONTROL_26: 880d5315a23SMark Brown case WM2200_DSP2_CONTROL_27: 881d5315a23SMark Brown case WM2200_DSP2_CONTROL_28: 882d5315a23SMark Brown case WM2200_DSP2_CONTROL_29: 883d5315a23SMark Brown case WM2200_DSP2_CONTROL_30: 884d5315a23SMark Brown case WM2200_DSP2_CONTROL_31: 885d5315a23SMark Brown return true; 886d5315a23SMark Brown default: 887d5315a23SMark Brown return false; 888d5315a23SMark Brown } 889d5315a23SMark Brown } 890d5315a23SMark Brown 8918019ff6cSNariman Poushin static const struct reg_sequence wm2200_reva_patch[] = { 892d5315a23SMark Brown { 0x07, 0x0003 }, 893d5315a23SMark Brown { 0x102, 0x0200 }, 894d5315a23SMark Brown { 0x203, 0x0084 }, 895d5315a23SMark Brown { 0x201, 0x83FF }, 896d5315a23SMark Brown { 0x20C, 0x0062 }, 897d5315a23SMark Brown { 0x20D, 0x0062 }, 898d5315a23SMark Brown { 0x207, 0x2002 }, 899d5315a23SMark Brown { 0x208, 0x20C0 }, 900d5315a23SMark Brown { 0x21D, 0x01C0 }, 901d5315a23SMark Brown { 0x50A, 0x0001 }, 902d5315a23SMark Brown { 0x50B, 0x0002 }, 903d5315a23SMark Brown { 0x50C, 0x0003 }, 904d5315a23SMark Brown { 0x50D, 0x0004 }, 905d5315a23SMark Brown { 0x50E, 0x0005 }, 906d5315a23SMark Brown { 0x510, 0x0001 }, 907d5315a23SMark Brown { 0x511, 0x0002 }, 908d5315a23SMark Brown { 0x512, 0x0003 }, 909d5315a23SMark Brown { 0x513, 0x0004 }, 910d5315a23SMark Brown { 0x514, 0x0005 }, 911d5315a23SMark Brown { 0x515, 0x0000 }, 912d5315a23SMark Brown { 0x201, 0x8084 }, 913d5315a23SMark Brown { 0x202, 0xBBDE }, 914d5315a23SMark Brown { 0x203, 0x00EC }, 915d5315a23SMark Brown { 0x500, 0x8000 }, 916d5315a23SMark Brown { 0x507, 0x1820 }, 917d5315a23SMark Brown { 0x508, 0x1820 }, 918d5315a23SMark Brown { 0x505, 0x0300 }, 919d5315a23SMark Brown { 0x506, 0x0300 }, 920d5315a23SMark Brown { 0x302, 0x2280 }, 921d5315a23SMark Brown { 0x303, 0x0080 }, 922d5315a23SMark Brown { 0x304, 0x2280 }, 923d5315a23SMark Brown { 0x305, 0x0080 }, 924d5315a23SMark Brown { 0x306, 0x2280 }, 925d5315a23SMark Brown { 0x307, 0x0080 }, 926d5315a23SMark Brown { 0x401, 0x0080 }, 927d5315a23SMark Brown { 0x402, 0x0080 }, 928d5315a23SMark Brown { 0x417, 0x3069 }, 929d5315a23SMark Brown { 0x900, 0x6318 }, 930d5315a23SMark Brown { 0x901, 0x6300 }, 931d5315a23SMark Brown { 0x902, 0x0FC8 }, 932d5315a23SMark Brown { 0x903, 0x03FE }, 933d5315a23SMark Brown { 0x904, 0x00E0 }, 934d5315a23SMark Brown { 0x905, 0x1EC4 }, 935d5315a23SMark Brown { 0x906, 0xF136 }, 936d5315a23SMark Brown { 0x907, 0x0409 }, 937d5315a23SMark Brown { 0x908, 0x04CC }, 938d5315a23SMark Brown { 0x909, 0x1C9B }, 939d5315a23SMark Brown { 0x90A, 0xF337 }, 940d5315a23SMark Brown { 0x90B, 0x040B }, 941d5315a23SMark Brown { 0x90C, 0x0CBB }, 942d5315a23SMark Brown { 0x90D, 0x16F8 }, 943d5315a23SMark Brown { 0x90E, 0xF7D9 }, 944d5315a23SMark Brown { 0x90F, 0x040A }, 945d5315a23SMark Brown { 0x910, 0x1F14 }, 946d5315a23SMark Brown { 0x911, 0x058C }, 947d5315a23SMark Brown { 0x912, 0x0563 }, 948d5315a23SMark Brown { 0x913, 0x4000 }, 949d5315a23SMark Brown { 0x916, 0x6318 }, 950d5315a23SMark Brown { 0x917, 0x6300 }, 951d5315a23SMark Brown { 0x918, 0x0FC8 }, 952d5315a23SMark Brown { 0x919, 0x03FE }, 953d5315a23SMark Brown { 0x91A, 0x00E0 }, 954d5315a23SMark Brown { 0x91B, 0x1EC4 }, 955d5315a23SMark Brown { 0x91C, 0xF136 }, 956d5315a23SMark Brown { 0x91D, 0x0409 }, 957d5315a23SMark Brown { 0x91E, 0x04CC }, 958d5315a23SMark Brown { 0x91F, 0x1C9B }, 959d5315a23SMark Brown { 0x920, 0xF337 }, 960d5315a23SMark Brown { 0x921, 0x040B }, 961d5315a23SMark Brown { 0x922, 0x0CBB }, 962d5315a23SMark Brown { 0x923, 0x16F8 }, 963d5315a23SMark Brown { 0x924, 0xF7D9 }, 964d5315a23SMark Brown { 0x925, 0x040A }, 965d5315a23SMark Brown { 0x926, 0x1F14 }, 966d5315a23SMark Brown { 0x927, 0x058C }, 967d5315a23SMark Brown { 0x928, 0x0563 }, 968d5315a23SMark Brown { 0x929, 0x4000 }, 969d5315a23SMark Brown { 0x709, 0x2000 }, 970d5315a23SMark Brown { 0x207, 0x200E }, 971d5315a23SMark Brown { 0x208, 0x20D4 }, 972d5315a23SMark Brown { 0x20A, 0x0080 }, 973d5315a23SMark Brown { 0x07, 0x0000 }, 974d5315a23SMark Brown }; 975d5315a23SMark Brown 976d5315a23SMark Brown static int wm2200_reset(struct wm2200_priv *wm2200) 977d5315a23SMark Brown { 978d5315a23SMark Brown if (wm2200->pdata.reset) { 979d5315a23SMark Brown gpio_set_value_cansleep(wm2200->pdata.reset, 0); 980d5315a23SMark Brown gpio_set_value_cansleep(wm2200->pdata.reset, 1); 981d5315a23SMark Brown 982d5315a23SMark Brown return 0; 983d5315a23SMark Brown } else { 984d5315a23SMark Brown return regmap_write(wm2200->regmap, WM2200_SOFTWARE_RESET, 985d5315a23SMark Brown 0x2200); 986d5315a23SMark Brown } 987d5315a23SMark Brown } 988d5315a23SMark Brown 989d5315a23SMark Brown static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0); 990d5315a23SMark Brown static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); 991d5315a23SMark Brown static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0); 992d5315a23SMark Brown 9934090d63bSCharles Keepax static const char * const wm2200_mixer_texts[] = { 994d5315a23SMark Brown "None", 995d5315a23SMark Brown "Tone Generator", 996999e068eSMark Brown "AEC Loopback", 997d5315a23SMark Brown "IN1L", 998d5315a23SMark Brown "IN1R", 999d5315a23SMark Brown "IN2L", 1000d5315a23SMark Brown "IN2R", 1001d5315a23SMark Brown "IN3L", 1002d5315a23SMark Brown "IN3R", 1003d5315a23SMark Brown "AIF1RX1", 1004d5315a23SMark Brown "AIF1RX2", 1005d5315a23SMark Brown "AIF1RX3", 1006d5315a23SMark Brown "AIF1RX4", 1007d5315a23SMark Brown "AIF1RX5", 1008d5315a23SMark Brown "AIF1RX6", 1009d5315a23SMark Brown "EQL", 1010d5315a23SMark Brown "EQR", 1011d5315a23SMark Brown "LHPF1", 1012d5315a23SMark Brown "LHPF2", 1013d5315a23SMark Brown "DSP1.1", 1014d5315a23SMark Brown "DSP1.2", 1015d5315a23SMark Brown "DSP1.3", 1016d5315a23SMark Brown "DSP1.4", 1017d5315a23SMark Brown "DSP1.5", 1018d5315a23SMark Brown "DSP1.6", 1019d5315a23SMark Brown "DSP2.1", 1020d5315a23SMark Brown "DSP2.2", 1021d5315a23SMark Brown "DSP2.3", 1022d5315a23SMark Brown "DSP2.4", 1023d5315a23SMark Brown "DSP2.5", 1024d5315a23SMark Brown "DSP2.6", 1025d5315a23SMark Brown }; 1026d5315a23SMark Brown 10274090d63bSCharles Keepax static unsigned int wm2200_mixer_values[] = { 1028d5315a23SMark Brown 0x00, 1029d5315a23SMark Brown 0x04, /* Tone */ 1030d5315a23SMark Brown 0x08, /* AEC */ 1031d5315a23SMark Brown 0x10, /* Input */ 1032d5315a23SMark Brown 0x11, 1033d5315a23SMark Brown 0x12, 1034d5315a23SMark Brown 0x13, 1035d5315a23SMark Brown 0x14, 1036d5315a23SMark Brown 0x15, 1037d5315a23SMark Brown 0x20, /* AIF */ 1038d5315a23SMark Brown 0x21, 1039d5315a23SMark Brown 0x22, 1040d5315a23SMark Brown 0x23, 1041d5315a23SMark Brown 0x24, 1042d5315a23SMark Brown 0x25, 1043d5315a23SMark Brown 0x50, /* EQ */ 1044d5315a23SMark Brown 0x51, 1045d5315a23SMark Brown 0x60, /* LHPF1 */ 1046d5315a23SMark Brown 0x61, /* LHPF2 */ 1047d5315a23SMark Brown 0x68, /* DSP1 */ 1048d5315a23SMark Brown 0x69, 1049d5315a23SMark Brown 0x6a, 1050d5315a23SMark Brown 0x6b, 1051d5315a23SMark Brown 0x6c, 1052d5315a23SMark Brown 0x6d, 1053d5315a23SMark Brown 0x70, /* DSP2 */ 1054d5315a23SMark Brown 0x71, 1055d5315a23SMark Brown 0x72, 1056d5315a23SMark Brown 0x73, 1057d5315a23SMark Brown 0x74, 1058d5315a23SMark Brown 0x75, 1059d5315a23SMark Brown }; 1060d5315a23SMark Brown 1061d5315a23SMark Brown #define WM2200_MIXER_CONTROLS(name, base) \ 1062d5315a23SMark Brown SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \ 1063d5315a23SMark Brown WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ 1064d5315a23SMark Brown SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \ 1065d5315a23SMark Brown WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ 1066d5315a23SMark Brown SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \ 1067d5315a23SMark Brown WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \ 1068d5315a23SMark Brown SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \ 1069d5315a23SMark Brown WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv) 1070d5315a23SMark Brown 1071d5315a23SMark Brown #define WM2200_MUX_ENUM_DECL(name, reg) \ 1072d5315a23SMark Brown SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \ 1073d5315a23SMark Brown wm2200_mixer_texts, wm2200_mixer_values) 1074d5315a23SMark Brown 1075d5315a23SMark Brown #define WM2200_MUX_CTL_DECL(name) \ 1076d5315a23SMark Brown const struct snd_kcontrol_new name##_mux = \ 10777eb364abSLars-Peter Clausen SOC_DAPM_ENUM("Route", name##_enum) 1078d5315a23SMark Brown 1079d5315a23SMark Brown #define WM2200_MIXER_ENUMS(name, base_reg) \ 1080d5315a23SMark Brown static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg); \ 1081d5315a23SMark Brown static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \ 1082d5315a23SMark Brown static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \ 1083d5315a23SMark Brown static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \ 1084d5315a23SMark Brown static WM2200_MUX_CTL_DECL(name##_in1); \ 1085d5315a23SMark Brown static WM2200_MUX_CTL_DECL(name##_in2); \ 1086d5315a23SMark Brown static WM2200_MUX_CTL_DECL(name##_in3); \ 1087d5315a23SMark Brown static WM2200_MUX_CTL_DECL(name##_in4) 1088d5315a23SMark Brown 108909d5d588SMark Brown #define WM2200_DSP_ENUMS(name, base_reg) \ 109009d5d588SMark Brown static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg); \ 109109d5d588SMark Brown static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \ 109209d5d588SMark Brown static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \ 109309d5d588SMark Brown static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \ 109409d5d588SMark Brown static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \ 109509d5d588SMark Brown static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \ 109609d5d588SMark Brown static WM2200_MUX_CTL_DECL(name##_aux1); \ 109709d5d588SMark Brown static WM2200_MUX_CTL_DECL(name##_aux2); \ 109809d5d588SMark Brown static WM2200_MUX_CTL_DECL(name##_aux3); \ 109909d5d588SMark Brown static WM2200_MUX_CTL_DECL(name##_aux4); \ 110009d5d588SMark Brown static WM2200_MUX_CTL_DECL(name##_aux5); \ 110109d5d588SMark Brown static WM2200_MUX_CTL_DECL(name##_aux6); 110209d5d588SMark Brown 11034c97e8feSChris Rattray static const char *wm2200_rxanc_input_sel_texts[] = { 11044c97e8feSChris Rattray "None", "IN1", "IN2", "IN3", 11054c97e8feSChris Rattray }; 11064c97e8feSChris Rattray 11079614be73STakashi Iwai static SOC_ENUM_SINGLE_DECL(wm2200_rxanc_input_sel, 11089614be73STakashi Iwai WM2200_RXANC_SRC, 11094c97e8feSChris Rattray WM2200_IN_RXANC_SEL_SHIFT, 11104c97e8feSChris Rattray wm2200_rxanc_input_sel_texts); 11114c97e8feSChris Rattray 1112d5315a23SMark Brown static const struct snd_kcontrol_new wm2200_snd_controls[] = { 1113d5315a23SMark Brown SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, 1114d5315a23SMark Brown WM2200_IN1_OSR_SHIFT, 1, 0), 1115d5315a23SMark Brown SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL, 1116d5315a23SMark Brown WM2200_IN2_OSR_SHIFT, 1, 0), 1117d5315a23SMark Brown SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL, 1118d5315a23SMark Brown WM2200_IN3_OSR_SHIFT, 1, 0), 1119d5315a23SMark Brown 1120d5315a23SMark Brown SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL, 1121d5315a23SMark Brown WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv), 1122d5315a23SMark Brown SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL, 1123d5315a23SMark Brown WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv), 1124d5315a23SMark Brown SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL, 1125d5315a23SMark Brown WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv), 1126d5315a23SMark Brown 1127d5315a23SMark Brown SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, 1128d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1), 11290d2b6422SChris Rattray SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_2L, 1130d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1), 11310d2b6422SChris Rattray SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_3L, 1132d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1), 1133d5315a23SMark Brown 1134d5315a23SMark Brown SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L, 1135d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT, 1136d5315a23SMark Brown 0xbf, 0, digital_tlv), 1137d5315a23SMark Brown SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L, 1138d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT, 1139d5315a23SMark Brown 0xbf, 0, digital_tlv), 1140d5315a23SMark Brown SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L, 1141d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT, 1142d5315a23SMark Brown 0xbf, 0, digital_tlv), 1143d5315a23SMark Brown 1144908a5741SMark Brown SND_SOC_BYTES_MASK("EQL Coefficients", WM2200_EQL_1, 20, WM2200_EQL_ENA), 1145908a5741SMark Brown SND_SOC_BYTES_MASK("EQR Coefficients", WM2200_EQR_1, 20, WM2200_EQR_ENA), 1146908a5741SMark Brown 114757b70db2SColin Ian King SND_SOC_BYTES("LHPF1 Coefficients", WM2200_HPLPF1_2, 1), 114857b70db2SColin Ian King SND_SOC_BYTES("LHPF2 Coefficients", WM2200_HPLPF2_2, 1), 1149908a5741SMark Brown 1150d5315a23SMark Brown SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L, 1151d5315a23SMark Brown WM2200_OUT1_OSR_SHIFT, 1, 0), 1152d5315a23SMark Brown SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L, 1153d5315a23SMark Brown WM2200_OUT2_OSR_SHIFT, 1, 0), 1154d5315a23SMark Brown 1155d5315a23SMark Brown SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L, 1156d5315a23SMark Brown WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1), 1157d5315a23SMark Brown SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L, 1158d5315a23SMark Brown WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0, 1159d5315a23SMark Brown digital_tlv), 1160d5315a23SMark Brown SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L, 1161d5315a23SMark Brown WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT, 1162d5315a23SMark Brown 0x46, 0, out_tlv), 1163d5315a23SMark Brown 1164d5315a23SMark Brown SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L, 1165d5315a23SMark Brown WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1), 1166d5315a23SMark Brown SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, 1167d5315a23SMark Brown WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0, 1168d5315a23SMark Brown digital_tlv), 1169d5315a23SMark Brown SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, 1170a1b98e12SMark Brown WM2200_SPK1R_MUTE_SHIFT, 1, 1), 11714c97e8feSChris Rattray SOC_ENUM("RxANC Src", wm2200_rxanc_input_sel), 11720a047f07SRichard Fitzgerald 11730a047f07SRichard Fitzgerald WM_ADSP_FW_CONTROL("DSP1", 0), 11740a047f07SRichard Fitzgerald WM_ADSP_FW_CONTROL("DSP2", 1), 1175d5315a23SMark Brown }; 1176d5315a23SMark Brown 1177d5315a23SMark Brown WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); 1178d5315a23SMark Brown WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE); 1179d5315a23SMark Brown WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE); 1180d5315a23SMark Brown WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE); 1181d5315a23SMark Brown 1182d5315a23SMark Brown WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE); 1183d5315a23SMark Brown WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE); 1184d5315a23SMark Brown WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE); 1185d5315a23SMark Brown WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE); 1186d5315a23SMark Brown WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE); 1187d5315a23SMark Brown WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE); 1188d5315a23SMark Brown 1189d5315a23SMark Brown WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE); 1190d5315a23SMark Brown WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE); 1191d5315a23SMark Brown 1192d5315a23SMark Brown WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE); 1193d5315a23SMark Brown WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE); 1194d5315a23SMark Brown WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE); 1195d5315a23SMark Brown WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE); 1196d5315a23SMark Brown 119709d5d588SMark Brown WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE); 119809d5d588SMark Brown WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE); 119909d5d588SMark Brown 1200d5315a23SMark Brown WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE); 1201d5315a23SMark Brown WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE); 1202d5315a23SMark Brown 1203d5315a23SMark Brown #define WM2200_MUX(name, ctrl) \ 12047eb364abSLars-Peter Clausen SND_SOC_DAPM_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) 1205d5315a23SMark Brown 1206d5315a23SMark Brown #define WM2200_MIXER_WIDGETS(name, name_str) \ 1207d5315a23SMark Brown WM2200_MUX(name_str " Input 1", &name##_in1_mux), \ 1208d5315a23SMark Brown WM2200_MUX(name_str " Input 2", &name##_in2_mux), \ 1209d5315a23SMark Brown WM2200_MUX(name_str " Input 3", &name##_in3_mux), \ 1210d5315a23SMark Brown WM2200_MUX(name_str " Input 4", &name##_in4_mux), \ 1211d5315a23SMark Brown SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) 1212d5315a23SMark Brown 121309d5d588SMark Brown #define WM2200_DSP_WIDGETS(name, name_str) \ 121409d5d588SMark Brown WM2200_MIXER_WIDGETS(name##L, name_str "L"), \ 121509d5d588SMark Brown WM2200_MIXER_WIDGETS(name##R, name_str "R"), \ 121609d5d588SMark Brown WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \ 121709d5d588SMark Brown WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \ 121809d5d588SMark Brown WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \ 121909d5d588SMark Brown WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \ 122009d5d588SMark Brown WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \ 122109d5d588SMark Brown WM2200_MUX(name_str " Aux 6", &name##_aux6_mux) 122209d5d588SMark Brown 1223d5315a23SMark Brown #define WM2200_MIXER_INPUT_ROUTES(name) \ 1224d5315a23SMark Brown { name, "Tone Generator", "Tone Generator" }, \ 1225999e068eSMark Brown { name, "AEC Loopback", "AEC Loopback" }, \ 1226d5315a23SMark Brown { name, "IN1L", "IN1L PGA" }, \ 1227d5315a23SMark Brown { name, "IN1R", "IN1R PGA" }, \ 1228d5315a23SMark Brown { name, "IN2L", "IN2L PGA" }, \ 1229d5315a23SMark Brown { name, "IN2R", "IN2R PGA" }, \ 1230d5315a23SMark Brown { name, "IN3L", "IN3L PGA" }, \ 1231d5315a23SMark Brown { name, "IN3R", "IN3R PGA" }, \ 1232d5315a23SMark Brown { name, "DSP1.1", "DSP1" }, \ 1233d5315a23SMark Brown { name, "DSP1.2", "DSP1" }, \ 1234d5315a23SMark Brown { name, "DSP1.3", "DSP1" }, \ 1235d5315a23SMark Brown { name, "DSP1.4", "DSP1" }, \ 1236d5315a23SMark Brown { name, "DSP1.5", "DSP1" }, \ 1237d5315a23SMark Brown { name, "DSP1.6", "DSP1" }, \ 1238d5315a23SMark Brown { name, "DSP2.1", "DSP2" }, \ 1239d5315a23SMark Brown { name, "DSP2.2", "DSP2" }, \ 1240d5315a23SMark Brown { name, "DSP2.3", "DSP2" }, \ 1241d5315a23SMark Brown { name, "DSP2.4", "DSP2" }, \ 1242d5315a23SMark Brown { name, "DSP2.5", "DSP2" }, \ 1243d5315a23SMark Brown { name, "DSP2.6", "DSP2" }, \ 1244d5315a23SMark Brown { name, "AIF1RX1", "AIF1RX1" }, \ 1245d5315a23SMark Brown { name, "AIF1RX2", "AIF1RX2" }, \ 1246d5315a23SMark Brown { name, "AIF1RX3", "AIF1RX3" }, \ 1247d5315a23SMark Brown { name, "AIF1RX4", "AIF1RX4" }, \ 1248d5315a23SMark Brown { name, "AIF1RX5", "AIF1RX5" }, \ 1249d5315a23SMark Brown { name, "AIF1RX6", "AIF1RX6" }, \ 1250d5315a23SMark Brown { name, "EQL", "EQL" }, \ 1251d5315a23SMark Brown { name, "EQR", "EQR" }, \ 1252d5315a23SMark Brown { name, "LHPF1", "LHPF1" }, \ 1253d5315a23SMark Brown { name, "LHPF2", "LHPF2" } 1254d5315a23SMark Brown 1255d5315a23SMark Brown #define WM2200_MIXER_ROUTES(widget, name) \ 1256d5315a23SMark Brown { widget, NULL, name " Mixer" }, \ 1257d5315a23SMark Brown { name " Mixer", NULL, name " Input 1" }, \ 1258d5315a23SMark Brown { name " Mixer", NULL, name " Input 2" }, \ 1259d5315a23SMark Brown { name " Mixer", NULL, name " Input 3" }, \ 1260d5315a23SMark Brown { name " Mixer", NULL, name " Input 4" }, \ 1261d5315a23SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \ 1262d5315a23SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \ 1263d5315a23SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \ 1264d5315a23SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Input 4") 1265d5315a23SMark Brown 126609d5d588SMark Brown #define WM2200_DSP_AUX_ROUTES(name) \ 126709d5d588SMark Brown { name, NULL, name " Aux 1" }, \ 126809d5d588SMark Brown { name, NULL, name " Aux 2" }, \ 126909d5d588SMark Brown { name, NULL, name " Aux 3" }, \ 127009d5d588SMark Brown { name, NULL, name " Aux 4" }, \ 127109d5d588SMark Brown { name, NULL, name " Aux 5" }, \ 127209d5d588SMark Brown { name, NULL, name " Aux 6" }, \ 127309d5d588SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \ 127409d5d588SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \ 127509d5d588SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \ 127609d5d588SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \ 127709d5d588SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \ 127809d5d588SMark Brown WM2200_MIXER_INPUT_ROUTES(name " Aux 6") 1279999e068eSMark Brown 1280999e068eSMark Brown static const char *wm2200_aec_loopback_texts[] = { 1281999e068eSMark Brown "OUT1L", "OUT1R", "OUT2L", "OUT2R", 1282999e068eSMark Brown }; 1283999e068eSMark Brown 12849614be73STakashi Iwai static SOC_ENUM_SINGLE_DECL(wm2200_aec_loopback, 12859614be73STakashi Iwai WM2200_DAC_AEC_CONTROL_1, 1286999e068eSMark Brown WM2200_AEC_LOOPBACK_SRC_SHIFT, 1287999e068eSMark Brown wm2200_aec_loopback_texts); 1288999e068eSMark Brown 1289999e068eSMark Brown static const struct snd_kcontrol_new wm2200_aec_loopback_mux = 1290999e068eSMark Brown SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback); 1291999e068eSMark Brown 1292d5315a23SMark Brown static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = { 1293d5315a23SMark Brown SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0, 1294d5315a23SMark Brown NULL, 0), 1295d5315a23SMark Brown SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0, 1296d5315a23SMark Brown NULL, 0), 1297d5315a23SMark Brown SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0, 1298d5315a23SMark Brown NULL, 0), 1299d5315a23SMark Brown SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT, 1300d5315a23SMark Brown 0, NULL, 0), 1301d5315a23SMark Brown SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT, 1302d5315a23SMark Brown 0, NULL, 0), 1303822b4b8dSMark Brown SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), 1304822b4b8dSMark Brown SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20, 0), 1305d5315a23SMark Brown 1306d5315a23SMark Brown SND_SOC_DAPM_INPUT("IN1L"), 1307d5315a23SMark Brown SND_SOC_DAPM_INPUT("IN1R"), 1308d5315a23SMark Brown SND_SOC_DAPM_INPUT("IN2L"), 1309d5315a23SMark Brown SND_SOC_DAPM_INPUT("IN2R"), 1310d5315a23SMark Brown SND_SOC_DAPM_INPUT("IN3L"), 1311d5315a23SMark Brown SND_SOC_DAPM_INPUT("IN3R"), 1312d5315a23SMark Brown 1313d5315a23SMark Brown SND_SOC_DAPM_SIGGEN("TONE"), 1314d5315a23SMark Brown SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1, 1315d5315a23SMark Brown WM2200_TONE_ENA_SHIFT, 0, NULL, 0), 1316d5315a23SMark Brown 1317d5315a23SMark Brown SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0, 1318d5315a23SMark Brown NULL, 0), 1319d5315a23SMark Brown SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0, 1320d5315a23SMark Brown NULL, 0), 1321d5315a23SMark Brown SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0, 1322d5315a23SMark Brown NULL, 0), 1323d5315a23SMark Brown SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0, 1324d5315a23SMark Brown NULL, 0), 1325d5315a23SMark Brown SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0, 1326d5315a23SMark Brown NULL, 0), 1327d5315a23SMark Brown SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0, 1328d5315a23SMark Brown NULL, 0), 1329d5315a23SMark Brown 1330d5315a23SMark Brown SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0, 1331d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0), 1332d5315a23SMark Brown SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1, 1333d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0), 1334d5315a23SMark Brown SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2, 1335d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0), 1336d5315a23SMark Brown SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3, 1337d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0), 1338d5315a23SMark Brown SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4, 1339d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0), 1340d5315a23SMark Brown SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5, 1341d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0), 1342d5315a23SMark Brown 1343d5315a23SMark Brown SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0), 1344d5315a23SMark Brown SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0), 1345d5315a23SMark Brown 1346d5315a23SMark Brown SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0, 1347d5315a23SMark Brown NULL, 0), 1348d5315a23SMark Brown SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0, 1349d5315a23SMark Brown NULL, 0), 1350d5315a23SMark Brown 1351f017eb29SMark Brown WM_ADSP1("DSP1", 0), 1352f017eb29SMark Brown WM_ADSP1("DSP2", 1), 1353d5315a23SMark Brown 1354d5315a23SMark Brown SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0, 1355d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0), 1356d5315a23SMark Brown SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1, 1357d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0), 1358d5315a23SMark Brown SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2, 1359d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0), 1360d5315a23SMark Brown SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3, 1361d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0), 1362d5315a23SMark Brown SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4, 1363d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0), 1364d5315a23SMark Brown SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5, 1365d5315a23SMark Brown WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0), 1366d5315a23SMark Brown 1367999e068eSMark Brown SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1, 1368999e068eSMark Brown WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux), 1369999e068eSMark Brown 1370d5315a23SMark Brown SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES, 1371d5315a23SMark Brown WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0), 1372d5315a23SMark Brown SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES, 1373d5315a23SMark Brown WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0), 1374d5315a23SMark Brown 1375d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1, 1376d5315a23SMark Brown WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0), 1377d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1, 1378d5315a23SMark Brown WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0), 1379d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1, 1380d5315a23SMark Brown WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0), 1381d5315a23SMark Brown 1382d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1, 1383d5315a23SMark Brown WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0), 1384d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1, 1385d5315a23SMark Brown WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0), 1386d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1, 1387d5315a23SMark Brown WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0), 1388d5315a23SMark Brown 1389d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2, 1390d5315a23SMark Brown WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0), 1391d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2, 1392d5315a23SMark Brown WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0), 1393d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2, 1394d5315a23SMark Brown WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0), 1395d5315a23SMark Brown 1396d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2, 1397d5315a23SMark Brown WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0), 1398d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2, 1399d5315a23SMark Brown WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0), 1400d5315a23SMark Brown SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2, 1401d5315a23SMark Brown WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0), 1402d5315a23SMark Brown 1403d5315a23SMark Brown SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT, 1404d5315a23SMark Brown 0, NULL, 0), 1405d5315a23SMark Brown SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT, 1406d5315a23SMark Brown 0, NULL, 0), 1407d5315a23SMark Brown 1408d5315a23SMark Brown SND_SOC_DAPM_OUTPUT("EPOUTLN"), 1409d5315a23SMark Brown SND_SOC_DAPM_OUTPUT("EPOUTLP"), 1410d5315a23SMark Brown SND_SOC_DAPM_OUTPUT("EPOUTRN"), 1411d5315a23SMark Brown SND_SOC_DAPM_OUTPUT("EPOUTRP"), 1412d5315a23SMark Brown SND_SOC_DAPM_OUTPUT("SPK"), 1413d5315a23SMark Brown 1414d5315a23SMark Brown WM2200_MIXER_WIDGETS(EQL, "EQL"), 1415d5315a23SMark Brown WM2200_MIXER_WIDGETS(EQR, "EQR"), 1416d5315a23SMark Brown 1417d5315a23SMark Brown WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"), 1418d5315a23SMark Brown WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"), 1419d5315a23SMark Brown 142009d5d588SMark Brown WM2200_DSP_WIDGETS(DSP1, "DSP1"), 142109d5d588SMark Brown WM2200_DSP_WIDGETS(DSP2, "DSP2"), 1422d5315a23SMark Brown 1423d5315a23SMark Brown WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), 1424d5315a23SMark Brown WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), 1425d5315a23SMark Brown WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"), 1426d5315a23SMark Brown WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"), 1427d5315a23SMark Brown WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"), 1428d5315a23SMark Brown WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"), 1429d5315a23SMark Brown 1430d5315a23SMark Brown WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"), 1431d5315a23SMark Brown WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"), 1432d5315a23SMark Brown WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"), 1433d5315a23SMark Brown WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"), 1434d5315a23SMark Brown }; 1435d5315a23SMark Brown 1436d5315a23SMark Brown static const struct snd_soc_dapm_route wm2200_dapm_routes[] = { 1437d5315a23SMark Brown /* Everything needs SYSCLK but only hook up things on the edge 1438d5315a23SMark Brown * of the chip */ 1439d5315a23SMark Brown { "IN1L", NULL, "SYSCLK" }, 1440d5315a23SMark Brown { "IN1R", NULL, "SYSCLK" }, 1441d5315a23SMark Brown { "IN2L", NULL, "SYSCLK" }, 1442d5315a23SMark Brown { "IN2R", NULL, "SYSCLK" }, 1443d5315a23SMark Brown { "IN3L", NULL, "SYSCLK" }, 1444d5315a23SMark Brown { "IN3R", NULL, "SYSCLK" }, 1445d5315a23SMark Brown { "OUT1L", NULL, "SYSCLK" }, 1446d5315a23SMark Brown { "OUT1R", NULL, "SYSCLK" }, 1447d5315a23SMark Brown { "OUT2L", NULL, "SYSCLK" }, 1448d5315a23SMark Brown { "OUT2R", NULL, "SYSCLK" }, 1449d5315a23SMark Brown { "AIF1RX1", NULL, "SYSCLK" }, 1450d5315a23SMark Brown { "AIF1RX2", NULL, "SYSCLK" }, 1451d5315a23SMark Brown { "AIF1RX3", NULL, "SYSCLK" }, 1452d5315a23SMark Brown { "AIF1RX4", NULL, "SYSCLK" }, 1453d5315a23SMark Brown { "AIF1RX5", NULL, "SYSCLK" }, 1454d5315a23SMark Brown { "AIF1RX6", NULL, "SYSCLK" }, 1455d5315a23SMark Brown { "AIF1TX1", NULL, "SYSCLK" }, 1456d5315a23SMark Brown { "AIF1TX2", NULL, "SYSCLK" }, 1457d5315a23SMark Brown { "AIF1TX3", NULL, "SYSCLK" }, 1458d5315a23SMark Brown { "AIF1TX4", NULL, "SYSCLK" }, 1459d5315a23SMark Brown { "AIF1TX5", NULL, "SYSCLK" }, 1460d5315a23SMark Brown { "AIF1TX6", NULL, "SYSCLK" }, 1461d5315a23SMark Brown 1462d5315a23SMark Brown { "IN1L", NULL, "AVDD" }, 1463d5315a23SMark Brown { "IN1R", NULL, "AVDD" }, 1464d5315a23SMark Brown { "IN2L", NULL, "AVDD" }, 1465d5315a23SMark Brown { "IN2R", NULL, "AVDD" }, 1466d5315a23SMark Brown { "IN3L", NULL, "AVDD" }, 1467d5315a23SMark Brown { "IN3R", NULL, "AVDD" }, 1468d5315a23SMark Brown { "OUT1L", NULL, "AVDD" }, 1469d5315a23SMark Brown { "OUT1R", NULL, "AVDD" }, 1470d5315a23SMark Brown 1471d5315a23SMark Brown { "IN1L PGA", NULL, "IN1L" }, 1472d5315a23SMark Brown { "IN1R PGA", NULL, "IN1R" }, 1473d5315a23SMark Brown { "IN2L PGA", NULL, "IN2L" }, 1474d5315a23SMark Brown { "IN2R PGA", NULL, "IN2R" }, 1475d5315a23SMark Brown { "IN3L PGA", NULL, "IN3L" }, 1476d5315a23SMark Brown { "IN3R PGA", NULL, "IN3R" }, 1477d5315a23SMark Brown 1478d5315a23SMark Brown { "Tone Generator", NULL, "TONE" }, 1479d5315a23SMark Brown 1480d5315a23SMark Brown { "CP2", NULL, "CPVDD" }, 1481d5315a23SMark Brown { "MICBIAS1", NULL, "CP2" }, 1482d5315a23SMark Brown { "MICBIAS2", NULL, "CP2" }, 1483d5315a23SMark Brown 1484d5315a23SMark Brown { "CP1", NULL, "CPVDD" }, 1485d5315a23SMark Brown { "EPD_LN", NULL, "CP1" }, 1486d5315a23SMark Brown { "EPD_LP", NULL, "CP1" }, 1487d5315a23SMark Brown { "EPD_RN", NULL, "CP1" }, 1488d5315a23SMark Brown { "EPD_RP", NULL, "CP1" }, 1489d5315a23SMark Brown 1490d5315a23SMark Brown { "EPD_LP", NULL, "OUT1L" }, 1491d5315a23SMark Brown { "EPD_OUTP_LP", NULL, "EPD_LP" }, 1492d5315a23SMark Brown { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" }, 1493d5315a23SMark Brown { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" }, 1494d5315a23SMark Brown 1495d5315a23SMark Brown { "EPD_LN", NULL, "OUT1L" }, 1496d5315a23SMark Brown { "EPD_OUTP_LN", NULL, "EPD_LN" }, 1497d5315a23SMark Brown { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" }, 1498d5315a23SMark Brown { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" }, 1499d5315a23SMark Brown 1500d5315a23SMark Brown { "EPD_RP", NULL, "OUT1R" }, 1501d5315a23SMark Brown { "EPD_OUTP_RP", NULL, "EPD_RP" }, 1502d5315a23SMark Brown { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" }, 1503d5315a23SMark Brown { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" }, 1504d5315a23SMark Brown 1505d5315a23SMark Brown { "EPD_RN", NULL, "OUT1R" }, 1506d5315a23SMark Brown { "EPD_OUTP_RN", NULL, "EPD_RN" }, 1507d5315a23SMark Brown { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" }, 1508d5315a23SMark Brown { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" }, 1509d5315a23SMark Brown 1510d5315a23SMark Brown { "SPK", NULL, "OUT2L" }, 1511d5315a23SMark Brown { "SPK", NULL, "OUT2R" }, 1512d5315a23SMark Brown 1513999e068eSMark Brown { "AEC Loopback", "OUT1L", "OUT1L" }, 1514999e068eSMark Brown { "AEC Loopback", "OUT1R", "OUT1R" }, 1515999e068eSMark Brown { "AEC Loopback", "OUT2L", "OUT2L" }, 1516999e068eSMark Brown { "AEC Loopback", "OUT2R", "OUT2R" }, 1517999e068eSMark Brown 1518d5315a23SMark Brown WM2200_MIXER_ROUTES("DSP1", "DSP1L"), 1519d5315a23SMark Brown WM2200_MIXER_ROUTES("DSP1", "DSP1R"), 1520d5315a23SMark Brown WM2200_MIXER_ROUTES("DSP2", "DSP2L"), 1521d5315a23SMark Brown WM2200_MIXER_ROUTES("DSP2", "DSP2R"), 1522d5315a23SMark Brown 152309d5d588SMark Brown WM2200_DSP_AUX_ROUTES("DSP1"), 152409d5d588SMark Brown WM2200_DSP_AUX_ROUTES("DSP2"), 152509d5d588SMark Brown 1526d5315a23SMark Brown WM2200_MIXER_ROUTES("OUT1L", "OUT1L"), 1527d5315a23SMark Brown WM2200_MIXER_ROUTES("OUT1R", "OUT1R"), 1528d5315a23SMark Brown WM2200_MIXER_ROUTES("OUT2L", "OUT2L"), 1529d5315a23SMark Brown WM2200_MIXER_ROUTES("OUT2R", "OUT2R"), 1530d5315a23SMark Brown 1531d5315a23SMark Brown WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"), 1532d5315a23SMark Brown WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"), 1533d5315a23SMark Brown WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"), 1534d5315a23SMark Brown WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"), 1535d5315a23SMark Brown WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"), 1536d5315a23SMark Brown WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"), 1537d5315a23SMark Brown 1538d5315a23SMark Brown WM2200_MIXER_ROUTES("EQL", "EQL"), 1539d5315a23SMark Brown WM2200_MIXER_ROUTES("EQR", "EQR"), 1540d5315a23SMark Brown 1541d5315a23SMark Brown WM2200_MIXER_ROUTES("LHPF1", "LHPF1"), 1542d5315a23SMark Brown WM2200_MIXER_ROUTES("LHPF2", "LHPF2"), 1543d5315a23SMark Brown }; 1544d5315a23SMark Brown 1545908b5308SKuninori Morimoto static int wm2200_probe(struct snd_soc_component *component) 1546d5315a23SMark Brown { 1547908b5308SKuninori Morimoto struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); 1548d5315a23SMark Brown 1549908b5308SKuninori Morimoto wm2200->component = component; 1550d5315a23SMark Brown 15510a047f07SRichard Fitzgerald return 0; 1552d5315a23SMark Brown } 1553d5315a23SMark Brown 1554d5315a23SMark Brown static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 1555d5315a23SMark Brown { 1556908b5308SKuninori Morimoto struct snd_soc_component *component = dai->component; 1557d5315a23SMark Brown int lrclk, bclk, fmt_val; 1558d5315a23SMark Brown 1559d5315a23SMark Brown lrclk = 0; 1560d5315a23SMark Brown bclk = 0; 1561d5315a23SMark Brown 1562d5315a23SMark Brown switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 1563d5315a23SMark Brown case SND_SOC_DAIFMT_DSP_A: 1564d5315a23SMark Brown fmt_val = 0; 1565d5315a23SMark Brown break; 1566d5315a23SMark Brown case SND_SOC_DAIFMT_I2S: 1567d5315a23SMark Brown fmt_val = 2; 1568d5315a23SMark Brown break; 1569d5315a23SMark Brown default: 1570908b5308SKuninori Morimoto dev_err(component->dev, "Unsupported DAI format %d\n", 1571d5315a23SMark Brown fmt & SND_SOC_DAIFMT_FORMAT_MASK); 1572d5315a23SMark Brown return -EINVAL; 1573d5315a23SMark Brown } 1574d5315a23SMark Brown 1575d5315a23SMark Brown switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 1576d5315a23SMark Brown case SND_SOC_DAIFMT_CBS_CFS: 1577d5315a23SMark Brown break; 1578d5315a23SMark Brown case SND_SOC_DAIFMT_CBS_CFM: 1579d5315a23SMark Brown lrclk |= WM2200_AIF1TX_LRCLK_MSTR; 1580d5315a23SMark Brown break; 1581d5315a23SMark Brown case SND_SOC_DAIFMT_CBM_CFS: 1582d5315a23SMark Brown bclk |= WM2200_AIF1_BCLK_MSTR; 1583d5315a23SMark Brown break; 1584d5315a23SMark Brown case SND_SOC_DAIFMT_CBM_CFM: 1585d5315a23SMark Brown lrclk |= WM2200_AIF1TX_LRCLK_MSTR; 1586d5315a23SMark Brown bclk |= WM2200_AIF1_BCLK_MSTR; 1587d5315a23SMark Brown break; 1588d5315a23SMark Brown default: 1589908b5308SKuninori Morimoto dev_err(component->dev, "Unsupported master mode %d\n", 1590d5315a23SMark Brown fmt & SND_SOC_DAIFMT_MASTER_MASK); 1591d5315a23SMark Brown return -EINVAL; 1592d5315a23SMark Brown } 1593d5315a23SMark Brown 1594d5315a23SMark Brown switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 1595d5315a23SMark Brown case SND_SOC_DAIFMT_NB_NF: 1596d5315a23SMark Brown break; 1597d5315a23SMark Brown case SND_SOC_DAIFMT_IB_IF: 1598d5315a23SMark Brown bclk |= WM2200_AIF1_BCLK_INV; 1599d5315a23SMark Brown lrclk |= WM2200_AIF1TX_LRCLK_INV; 1600d5315a23SMark Brown break; 1601d5315a23SMark Brown case SND_SOC_DAIFMT_IB_NF: 1602d5315a23SMark Brown bclk |= WM2200_AIF1_BCLK_INV; 1603d5315a23SMark Brown break; 1604d5315a23SMark Brown case SND_SOC_DAIFMT_NB_IF: 1605d5315a23SMark Brown lrclk |= WM2200_AIF1TX_LRCLK_INV; 1606d5315a23SMark Brown break; 1607d5315a23SMark Brown default: 1608d5315a23SMark Brown return -EINVAL; 1609d5315a23SMark Brown } 1610d5315a23SMark Brown 1611908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR | 1612d5315a23SMark Brown WM2200_AIF1_BCLK_INV, bclk); 1613908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_2, 1614d5315a23SMark Brown WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, 1615d5315a23SMark Brown lrclk); 1616908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_3, 1617d5315a23SMark Brown WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, 1618d5315a23SMark Brown lrclk); 1619908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_5, 16202a5f4315SAxel Lin WM2200_AIF1_FMT_MASK, fmt_val); 1621d5315a23SMark Brown 1622d5315a23SMark Brown return 0; 1623d5315a23SMark Brown } 1624d5315a23SMark Brown 1625d5315a23SMark Brown static int wm2200_sr_code[] = { 1626d5315a23SMark Brown 0, 1627d5315a23SMark Brown 12000, 1628d5315a23SMark Brown 24000, 1629d5315a23SMark Brown 48000, 1630d5315a23SMark Brown 96000, 1631d5315a23SMark Brown 192000, 1632d5315a23SMark Brown 384000, 1633d5315a23SMark Brown 768000, 1634d5315a23SMark Brown 0, 1635d5315a23SMark Brown 11025, 1636d5315a23SMark Brown 22050, 1637d5315a23SMark Brown 44100, 1638d5315a23SMark Brown 88200, 1639d5315a23SMark Brown 176400, 1640d5315a23SMark Brown 352800, 1641d5315a23SMark Brown 705600, 1642d5315a23SMark Brown 4000, 1643d5315a23SMark Brown 8000, 1644d5315a23SMark Brown 16000, 1645d5315a23SMark Brown 32000, 1646d5315a23SMark Brown 64000, 1647d5315a23SMark Brown 128000, 1648d5315a23SMark Brown 256000, 1649d5315a23SMark Brown 512000, 1650d5315a23SMark Brown }; 1651d5315a23SMark Brown 1652d5315a23SMark Brown #define WM2200_NUM_BCLK_RATES 12 1653d5315a23SMark Brown 1654d5315a23SMark Brown static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = { 1655d5315a23SMark Brown 6144000, 1656d5315a23SMark Brown 3072000, 1657d5315a23SMark Brown 2048000, 1658d5315a23SMark Brown 1536000, 1659d5315a23SMark Brown 768000, 1660d5315a23SMark Brown 512000, 1661d5315a23SMark Brown 384000, 1662d5315a23SMark Brown 256000, 1663d5315a23SMark Brown 192000, 1664d5315a23SMark Brown 128000, 1665d5315a23SMark Brown 96000, 1666d5315a23SMark Brown 64000, 1667d5315a23SMark Brown }; 1668d5315a23SMark Brown 1669d5315a23SMark Brown static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = { 1670d5315a23SMark Brown 5644800, 1671b0dfa454SMark Brown 3763200, 1672d5315a23SMark Brown 2882400, 1673d5315a23SMark Brown 1881600, 1674d5315a23SMark Brown 1411200, 1675d5315a23SMark Brown 705600, 1676d5315a23SMark Brown 470400, 1677d5315a23SMark Brown 352800, 1678d5315a23SMark Brown 176400, 1679d5315a23SMark Brown 117600, 1680d5315a23SMark Brown 88200, 1681d5315a23SMark Brown 58800, 1682d5315a23SMark Brown }; 1683d5315a23SMark Brown 1684d5315a23SMark Brown static int wm2200_hw_params(struct snd_pcm_substream *substream, 1685d5315a23SMark Brown struct snd_pcm_hw_params *params, 1686d5315a23SMark Brown struct snd_soc_dai *dai) 1687d5315a23SMark Brown { 1688908b5308SKuninori Morimoto struct snd_soc_component *component = dai->component; 1689908b5308SKuninori Morimoto struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); 1690d5315a23SMark Brown int i, bclk, lrclk, wl, fl, sr_code; 1691d5315a23SMark Brown int *bclk_rates; 1692d5315a23SMark Brown 1693d5315a23SMark Brown /* Data sizes if not using TDM */ 16940a3dcb50SAxel Lin wl = params_width(params); 1695d5315a23SMark Brown if (wl < 0) 1696d5315a23SMark Brown return wl; 1697d5315a23SMark Brown fl = snd_soc_params_to_frame_size(params); 1698d5315a23SMark Brown if (fl < 0) 1699d5315a23SMark Brown return fl; 1700d5315a23SMark Brown 1701908b5308SKuninori Morimoto dev_dbg(component->dev, "Word length %d bits, frame length %d bits\n", 1702d5315a23SMark Brown wl, fl); 1703d5315a23SMark Brown 1704d5315a23SMark Brown /* Target BCLK rate */ 1705d5315a23SMark Brown bclk = snd_soc_params_to_bclk(params); 1706d5315a23SMark Brown if (bclk < 0) 1707d5315a23SMark Brown return bclk; 1708d5315a23SMark Brown 1709d5315a23SMark Brown if (!wm2200->sysclk) { 1710908b5308SKuninori Morimoto dev_err(component->dev, "SYSCLK has no rate set\n"); 1711d5315a23SMark Brown return -EINVAL; 1712d5315a23SMark Brown } 1713d5315a23SMark Brown 1714d5315a23SMark Brown for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++) 1715d5315a23SMark Brown if (wm2200_sr_code[i] == params_rate(params)) 1716d5315a23SMark Brown break; 1717d5315a23SMark Brown if (i == ARRAY_SIZE(wm2200_sr_code)) { 1718908b5308SKuninori Morimoto dev_err(component->dev, "Unsupported sample rate: %dHz\n", 1719d5315a23SMark Brown params_rate(params)); 1720d5315a23SMark Brown return -EINVAL; 1721d5315a23SMark Brown } 1722d5315a23SMark Brown sr_code = i; 1723d5315a23SMark Brown 1724908b5308SKuninori Morimoto dev_dbg(component->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n", 1725d5315a23SMark Brown bclk, wm2200->sysclk); 1726d5315a23SMark Brown 1727d5315a23SMark Brown if (wm2200->sysclk % 4000) 1728d5315a23SMark Brown bclk_rates = wm2200_bclk_rates_cd; 1729d5315a23SMark Brown else 1730d5315a23SMark Brown bclk_rates = wm2200_bclk_rates_dat; 1731d5315a23SMark Brown 1732d5315a23SMark Brown for (i = 0; i < WM2200_NUM_BCLK_RATES; i++) 1733d5315a23SMark Brown if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0)) 1734d5315a23SMark Brown break; 1735d5315a23SMark Brown if (i == WM2200_NUM_BCLK_RATES) { 1736908b5308SKuninori Morimoto dev_err(component->dev, 1737d5315a23SMark Brown "No valid BCLK for %dHz found from %dHz SYSCLK\n", 1738d5315a23SMark Brown bclk, wm2200->sysclk); 1739d5315a23SMark Brown return -EINVAL; 1740d5315a23SMark Brown } 1741d5315a23SMark Brown 1742d5315a23SMark Brown bclk = i; 1743908b5308SKuninori Morimoto dev_dbg(component->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]); 1744908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_1, 1745d5315a23SMark Brown WM2200_AIF1_BCLK_DIV_MASK, bclk); 1746d5315a23SMark Brown 1747d5315a23SMark Brown lrclk = bclk_rates[bclk] / params_rate(params); 1748908b5308SKuninori Morimoto dev_dbg(component->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk); 1749d5315a23SMark Brown if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || 17500e2d95aaSKuninori Morimoto wm2200->symmetric_rates) 1751908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_7, 1752d5315a23SMark Brown WM2200_AIF1RX_BCPF_MASK, lrclk); 1753d5315a23SMark Brown else 1754908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_6, 1755d5315a23SMark Brown WM2200_AIF1TX_BCPF_MASK, lrclk); 1756d5315a23SMark Brown 1757d5315a23SMark Brown i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl; 1758d5315a23SMark Brown if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1759908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_9, 1760d5315a23SMark Brown WM2200_AIF1RX_WL_MASK | 1761d5315a23SMark Brown WM2200_AIF1RX_SLOT_LEN_MASK, i); 1762d5315a23SMark Brown else 1763908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_8, 1764d5315a23SMark Brown WM2200_AIF1TX_WL_MASK | 1765d5315a23SMark Brown WM2200_AIF1TX_SLOT_LEN_MASK, i); 1766d5315a23SMark Brown 1767908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_CLOCKING_4, 1768d5315a23SMark Brown WM2200_SAMPLE_RATE_1_MASK, sr_code); 1769d5315a23SMark Brown 1770d5315a23SMark Brown return 0; 1771d5315a23SMark Brown } 1772d5315a23SMark Brown 1773d5315a23SMark Brown static const struct snd_soc_dai_ops wm2200_dai_ops = { 1774d5315a23SMark Brown .set_fmt = wm2200_set_fmt, 1775d5315a23SMark Brown .hw_params = wm2200_hw_params, 1776d5315a23SMark Brown }; 1777d5315a23SMark Brown 1778908b5308SKuninori Morimoto static int wm2200_set_sysclk(struct snd_soc_component *component, int clk_id, 1779d5315a23SMark Brown int source, unsigned int freq, int dir) 1780d5315a23SMark Brown { 1781908b5308SKuninori Morimoto struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); 1782d5315a23SMark Brown int fval; 1783d5315a23SMark Brown 1784d5315a23SMark Brown switch (clk_id) { 1785d5315a23SMark Brown case WM2200_CLK_SYSCLK: 1786d5315a23SMark Brown break; 1787d5315a23SMark Brown 1788d5315a23SMark Brown default: 1789908b5308SKuninori Morimoto dev_err(component->dev, "Unknown clock %d\n", clk_id); 1790d5315a23SMark Brown return -EINVAL; 1791d5315a23SMark Brown } 1792d5315a23SMark Brown 1793d5315a23SMark Brown switch (source) { 1794d5315a23SMark Brown case WM2200_CLKSRC_MCLK1: 1795d5315a23SMark Brown case WM2200_CLKSRC_MCLK2: 1796d5315a23SMark Brown case WM2200_CLKSRC_FLL: 1797d5315a23SMark Brown case WM2200_CLKSRC_BCLK1: 1798d5315a23SMark Brown break; 1799d5315a23SMark Brown default: 1800908b5308SKuninori Morimoto dev_err(component->dev, "Invalid source %d\n", source); 1801d5315a23SMark Brown return -EINVAL; 1802d5315a23SMark Brown } 1803d5315a23SMark Brown 1804d5315a23SMark Brown switch (freq) { 1805d5315a23SMark Brown case 22579200: 1806d5315a23SMark Brown case 24576000: 1807d5315a23SMark Brown fval = 2; 1808d5315a23SMark Brown break; 1809d5315a23SMark Brown default: 1810908b5308SKuninori Morimoto dev_err(component->dev, "Invalid clock rate: %d\n", freq); 1811d5315a23SMark Brown return -EINVAL; 1812d5315a23SMark Brown } 1813d5315a23SMark Brown 1814d5315a23SMark Brown /* TODO: Check if MCLKs are in use and enable/disable pulls to 1815d5315a23SMark Brown * match. 1816d5315a23SMark Brown */ 1817d5315a23SMark Brown 1818908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK | 1819d5315a23SMark Brown WM2200_SYSCLK_SRC_MASK, 1820d5315a23SMark Brown fval << WM2200_SYSCLK_FREQ_SHIFT | source); 1821d5315a23SMark Brown 1822d5315a23SMark Brown wm2200->sysclk = freq; 1823d5315a23SMark Brown 1824d5315a23SMark Brown return 0; 1825d5315a23SMark Brown } 1826d5315a23SMark Brown 1827d5315a23SMark Brown struct _fll_div { 1828d5315a23SMark Brown u16 fll_fratio; 1829d5315a23SMark Brown u16 fll_outdiv; 1830d5315a23SMark Brown u16 fll_refclk_div; 1831d5315a23SMark Brown u16 n; 1832d5315a23SMark Brown u16 theta; 1833d5315a23SMark Brown u16 lambda; 1834d5315a23SMark Brown }; 1835d5315a23SMark Brown 1836d5315a23SMark Brown static struct { 1837d5315a23SMark Brown unsigned int min; 1838d5315a23SMark Brown unsigned int max; 1839d5315a23SMark Brown u16 fll_fratio; 1840d5315a23SMark Brown int ratio; 1841d5315a23SMark Brown } fll_fratios[] = { 1842d5315a23SMark Brown { 0, 64000, 4, 16 }, 1843d5315a23SMark Brown { 64000, 128000, 3, 8 }, 1844d5315a23SMark Brown { 128000, 256000, 2, 4 }, 1845d5315a23SMark Brown { 256000, 1000000, 1, 2 }, 1846d5315a23SMark Brown { 1000000, 13500000, 0, 1 }, 1847d5315a23SMark Brown }; 1848d5315a23SMark Brown 1849d5315a23SMark Brown static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, 1850d5315a23SMark Brown unsigned int Fout) 1851d5315a23SMark Brown { 1852d5315a23SMark Brown unsigned int target; 1853d5315a23SMark Brown unsigned int div; 1854d5315a23SMark Brown unsigned int fratio, gcd_fll; 1855d5315a23SMark Brown int i; 1856d5315a23SMark Brown 1857d5315a23SMark Brown /* Fref must be <=13.5MHz */ 1858d5315a23SMark Brown div = 1; 1859d5315a23SMark Brown fll_div->fll_refclk_div = 0; 1860d5315a23SMark Brown while ((Fref / div) > 13500000) { 1861d5315a23SMark Brown div *= 2; 1862d5315a23SMark Brown fll_div->fll_refclk_div++; 1863d5315a23SMark Brown 1864d5315a23SMark Brown if (div > 8) { 1865d5315a23SMark Brown pr_err("Can't scale %dMHz input down to <=13.5MHz\n", 1866d5315a23SMark Brown Fref); 1867d5315a23SMark Brown return -EINVAL; 1868d5315a23SMark Brown } 1869d5315a23SMark Brown } 1870d5315a23SMark Brown 1871d5315a23SMark Brown pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout); 1872d5315a23SMark Brown 1873d5315a23SMark Brown /* Apply the division for our remaining calculations */ 1874d5315a23SMark Brown Fref /= div; 1875d5315a23SMark Brown 1876d5315a23SMark Brown /* Fvco should be 90-100MHz; don't check the upper bound */ 1877d5315a23SMark Brown div = 2; 1878d5315a23SMark Brown while (Fout * div < 90000000) { 1879d5315a23SMark Brown div++; 1880d5315a23SMark Brown if (div > 64) { 1881d5315a23SMark Brown pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", 1882d5315a23SMark Brown Fout); 1883d5315a23SMark Brown return -EINVAL; 1884d5315a23SMark Brown } 1885d5315a23SMark Brown } 1886d5315a23SMark Brown target = Fout * div; 1887d5315a23SMark Brown fll_div->fll_outdiv = div - 1; 1888d5315a23SMark Brown 1889d5315a23SMark Brown pr_debug("FLL Fvco=%dHz\n", target); 1890d5315a23SMark Brown 1891d5315a23SMark Brown /* Find an appropraite FLL_FRATIO and factor it out of the target */ 1892d5315a23SMark Brown for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { 1893d5315a23SMark Brown if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { 1894d5315a23SMark Brown fll_div->fll_fratio = fll_fratios[i].fll_fratio; 1895d5315a23SMark Brown fratio = fll_fratios[i].ratio; 1896d5315a23SMark Brown break; 1897d5315a23SMark Brown } 1898d5315a23SMark Brown } 1899d5315a23SMark Brown if (i == ARRAY_SIZE(fll_fratios)) { 1900d5315a23SMark Brown pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); 1901d5315a23SMark Brown return -EINVAL; 1902d5315a23SMark Brown } 1903d5315a23SMark Brown 1904d5315a23SMark Brown fll_div->n = target / (fratio * Fref); 1905d5315a23SMark Brown 1906d5315a23SMark Brown if (target % Fref == 0) { 1907d5315a23SMark Brown fll_div->theta = 0; 1908d5315a23SMark Brown fll_div->lambda = 0; 1909d5315a23SMark Brown } else { 1910d5315a23SMark Brown gcd_fll = gcd(target, fratio * Fref); 1911d5315a23SMark Brown 1912d5315a23SMark Brown fll_div->theta = (target - (fll_div->n * fratio * Fref)) 1913d5315a23SMark Brown / gcd_fll; 1914d5315a23SMark Brown fll_div->lambda = (fratio * Fref) / gcd_fll; 1915d5315a23SMark Brown } 1916d5315a23SMark Brown 1917d5315a23SMark Brown pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n", 1918d5315a23SMark Brown fll_div->n, fll_div->theta, fll_div->lambda); 1919d5315a23SMark Brown pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n", 1920d5315a23SMark Brown fll_div->fll_fratio, fratio, fll_div->fll_outdiv, 1921d5315a23SMark Brown fll_div->fll_refclk_div); 1922d5315a23SMark Brown 1923d5315a23SMark Brown return 0; 1924d5315a23SMark Brown } 1925d5315a23SMark Brown 1926908b5308SKuninori Morimoto static int wm2200_set_fll(struct snd_soc_component *component, int fll_id, int source, 1927d5315a23SMark Brown unsigned int Fref, unsigned int Fout) 1928d5315a23SMark Brown { 1929908b5308SKuninori Morimoto struct i2c_client *i2c = to_i2c_client(component->dev); 1930908b5308SKuninori Morimoto struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); 1931d5315a23SMark Brown struct _fll_div factors; 1932d5315a23SMark Brown int ret, i, timeout; 193378bb997aSNicholas Mc Guire unsigned long time_left; 1934d5315a23SMark Brown 1935d5315a23SMark Brown if (!Fout) { 1936908b5308SKuninori Morimoto dev_dbg(component->dev, "FLL disabled"); 1937d5315a23SMark Brown 1938d5315a23SMark Brown if (wm2200->fll_fout) 1939908b5308SKuninori Morimoto pm_runtime_put(component->dev); 1940d5315a23SMark Brown 1941d5315a23SMark Brown wm2200->fll_fout = 0; 1942908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_1, 1943d5315a23SMark Brown WM2200_FLL_ENA, 0); 1944d5315a23SMark Brown return 0; 1945d5315a23SMark Brown } 1946d5315a23SMark Brown 1947d5315a23SMark Brown switch (source) { 1948d5315a23SMark Brown case WM2200_FLL_SRC_MCLK1: 1949d5315a23SMark Brown case WM2200_FLL_SRC_MCLK2: 1950d5315a23SMark Brown case WM2200_FLL_SRC_BCLK: 1951d5315a23SMark Brown break; 1952d5315a23SMark Brown default: 1953908b5308SKuninori Morimoto dev_err(component->dev, "Invalid FLL source %d\n", source); 1954d5315a23SMark Brown return -EINVAL; 1955d5315a23SMark Brown } 1956d5315a23SMark Brown 1957d5315a23SMark Brown ret = fll_factors(&factors, Fref, Fout); 1958d5315a23SMark Brown if (ret < 0) 1959d5315a23SMark Brown return ret; 1960d5315a23SMark Brown 1961d5315a23SMark Brown /* Disable the FLL while we reconfigure */ 1962908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0); 1963d5315a23SMark Brown 1964908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_2, 1965d5315a23SMark Brown WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK, 1966d5315a23SMark Brown (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) | 1967d5315a23SMark Brown factors.fll_fratio); 1968d5315a23SMark Brown if (factors.theta) { 1969908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_3, 1970d5315a23SMark Brown WM2200_FLL_FRACN_ENA, 1971d5315a23SMark Brown WM2200_FLL_FRACN_ENA); 1972908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_EFS_2, 1973d5315a23SMark Brown WM2200_FLL_EFS_ENA, 1974d5315a23SMark Brown WM2200_FLL_EFS_ENA); 1975d5315a23SMark Brown } else { 1976908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_3, 1977d5315a23SMark Brown WM2200_FLL_FRACN_ENA, 0); 1978908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_EFS_2, 1979d5315a23SMark Brown WM2200_FLL_EFS_ENA, 0); 1980d5315a23SMark Brown } 1981d5315a23SMark Brown 1982908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK, 1983d5315a23SMark Brown factors.theta); 1984908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK, 1985d5315a23SMark Brown factors.n); 1986908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_7, 1987d5315a23SMark Brown WM2200_FLL_CLK_REF_DIV_MASK | 1988d5315a23SMark Brown WM2200_FLL_CLK_REF_SRC_MASK, 1989d5315a23SMark Brown (factors.fll_refclk_div 1990d5315a23SMark Brown << WM2200_FLL_CLK_REF_DIV_SHIFT) | source); 1991908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_EFS_1, 1992d5315a23SMark Brown WM2200_FLL_LAMBDA_MASK, factors.lambda); 1993d5315a23SMark Brown 1994d5315a23SMark Brown /* Clear any pending completions */ 1995d5315a23SMark Brown try_wait_for_completion(&wm2200->fll_lock); 1996d5315a23SMark Brown 1997908b5308SKuninori Morimoto pm_runtime_get_sync(component->dev); 1998d5315a23SMark Brown 1999908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_FLL_CONTROL_1, 2000d5315a23SMark Brown WM2200_FLL_ENA, WM2200_FLL_ENA); 2001d5315a23SMark Brown 2002d5315a23SMark Brown if (i2c->irq) 2003d5315a23SMark Brown timeout = 2; 2004d5315a23SMark Brown else 2005d5315a23SMark Brown timeout = 50; 2006d5315a23SMark Brown 2007908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA, 2008d5315a23SMark Brown WM2200_SYSCLK_ENA); 2009d5315a23SMark Brown 2010d5315a23SMark Brown /* Poll for the lock; will use the interrupt to exit quickly */ 2011d5315a23SMark Brown for (i = 0; i < timeout; i++) { 2012d5315a23SMark Brown if (i2c->irq) { 201378bb997aSNicholas Mc Guire time_left = wait_for_completion_timeout( 201478bb997aSNicholas Mc Guire &wm2200->fll_lock, 2015d5315a23SMark Brown msecs_to_jiffies(25)); 201678bb997aSNicholas Mc Guire if (time_left > 0) 2017d5315a23SMark Brown break; 2018d5315a23SMark Brown } else { 2019d5315a23SMark Brown msleep(1); 2020d5315a23SMark Brown } 2021d5315a23SMark Brown 20226d75dfc3SKuninori Morimoto ret = snd_soc_component_read(component, 2023d5315a23SMark Brown WM2200_INTERRUPT_RAW_STATUS_2); 2024d5315a23SMark Brown if (ret < 0) { 2025908b5308SKuninori Morimoto dev_err(component->dev, 2026d5315a23SMark Brown "Failed to read FLL status: %d\n", 2027d5315a23SMark Brown ret); 2028d5315a23SMark Brown continue; 2029d5315a23SMark Brown } 2030d5315a23SMark Brown if (ret & WM2200_FLL_LOCK_STS) 2031d5315a23SMark Brown break; 2032d5315a23SMark Brown } 2033d5315a23SMark Brown if (i == timeout) { 2034908b5308SKuninori Morimoto dev_err(component->dev, "FLL lock timed out\n"); 2035908b5308SKuninori Morimoto pm_runtime_put(component->dev); 2036d5315a23SMark Brown return -ETIMEDOUT; 2037d5315a23SMark Brown } 2038d5315a23SMark Brown 2039d5315a23SMark Brown wm2200->fll_src = source; 2040d5315a23SMark Brown wm2200->fll_fref = Fref; 2041d5315a23SMark Brown wm2200->fll_fout = Fout; 2042d5315a23SMark Brown 2043908b5308SKuninori Morimoto dev_dbg(component->dev, "FLL running %dHz->%dHz\n", Fref, Fout); 2044d5315a23SMark Brown 2045d5315a23SMark Brown return 0; 2046d5315a23SMark Brown } 2047d5315a23SMark Brown 2048d5315a23SMark Brown static int wm2200_dai_probe(struct snd_soc_dai *dai) 2049d5315a23SMark Brown { 2050908b5308SKuninori Morimoto struct snd_soc_component *component = dai->component; 2051908b5308SKuninori Morimoto struct wm2200_priv *wm2200 = snd_soc_component_get_drvdata(component); 2052d5315a23SMark Brown unsigned int val = 0; 2053d5315a23SMark Brown int ret; 2054d5315a23SMark Brown 20556d75dfc3SKuninori Morimoto ret = snd_soc_component_read(component, WM2200_GPIO_CTRL_1); 2056d5315a23SMark Brown if (ret >= 0) { 2057d5315a23SMark Brown if ((ret & WM2200_GP1_FN_MASK) != 0) { 20580e2d95aaSKuninori Morimoto wm2200->symmetric_rates = true; 2059d5315a23SMark Brown val = WM2200_AIF1TX_LRCLK_SRC; 2060d5315a23SMark Brown } 2061d5315a23SMark Brown } else { 2062908b5308SKuninori Morimoto dev_err(component->dev, "Failed to read GPIO 1 config: %d\n", ret); 2063d5315a23SMark Brown } 2064d5315a23SMark Brown 2065908b5308SKuninori Morimoto snd_soc_component_update_bits(component, WM2200_AUDIO_IF_1_2, 2066d5315a23SMark Brown WM2200_AIF1TX_LRCLK_SRC, val); 2067d5315a23SMark Brown 2068d5315a23SMark Brown return 0; 2069d5315a23SMark Brown } 2070d5315a23SMark Brown 2071d5315a23SMark Brown #define WM2200_RATES SNDRV_PCM_RATE_8000_48000 2072d5315a23SMark Brown 2073d5315a23SMark Brown #define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 2074d5315a23SMark Brown SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 2075d5315a23SMark Brown 2076d5315a23SMark Brown static struct snd_soc_dai_driver wm2200_dai = { 2077d5315a23SMark Brown .name = "wm2200", 2078d5315a23SMark Brown .probe = wm2200_dai_probe, 2079d5315a23SMark Brown .playback = { 2080d5315a23SMark Brown .stream_name = "Playback", 2081d5315a23SMark Brown .channels_min = 2, 2082d5315a23SMark Brown .channels_max = 2, 2083d5315a23SMark Brown .rates = WM2200_RATES, 2084d5315a23SMark Brown .formats = WM2200_FORMATS, 2085d5315a23SMark Brown }, 2086d5315a23SMark Brown .capture = { 2087d5315a23SMark Brown .stream_name = "Capture", 2088d5315a23SMark Brown .channels_min = 2, 2089d5315a23SMark Brown .channels_max = 2, 2090d5315a23SMark Brown .rates = WM2200_RATES, 2091d5315a23SMark Brown .formats = WM2200_FORMATS, 2092d5315a23SMark Brown }, 2093d5315a23SMark Brown .ops = &wm2200_dai_ops, 2094d5315a23SMark Brown }; 2095d5315a23SMark Brown 2096908b5308SKuninori Morimoto static const struct snd_soc_component_driver soc_component_wm2200 = { 2097d5315a23SMark Brown .probe = wm2200_probe, 2098d5315a23SMark Brown .set_sysclk = wm2200_set_sysclk, 2099d5315a23SMark Brown .set_pll = wm2200_set_fll, 2100d5315a23SMark Brown .controls = wm2200_snd_controls, 2101d5315a23SMark Brown .num_controls = ARRAY_SIZE(wm2200_snd_controls), 2102d5315a23SMark Brown .dapm_widgets = wm2200_dapm_widgets, 2103d5315a23SMark Brown .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets), 2104d5315a23SMark Brown .dapm_routes = wm2200_dapm_routes, 2105d5315a23SMark Brown .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes), 2106908b5308SKuninori Morimoto .endianness = 1, 2107d5315a23SMark Brown }; 2108d5315a23SMark Brown 2109d5315a23SMark Brown static irqreturn_t wm2200_irq(int irq, void *data) 2110d5315a23SMark Brown { 2111d5315a23SMark Brown struct wm2200_priv *wm2200 = data; 2112d5315a23SMark Brown unsigned int val, mask; 2113d5315a23SMark Brown int ret; 2114d5315a23SMark Brown 2115d5315a23SMark Brown ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val); 2116d5315a23SMark Brown if (ret != 0) { 2117d5315a23SMark Brown dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret); 2118d5315a23SMark Brown return IRQ_NONE; 2119d5315a23SMark Brown } 2120d5315a23SMark Brown 2121d5315a23SMark Brown ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK, 2122d5315a23SMark Brown &mask); 2123d5315a23SMark Brown if (ret != 0) { 2124d5315a23SMark Brown dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret); 2125d5315a23SMark Brown mask = 0; 2126d5315a23SMark Brown } 2127d5315a23SMark Brown 2128d5315a23SMark Brown val &= ~mask; 2129d5315a23SMark Brown 2130d5315a23SMark Brown if (val & WM2200_FLL_LOCK_EINT) { 2131d5315a23SMark Brown dev_dbg(wm2200->dev, "FLL locked\n"); 2132d5315a23SMark Brown complete(&wm2200->fll_lock); 2133d5315a23SMark Brown } 2134d5315a23SMark Brown 2135d5315a23SMark Brown if (val) { 2136d5315a23SMark Brown regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val); 2137d5315a23SMark Brown 2138d5315a23SMark Brown return IRQ_HANDLED; 2139d5315a23SMark Brown } else { 2140d5315a23SMark Brown return IRQ_NONE; 2141d5315a23SMark Brown } 2142d5315a23SMark Brown } 2143d5315a23SMark Brown 2144d5315a23SMark Brown static const struct regmap_config wm2200_regmap = { 2145d5315a23SMark Brown .reg_bits = 16, 2146d5315a23SMark Brown .val_bits = 16, 2147d5315a23SMark Brown 2148eae2328dSMark Brown .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) * 2149eae2328dSMark Brown WM2200_DSP_SPACING), 2150d5315a23SMark Brown .reg_defaults = wm2200_reg_defaults, 2151d5315a23SMark Brown .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults), 2152d5315a23SMark Brown .volatile_reg = wm2200_volatile_register, 2153d5315a23SMark Brown .readable_reg = wm2200_readable_register, 2154d5315a23SMark Brown .cache_type = REGCACHE_RBTREE, 2155eae2328dSMark Brown .ranges = wm2200_ranges, 2156eae2328dSMark Brown .num_ranges = ARRAY_SIZE(wm2200_ranges), 2157d5315a23SMark Brown }; 2158d5315a23SMark Brown 2159d5315a23SMark Brown static const unsigned int wm2200_dig_vu[] = { 2160d5315a23SMark Brown WM2200_DAC_DIGITAL_VOLUME_1L, 2161d5315a23SMark Brown WM2200_DAC_DIGITAL_VOLUME_1R, 2162d5315a23SMark Brown WM2200_DAC_DIGITAL_VOLUME_2L, 2163d5315a23SMark Brown WM2200_DAC_DIGITAL_VOLUME_2R, 2164d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_1L, 2165d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_1R, 2166d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_2L, 2167d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_2R, 2168d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_3L, 2169d5315a23SMark Brown WM2200_ADC_DIGITAL_VOLUME_3R, 2170d5315a23SMark Brown }; 2171d5315a23SMark Brown 2172d5315a23SMark Brown static const unsigned int wm2200_mic_ctrl_reg[] = { 2173d5315a23SMark Brown WM2200_IN1L_CONTROL, 2174d5315a23SMark Brown WM2200_IN2L_CONTROL, 2175d5315a23SMark Brown WM2200_IN3L_CONTROL, 2176d5315a23SMark Brown }; 2177d5315a23SMark Brown 217897b0b6e3SStephen Kitt static int wm2200_i2c_probe(struct i2c_client *i2c) 2179d5315a23SMark Brown { 2180d5315a23SMark Brown struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev); 2181d5315a23SMark Brown struct wm2200_priv *wm2200; 2182d5315a23SMark Brown unsigned int reg; 2183d5315a23SMark Brown int ret, i; 21841a786243SChris Rattray int val; 2185d5315a23SMark Brown 2186d5315a23SMark Brown wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv), 2187d5315a23SMark Brown GFP_KERNEL); 2188d5315a23SMark Brown if (wm2200 == NULL) 2189d5315a23SMark Brown return -ENOMEM; 2190d5315a23SMark Brown 2191d5315a23SMark Brown wm2200->dev = &i2c->dev; 2192d5315a23SMark Brown init_completion(&wm2200->fll_lock); 2193d5315a23SMark Brown 219498ad089fSMark Brown wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap); 2195d5315a23SMark Brown if (IS_ERR(wm2200->regmap)) { 2196d5315a23SMark Brown ret = PTR_ERR(wm2200->regmap); 2197d5315a23SMark Brown dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 2198d5315a23SMark Brown ret); 2199f55ec27fSSachin Kamat return ret; 2200d5315a23SMark Brown } 2201d5315a23SMark Brown 2202f017eb29SMark Brown for (i = 0; i < 2; i++) { 2203e1468202SSimon Trimmer wm2200->dsp[i].cs_dsp.type = WMFW_ADSP1; 2204f017eb29SMark Brown wm2200->dsp[i].part = "wm2200"; 2205e1468202SSimon Trimmer wm2200->dsp[i].cs_dsp.num = i + 1; 2206e1468202SSimon Trimmer wm2200->dsp[i].cs_dsp.dev = &i2c->dev; 2207e1468202SSimon Trimmer wm2200->dsp[i].cs_dsp.regmap = wm2200->regmap; 2208e1468202SSimon Trimmer wm2200->dsp[i].cs_dsp.sysclk_reg = WM2200_CLOCKING_3; 2209e1468202SSimon Trimmer wm2200->dsp[i].cs_dsp.sysclk_mask = WM2200_SYSCLK_FREQ_MASK; 2210e1468202SSimon Trimmer wm2200->dsp[i].cs_dsp.sysclk_shift = WM2200_SYSCLK_FREQ_SHIFT; 2211f017eb29SMark Brown } 2212f017eb29SMark Brown 2213e1468202SSimon Trimmer wm2200->dsp[0].cs_dsp.base = WM2200_DSP1_CONTROL_1; 2214e1468202SSimon Trimmer wm2200->dsp[0].cs_dsp.mem = wm2200_dsp1_regions; 2215e1468202SSimon Trimmer wm2200->dsp[0].cs_dsp.num_mems = ARRAY_SIZE(wm2200_dsp1_regions); 2216f017eb29SMark Brown 2217e1468202SSimon Trimmer wm2200->dsp[1].cs_dsp.base = WM2200_DSP2_CONTROL_1; 2218e1468202SSimon Trimmer wm2200->dsp[1].cs_dsp.mem = wm2200_dsp2_regions; 2219e1468202SSimon Trimmer wm2200->dsp[1].cs_dsp.num_mems = ARRAY_SIZE(wm2200_dsp2_regions); 2220f017eb29SMark Brown 22215851cb3dSMark Brown for (i = 0; i < ARRAY_SIZE(wm2200->dsp); i++) 22225851cb3dSMark Brown wm_adsp1_init(&wm2200->dsp[i]); 22235851cb3dSMark Brown 2224d5315a23SMark Brown if (pdata) 2225d5315a23SMark Brown wm2200->pdata = *pdata; 2226d5315a23SMark Brown 2227d5315a23SMark Brown i2c_set_clientdata(i2c, wm2200); 2228d5315a23SMark Brown 2229d5315a23SMark Brown for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++) 2230d5315a23SMark Brown wm2200->core_supplies[i].supply = wm2200_core_supply_names[i]; 2231d5315a23SMark Brown 223298ad089fSMark Brown ret = devm_regulator_bulk_get(&i2c->dev, 223398ad089fSMark Brown ARRAY_SIZE(wm2200->core_supplies), 2234d5315a23SMark Brown wm2200->core_supplies); 2235d5315a23SMark Brown if (ret != 0) { 2236d5315a23SMark Brown dev_err(&i2c->dev, "Failed to request core supplies: %d\n", 2237d5315a23SMark Brown ret); 2238f55ec27fSSachin Kamat return ret; 2239d5315a23SMark Brown } 2240d5315a23SMark Brown 2241d5315a23SMark Brown ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies), 2242d5315a23SMark Brown wm2200->core_supplies); 2243d5315a23SMark Brown if (ret != 0) { 2244d5315a23SMark Brown dev_err(&i2c->dev, "Failed to enable core supplies: %d\n", 2245d5315a23SMark Brown ret); 2246f55ec27fSSachin Kamat return ret; 2247d5315a23SMark Brown } 2248d5315a23SMark Brown 2249d5315a23SMark Brown if (wm2200->pdata.ldo_ena) { 225098ad089fSMark Brown ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena, 225198ad089fSMark Brown GPIOF_OUT_INIT_HIGH, 225298ad089fSMark Brown "WM2200 LDOENA"); 2253d5315a23SMark Brown if (ret < 0) { 2254d5315a23SMark Brown dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", 2255d5315a23SMark Brown wm2200->pdata.ldo_ena, ret); 2256d5315a23SMark Brown goto err_enable; 2257d5315a23SMark Brown } 2258d5315a23SMark Brown msleep(2); 2259d5315a23SMark Brown } 2260d5315a23SMark Brown 2261d5315a23SMark Brown if (wm2200->pdata.reset) { 226298ad089fSMark Brown ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset, 226398ad089fSMark Brown GPIOF_OUT_INIT_HIGH, 226498ad089fSMark Brown "WM2200 /RESET"); 2265d5315a23SMark Brown if (ret < 0) { 2266d5315a23SMark Brown dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", 2267d5315a23SMark Brown wm2200->pdata.reset, ret); 2268d5315a23SMark Brown goto err_ldo; 2269d5315a23SMark Brown } 2270d5315a23SMark Brown } 2271d5315a23SMark Brown 2272d5315a23SMark Brown ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, ®); 2273d5315a23SMark Brown if (ret < 0) { 2274d5315a23SMark Brown dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); 2275d5315a23SMark Brown goto err_reset; 2276d5315a23SMark Brown } 2277d5315a23SMark Brown switch (reg) { 2278d5315a23SMark Brown case 0x2200: 2279d5315a23SMark Brown break; 2280d5315a23SMark Brown 2281d5315a23SMark Brown default: 2282d5315a23SMark Brown dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg); 2283d5315a23SMark Brown ret = -EINVAL; 2284d5315a23SMark Brown goto err_reset; 2285d5315a23SMark Brown } 2286d5315a23SMark Brown 2287d5315a23SMark Brown ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, ®); 2288d5315a23SMark Brown if (ret < 0) { 2289d5315a23SMark Brown dev_err(&i2c->dev, "Failed to read revision register\n"); 2290d5315a23SMark Brown goto err_reset; 2291d5315a23SMark Brown } 2292d5315a23SMark Brown 2293916be22cSAxel Lin wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK; 2294d5315a23SMark Brown 2295d5315a23SMark Brown dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A'); 2296d5315a23SMark Brown 2297d5315a23SMark Brown switch (wm2200->rev) { 2298d5315a23SMark Brown case 0: 22995ae9eb4cSMark Brown case 1: 2300d5315a23SMark Brown ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch, 2301d5315a23SMark Brown ARRAY_SIZE(wm2200_reva_patch)); 2302d5315a23SMark Brown if (ret != 0) { 2303d5315a23SMark Brown dev_err(&i2c->dev, "Failed to register patch: %d\n", 2304d5315a23SMark Brown ret); 2305d5315a23SMark Brown } 2306d5315a23SMark Brown break; 2307d5315a23SMark Brown default: 2308d5315a23SMark Brown break; 2309d5315a23SMark Brown } 2310d5315a23SMark Brown 2311d5315a23SMark Brown ret = wm2200_reset(wm2200); 2312d5315a23SMark Brown if (ret < 0) { 2313d5315a23SMark Brown dev_err(&i2c->dev, "Failed to issue reset\n"); 2314d5315a23SMark Brown goto err_reset; 2315d5315a23SMark Brown } 2316d5315a23SMark Brown 2317d5315a23SMark Brown for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) { 2318d5315a23SMark Brown if (!wm2200->pdata.gpio_defaults[i]) 2319d5315a23SMark Brown continue; 2320d5315a23SMark Brown 2321d5315a23SMark Brown regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i, 2322d5315a23SMark Brown wm2200->pdata.gpio_defaults[i]); 2323d5315a23SMark Brown } 2324d5315a23SMark Brown 2325d5315a23SMark Brown for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++) 2326d5315a23SMark Brown regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i], 2327d5315a23SMark Brown WM2200_OUT_VU, WM2200_OUT_VU); 2328d5315a23SMark Brown 2329d5315a23SMark Brown /* Assign slots 1-6 to channels 1-6 for both TX and RX */ 2330d5315a23SMark Brown for (i = 0; i < 6; i++) { 2331d5315a23SMark Brown regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i); 2332d5315a23SMark Brown regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i); 2333d5315a23SMark Brown } 2334d5315a23SMark Brown 23351a786243SChris Rattray for (i = 0; i < WM2200_MAX_MICBIAS; i++) { 23361a786243SChris Rattray if (!wm2200->pdata.micbias[i].mb_lvl && 23371a786243SChris Rattray !wm2200->pdata.micbias[i].bypass) 23381a786243SChris Rattray continue; 23391a786243SChris Rattray 23401a786243SChris Rattray /* Apply default for bypass mode */ 23411a786243SChris Rattray if (!wm2200->pdata.micbias[i].mb_lvl) 23421a786243SChris Rattray wm2200->pdata.micbias[i].mb_lvl 23431a786243SChris Rattray = WM2200_MBIAS_LVL_1V5; 23441a786243SChris Rattray 23451a786243SChris Rattray val = (wm2200->pdata.micbias[i].mb_lvl -1) 23461a786243SChris Rattray << WM2200_MICB1_LVL_SHIFT; 23471a786243SChris Rattray 23481a786243SChris Rattray if (wm2200->pdata.micbias[i].discharge) 23491a786243SChris Rattray val |= WM2200_MICB1_DISCH; 23501a786243SChris Rattray 23511a786243SChris Rattray if (wm2200->pdata.micbias[i].fast_start) 23521a786243SChris Rattray val |= WM2200_MICB1_RATE; 23531a786243SChris Rattray 23541a786243SChris Rattray if (wm2200->pdata.micbias[i].bypass) 23551a786243SChris Rattray val |= WM2200_MICB1_MODE; 23561a786243SChris Rattray 23571a786243SChris Rattray regmap_update_bits(wm2200->regmap, 23581a786243SChris Rattray WM2200_MIC_BIAS_CTRL_1 + i, 23591a786243SChris Rattray WM2200_MICB1_LVL_MASK | 23601a786243SChris Rattray WM2200_MICB1_DISCH | 23611a786243SChris Rattray WM2200_MICB1_MODE | 23621a786243SChris Rattray WM2200_MICB1_RATE, val); 23631a786243SChris Rattray } 23641a786243SChris Rattray 2365d5315a23SMark Brown for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) { 2366d5315a23SMark Brown regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i], 2367d5315a23SMark Brown WM2200_IN1_MODE_MASK | 2368d5315a23SMark Brown WM2200_IN1_DMIC_SUP_MASK, 2369d5315a23SMark Brown (wm2200->pdata.in_mode[i] << 2370d5315a23SMark Brown WM2200_IN1_MODE_SHIFT) | 2371d5315a23SMark Brown (wm2200->pdata.dmic_sup[i] << 2372d5315a23SMark Brown WM2200_IN1_DMIC_SUP_SHIFT)); 2373d5315a23SMark Brown } 2374d5315a23SMark Brown 2375d5315a23SMark Brown if (i2c->irq) { 2376d5315a23SMark Brown ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq, 2377d5315a23SMark Brown IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 2378d5315a23SMark Brown "wm2200", wm2200); 2379d5315a23SMark Brown if (ret == 0) 2380d5315a23SMark Brown regmap_update_bits(wm2200->regmap, 2381d5315a23SMark Brown WM2200_INTERRUPT_STATUS_2_MASK, 2382d5315a23SMark Brown WM2200_FLL_LOCK_EINT, 0); 2383d5315a23SMark Brown else 2384d5315a23SMark Brown dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", 2385d5315a23SMark Brown i2c->irq, ret); 2386d5315a23SMark Brown } 2387d5315a23SMark Brown 2388d5315a23SMark Brown pm_runtime_set_active(&i2c->dev); 2389d5315a23SMark Brown pm_runtime_enable(&i2c->dev); 2390d5315a23SMark Brown pm_request_idle(&i2c->dev); 2391d5315a23SMark Brown 2392908b5308SKuninori Morimoto ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_wm2200, 2393d5315a23SMark Brown &wm2200_dai, 1); 2394d5315a23SMark Brown if (ret != 0) { 2395d5315a23SMark Brown dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); 2396d5315a23SMark Brown goto err_pm_runtime; 2397d5315a23SMark Brown } 2398d5315a23SMark Brown 2399d5315a23SMark Brown return 0; 2400d5315a23SMark Brown 2401d5315a23SMark Brown err_pm_runtime: 2402d5315a23SMark Brown pm_runtime_disable(&i2c->dev); 24032dab09beSChuhong Yuan if (i2c->irq) 24042dab09beSChuhong Yuan free_irq(i2c->irq, wm2200); 2405d5315a23SMark Brown err_reset: 240698ad089fSMark Brown if (wm2200->pdata.reset) 2407d5315a23SMark Brown gpio_set_value_cansleep(wm2200->pdata.reset, 0); 2408d5315a23SMark Brown err_ldo: 240998ad089fSMark Brown if (wm2200->pdata.ldo_ena) 2410d5315a23SMark Brown gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); 2411d5315a23SMark Brown err_enable: 2412d5315a23SMark Brown regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), 2413d5315a23SMark Brown wm2200->core_supplies); 2414d5315a23SMark Brown return ret; 2415d5315a23SMark Brown } 2416d5315a23SMark Brown 2417*ed5c2f5fSUwe Kleine-König static void wm2200_i2c_remove(struct i2c_client *i2c) 2418d5315a23SMark Brown { 2419d5315a23SMark Brown struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c); 2420d5315a23SMark Brown 24212dab09beSChuhong Yuan pm_runtime_disable(&i2c->dev); 2422d5315a23SMark Brown if (i2c->irq) 2423d5315a23SMark Brown free_irq(i2c->irq, wm2200); 242498ad089fSMark Brown if (wm2200->pdata.reset) 2425d5315a23SMark Brown gpio_set_value_cansleep(wm2200->pdata.reset, 0); 242698ad089fSMark Brown if (wm2200->pdata.ldo_ena) 2427d5315a23SMark Brown gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); 24282dab09beSChuhong Yuan regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), 24292dab09beSChuhong Yuan wm2200->core_supplies); 2430d5315a23SMark Brown } 2431d5315a23SMark Brown 2432641d334bSRafael J. Wysocki #ifdef CONFIG_PM 2433d5315a23SMark Brown static int wm2200_runtime_suspend(struct device *dev) 2434d5315a23SMark Brown { 2435d5315a23SMark Brown struct wm2200_priv *wm2200 = dev_get_drvdata(dev); 2436d5315a23SMark Brown 2437d5315a23SMark Brown regcache_cache_only(wm2200->regmap, true); 2438d5315a23SMark Brown regcache_mark_dirty(wm2200->regmap); 2439d5315a23SMark Brown if (wm2200->pdata.ldo_ena) 2440d5315a23SMark Brown gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); 2441d5315a23SMark Brown regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), 2442d5315a23SMark Brown wm2200->core_supplies); 2443d5315a23SMark Brown 2444d5315a23SMark Brown return 0; 2445d5315a23SMark Brown } 2446d5315a23SMark Brown 2447d5315a23SMark Brown static int wm2200_runtime_resume(struct device *dev) 2448d5315a23SMark Brown { 2449d5315a23SMark Brown struct wm2200_priv *wm2200 = dev_get_drvdata(dev); 2450d5315a23SMark Brown int ret; 2451d5315a23SMark Brown 2452d5315a23SMark Brown ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies), 2453d5315a23SMark Brown wm2200->core_supplies); 2454d5315a23SMark Brown if (ret != 0) { 2455d5315a23SMark Brown dev_err(dev, "Failed to enable supplies: %d\n", 2456d5315a23SMark Brown ret); 2457d5315a23SMark Brown return ret; 2458d5315a23SMark Brown } 2459d5315a23SMark Brown 2460d5315a23SMark Brown if (wm2200->pdata.ldo_ena) { 2461d5315a23SMark Brown gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1); 2462d5315a23SMark Brown msleep(2); 2463d5315a23SMark Brown } 2464d5315a23SMark Brown 2465d5315a23SMark Brown regcache_cache_only(wm2200->regmap, false); 2466d5315a23SMark Brown regcache_sync(wm2200->regmap); 2467d5315a23SMark Brown 2468d5315a23SMark Brown return 0; 2469d5315a23SMark Brown } 2470d5315a23SMark Brown #endif 2471d5315a23SMark Brown 247242d1b8ceSAxel Lin static const struct dev_pm_ops wm2200_pm = { 2473d5315a23SMark Brown SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume, 2474d5315a23SMark Brown NULL) 2475d5315a23SMark Brown }; 2476d5315a23SMark Brown 2477d5315a23SMark Brown static const struct i2c_device_id wm2200_i2c_id[] = { 2478d5315a23SMark Brown { "wm2200", 0 }, 2479d5315a23SMark Brown { } 2480d5315a23SMark Brown }; 2481d5315a23SMark Brown MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id); 2482d5315a23SMark Brown 2483d5315a23SMark Brown static struct i2c_driver wm2200_i2c_driver = { 2484d5315a23SMark Brown .driver = { 2485d5315a23SMark Brown .name = "wm2200", 2486d5315a23SMark Brown .pm = &wm2200_pm, 2487d5315a23SMark Brown }, 248897b0b6e3SStephen Kitt .probe_new = wm2200_i2c_probe, 24897a79e94eSBill Pemberton .remove = wm2200_i2c_remove, 2490d5315a23SMark Brown .id_table = wm2200_i2c_id, 2491d5315a23SMark Brown }; 2492d5315a23SMark Brown 2493a9418ddcSSachin Kamat module_i2c_driver(wm2200_i2c_driver); 2494d5315a23SMark Brown 2495d5315a23SMark Brown MODULE_DESCRIPTION("ASoC WM2200 driver"); 2496d5315a23SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 2497d5315a23SMark Brown MODULE_LICENSE("GPL"); 2498