1112 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * wm8983.c -- WM8983 ALSA SoC Audio driver4 *5 * Copyright 2011 Wolfson Microelectronics plc6 *7 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>8 */9 10#include <linux/module.h>11#include <linux/moduleparam.h>12#include <linux/init.h>13#include <linux/delay.h>14#include <linux/pm.h>15#include <linux/i2c.h>16#include <linux/regmap.h>17#include <linux/spi/spi.h>18#include <linux/slab.h>19#include <sound/core.h>20#include <sound/pcm.h>21#include <sound/pcm_params.h>22#include <sound/soc.h>23#include <sound/initval.h>24#include <sound/tlv.h>25 26#include "wm8983.h"27 28static const struct reg_default wm8983_defaults[] = {29 { 0x01, 0x0000 }, /* R1 - Power management 1 */30 { 0x02, 0x0000 }, /* R2 - Power management 2 */31 { 0x03, 0x0000 }, /* R3 - Power management 3 */32 { 0x04, 0x0050 }, /* R4 - Audio Interface */33 { 0x05, 0x0000 }, /* R5 - Companding control */34 { 0x06, 0x0140 }, /* R6 - Clock Gen control */35 { 0x07, 0x0000 }, /* R7 - Additional control */36 { 0x08, 0x0000 }, /* R8 - GPIO Control */37 { 0x09, 0x0000 }, /* R9 - Jack Detect Control 1 */38 { 0x0A, 0x0000 }, /* R10 - DAC Control */39 { 0x0B, 0x00FF }, /* R11 - Left DAC digital Vol */40 { 0x0C, 0x00FF }, /* R12 - Right DAC digital vol */41 { 0x0D, 0x0000 }, /* R13 - Jack Detect Control 2 */42 { 0x0E, 0x0100 }, /* R14 - ADC Control */43 { 0x0F, 0x00FF }, /* R15 - Left ADC Digital Vol */44 { 0x10, 0x00FF }, /* R16 - Right ADC Digital Vol */45 { 0x12, 0x012C }, /* R18 - EQ1 - low shelf */46 { 0x13, 0x002C }, /* R19 - EQ2 - peak 1 */47 { 0x14, 0x002C }, /* R20 - EQ3 - peak 2 */48 { 0x15, 0x002C }, /* R21 - EQ4 - peak 3 */49 { 0x16, 0x002C }, /* R22 - EQ5 - high shelf */50 { 0x18, 0x0032 }, /* R24 - DAC Limiter 1 */51 { 0x19, 0x0000 }, /* R25 - DAC Limiter 2 */52 { 0x1B, 0x0000 }, /* R27 - Notch Filter 1 */53 { 0x1C, 0x0000 }, /* R28 - Notch Filter 2 */54 { 0x1D, 0x0000 }, /* R29 - Notch Filter 3 */55 { 0x1E, 0x0000 }, /* R30 - Notch Filter 4 */56 { 0x20, 0x0038 }, /* R32 - ALC control 1 */57 { 0x21, 0x000B }, /* R33 - ALC control 2 */58 { 0x22, 0x0032 }, /* R34 - ALC control 3 */59 { 0x23, 0x0000 }, /* R35 - Noise Gate */60 { 0x24, 0x0008 }, /* R36 - PLL N */61 { 0x25, 0x000C }, /* R37 - PLL K 1 */62 { 0x26, 0x0093 }, /* R38 - PLL K 2 */63 { 0x27, 0x00E9 }, /* R39 - PLL K 3 */64 { 0x29, 0x0000 }, /* R41 - 3D control */65 { 0x2A, 0x0000 }, /* R42 - OUT4 to ADC */66 { 0x2B, 0x0000 }, /* R43 - Beep control */67 { 0x2C, 0x0033 }, /* R44 - Input ctrl */68 { 0x2D, 0x0010 }, /* R45 - Left INP PGA gain ctrl */69 { 0x2E, 0x0010 }, /* R46 - Right INP PGA gain ctrl */70 { 0x2F, 0x0100 }, /* R47 - Left ADC BOOST ctrl */71 { 0x30, 0x0100 }, /* R48 - Right ADC BOOST ctrl */72 { 0x31, 0x0002 }, /* R49 - Output ctrl */73 { 0x32, 0x0001 }, /* R50 - Left mixer ctrl */74 { 0x33, 0x0001 }, /* R51 - Right mixer ctrl */75 { 0x34, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */76 { 0x35, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */77 { 0x36, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */78 { 0x37, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */79 { 0x38, 0x0001 }, /* R56 - OUT3 mixer ctrl */80 { 0x39, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */81 { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */82};83 84/* vol/gain update regs */85static const int vol_update_regs[] = {86 WM8983_LEFT_DAC_DIGITAL_VOL,87 WM8983_RIGHT_DAC_DIGITAL_VOL,88 WM8983_LEFT_ADC_DIGITAL_VOL,89 WM8983_RIGHT_ADC_DIGITAL_VOL,90 WM8983_LOUT1_HP_VOLUME_CTRL,91 WM8983_ROUT1_HP_VOLUME_CTRL,92 WM8983_LOUT2_SPK_VOLUME_CTRL,93 WM8983_ROUT2_SPK_VOLUME_CTRL,94 WM8983_LEFT_INP_PGA_GAIN_CTRL,95 WM8983_RIGHT_INP_PGA_GAIN_CTRL96};97 98struct wm8983_priv {99 struct regmap *regmap;100 u32 sysclk;101 u32 bclk;102};103 104static const struct {105 int div;106 int ratio;107} fs_ratios[] = {108 { 10, 128 },109 { 15, 192 },110 { 20, 256 },111 { 30, 384 },112 { 40, 512 },113 { 60, 768 },114 { 80, 1024 },115 { 120, 1536 }116};117 118static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 };119 120static const int bclk_divs[] = {121 1, 2, 4, 8, 16, 32122};123 124static int eqmode_get(struct snd_kcontrol *kcontrol,125 struct snd_ctl_elem_value *ucontrol);126static int eqmode_put(struct snd_kcontrol *kcontrol,127 struct snd_ctl_elem_value *ucontrol);128 129static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);130static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1);131static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);132static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0);133static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0);134static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0);135static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0);136static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0);137static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0);138static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);139static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);140static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0);141static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);142static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0);143 144static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" };145static SOC_ENUM_SINGLE_DECL(alc_sel, WM8983_ALC_CONTROL_1, 7, alc_sel_text);146 147static const char *alc_mode_text[] = { "ALC", "Limiter" };148static SOC_ENUM_SINGLE_DECL(alc_mode, WM8983_ALC_CONTROL_3, 8, alc_mode_text);149 150static const char *filter_mode_text[] = { "Audio", "Application" };151static SOC_ENUM_SINGLE_DECL(filter_mode, WM8983_ADC_CONTROL, 7,152 filter_mode_text);153 154static const char *eq_bw_text[] = { "Narrow", "Wide" };155static const char *eqmode_text[] = { "Capture", "Playback" };156static SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);157 158static const char *eq1_cutoff_text[] = {159 "80Hz", "105Hz", "135Hz", "175Hz"160};161static SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8983_EQ1_LOW_SHELF, 5,162 eq1_cutoff_text);163static const char *eq2_cutoff_text[] = {164 "230Hz", "300Hz", "385Hz", "500Hz"165};166static SOC_ENUM_SINGLE_DECL(eq2_bw, WM8983_EQ2_PEAK_1, 8, eq_bw_text);167static SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8983_EQ2_PEAK_1, 5, eq2_cutoff_text);168static const char *eq3_cutoff_text[] = {169 "650Hz", "850Hz", "1.1kHz", "1.4kHz"170};171static SOC_ENUM_SINGLE_DECL(eq3_bw, WM8983_EQ3_PEAK_2, 8, eq_bw_text);172static SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8983_EQ3_PEAK_2, 5, eq3_cutoff_text);173static const char *eq4_cutoff_text[] = {174 "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"175};176static SOC_ENUM_SINGLE_DECL(eq4_bw, WM8983_EQ4_PEAK_3, 8, eq_bw_text);177static SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8983_EQ4_PEAK_3, 5, eq4_cutoff_text);178static const char *eq5_cutoff_text[] = {179 "5.3kHz", "6.9kHz", "9kHz", "11.7kHz"180};181static SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5,182 eq5_cutoff_text);183 184static const char *depth_3d_text[] = {185 "Off",186 "6.67%",187 "13.3%",188 "20%",189 "26.7%",190 "33.3%",191 "40%",192 "46.6%",193 "53.3%",194 "60%",195 "66.7%",196 "73.3%",197 "80%",198 "86.7%",199 "93.3%",200 "100%"201};202static SOC_ENUM_SINGLE_DECL(depth_3d, WM8983_3D_CONTROL, 0,203 depth_3d_text);204 205static const struct snd_kcontrol_new wm8983_snd_controls[] = {206 SOC_SINGLE("Digital Loopback Switch", WM8983_COMPANDING_CONTROL,207 0, 1, 0),208 209 SOC_ENUM("ALC Capture Function", alc_sel),210 SOC_SINGLE_TLV("ALC Capture Max Volume", WM8983_ALC_CONTROL_1,211 3, 7, 0, alc_max_tlv),212 SOC_SINGLE_TLV("ALC Capture Min Volume", WM8983_ALC_CONTROL_1,213 0, 7, 0, alc_min_tlv),214 SOC_SINGLE_TLV("ALC Capture Target Volume", WM8983_ALC_CONTROL_2,215 0, 15, 0, alc_tar_tlv),216 SOC_SINGLE("ALC Capture Attack", WM8983_ALC_CONTROL_3, 0, 10, 0),217 SOC_SINGLE("ALC Capture Hold", WM8983_ALC_CONTROL_2, 4, 10, 0),218 SOC_SINGLE("ALC Capture Decay", WM8983_ALC_CONTROL_3, 4, 10, 0),219 SOC_ENUM("ALC Mode", alc_mode),220 SOC_SINGLE("ALC Capture NG Switch", WM8983_NOISE_GATE,221 3, 1, 0),222 SOC_SINGLE("ALC Capture NG Threshold", WM8983_NOISE_GATE,223 0, 7, 1),224 225 SOC_DOUBLE_R_TLV("Capture Volume", WM8983_LEFT_ADC_DIGITAL_VOL,226 WM8983_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv),227 SOC_DOUBLE_R("Capture PGA ZC Switch", WM8983_LEFT_INP_PGA_GAIN_CTRL,228 WM8983_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0),229 SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8983_LEFT_INP_PGA_GAIN_CTRL,230 WM8983_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv),231 232 SOC_DOUBLE_R_TLV("Capture PGA Boost Volume",233 WM8983_LEFT_ADC_BOOST_CTRL, WM8983_RIGHT_ADC_BOOST_CTRL,234 8, 1, 0, pga_boost_tlv),235 236 SOC_DOUBLE("ADC Inversion Switch", WM8983_ADC_CONTROL, 0, 1, 1, 0),237 SOC_SINGLE("ADC 128x Oversampling Switch", WM8983_ADC_CONTROL, 8, 1, 0),238 239 SOC_DOUBLE_R_TLV("Playback Volume", WM8983_LEFT_DAC_DIGITAL_VOL,240 WM8983_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv),241 242 SOC_SINGLE("DAC Playback Limiter Switch", WM8983_DAC_LIMITER_1, 8, 1, 0),243 SOC_SINGLE("DAC Playback Limiter Decay", WM8983_DAC_LIMITER_1, 4, 10, 0),244 SOC_SINGLE("DAC Playback Limiter Attack", WM8983_DAC_LIMITER_1, 0, 11, 0),245 SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8983_DAC_LIMITER_2,246 4, 7, 1, lim_thresh_tlv),247 SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8983_DAC_LIMITER_2,248 0, 12, 0, lim_boost_tlv),249 SOC_DOUBLE("DAC Inversion Switch", WM8983_DAC_CONTROL, 0, 1, 1, 0),250 SOC_SINGLE("DAC Auto Mute Switch", WM8983_DAC_CONTROL, 2, 1, 0),251 SOC_SINGLE("DAC 128x Oversampling Switch", WM8983_DAC_CONTROL, 3, 1, 0),252 253 SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8983_LOUT1_HP_VOLUME_CTRL,254 WM8983_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv),255 SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8983_LOUT1_HP_VOLUME_CTRL,256 WM8983_ROUT1_HP_VOLUME_CTRL, 7, 1, 0),257 SOC_DOUBLE_R("Headphone Switch", WM8983_LOUT1_HP_VOLUME_CTRL,258 WM8983_ROUT1_HP_VOLUME_CTRL, 6, 1, 1),259 260 SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8983_LOUT2_SPK_VOLUME_CTRL,261 WM8983_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv),262 SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8983_LOUT2_SPK_VOLUME_CTRL,263 WM8983_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0),264 SOC_DOUBLE_R("Speaker Switch", WM8983_LOUT2_SPK_VOLUME_CTRL,265 WM8983_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1),266 267 SOC_SINGLE("OUT3 Switch", WM8983_OUT3_MIXER_CTRL,268 6, 1, 1),269 270 SOC_SINGLE("OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,271 6, 1, 1),272 273 SOC_SINGLE("High Pass Filter Switch", WM8983_ADC_CONTROL, 8, 1, 0),274 SOC_ENUM("High Pass Filter Mode", filter_mode),275 SOC_SINGLE("High Pass Filter Cutoff", WM8983_ADC_CONTROL, 4, 7, 0),276 277 SOC_DOUBLE_R_TLV("Aux Bypass Volume",278 WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 6, 7, 0,279 aux_tlv),280 281 SOC_DOUBLE_R_TLV("Input PGA Bypass Volume",282 WM8983_LEFT_MIXER_CTRL, WM8983_RIGHT_MIXER_CTRL, 2, 7, 0,283 bypass_tlv),284 285 SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put),286 SOC_ENUM("EQ1 Cutoff", eq1_cutoff),287 SOC_SINGLE_TLV("EQ1 Volume", WM8983_EQ1_LOW_SHELF, 0, 24, 1, eq_tlv),288 SOC_ENUM("EQ2 Bandwidth", eq2_bw),289 SOC_ENUM("EQ2 Cutoff", eq2_cutoff),290 SOC_SINGLE_TLV("EQ2 Volume", WM8983_EQ2_PEAK_1, 0, 24, 1, eq_tlv),291 SOC_ENUM("EQ3 Bandwidth", eq3_bw),292 SOC_ENUM("EQ3 Cutoff", eq3_cutoff),293 SOC_SINGLE_TLV("EQ3 Volume", WM8983_EQ3_PEAK_2, 0, 24, 1, eq_tlv),294 SOC_ENUM("EQ4 Bandwidth", eq4_bw),295 SOC_ENUM("EQ4 Cutoff", eq4_cutoff),296 SOC_SINGLE_TLV("EQ4 Volume", WM8983_EQ4_PEAK_3, 0, 24, 1, eq_tlv),297 SOC_ENUM("EQ5 Cutoff", eq5_cutoff),298 SOC_SINGLE_TLV("EQ5 Volume", WM8983_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),299 300 SOC_ENUM("3D Depth", depth_3d),301};302 303static const struct snd_kcontrol_new left_out_mixer[] = {304 SOC_DAPM_SINGLE("Line Switch", WM8983_LEFT_MIXER_CTRL, 1, 1, 0),305 SOC_DAPM_SINGLE("Aux Switch", WM8983_LEFT_MIXER_CTRL, 5, 1, 0),306 SOC_DAPM_SINGLE("PCM Switch", WM8983_LEFT_MIXER_CTRL, 0, 1, 0),307};308 309static const struct snd_kcontrol_new right_out_mixer[] = {310 SOC_DAPM_SINGLE("Line Switch", WM8983_RIGHT_MIXER_CTRL, 1, 1, 0),311 SOC_DAPM_SINGLE("Aux Switch", WM8983_RIGHT_MIXER_CTRL, 5, 1, 0),312 SOC_DAPM_SINGLE("PCM Switch", WM8983_RIGHT_MIXER_CTRL, 0, 1, 0),313};314 315static const struct snd_kcontrol_new left_input_mixer[] = {316 SOC_DAPM_SINGLE("L2 Switch", WM8983_INPUT_CTRL, 2, 1, 0),317 SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 1, 1, 0),318 SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 0, 1, 0),319};320 321static const struct snd_kcontrol_new right_input_mixer[] = {322 SOC_DAPM_SINGLE("R2 Switch", WM8983_INPUT_CTRL, 6, 1, 0),323 SOC_DAPM_SINGLE("MicN Switch", WM8983_INPUT_CTRL, 5, 1, 0),324 SOC_DAPM_SINGLE("MicP Switch", WM8983_INPUT_CTRL, 4, 1, 0),325};326 327static const struct snd_kcontrol_new left_boost_mixer[] = {328 SOC_DAPM_SINGLE_TLV("L2 Volume", WM8983_LEFT_ADC_BOOST_CTRL,329 4, 7, 0, boost_tlv),330 SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8983_LEFT_ADC_BOOST_CTRL,331 0, 7, 0, boost_tlv)332};333 334static const struct snd_kcontrol_new out3_mixer[] = {335 SOC_DAPM_SINGLE("LMIX2OUT3 Switch", WM8983_OUT3_MIXER_CTRL,336 1, 1, 0),337 SOC_DAPM_SINGLE("LDAC2OUT3 Switch", WM8983_OUT3_MIXER_CTRL,338 0, 1, 0),339};340 341static const struct snd_kcontrol_new out4_mixer[] = {342 SOC_DAPM_SINGLE("LMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,343 4, 1, 0),344 SOC_DAPM_SINGLE("RMIX2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,345 1, 1, 0),346 SOC_DAPM_SINGLE("LDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,347 3, 1, 0),348 SOC_DAPM_SINGLE("RDAC2OUT4 Switch", WM8983_OUT4_MONO_MIX_CTRL,349 0, 1, 0),350};351 352static const struct snd_kcontrol_new right_boost_mixer[] = {353 SOC_DAPM_SINGLE_TLV("R2 Volume", WM8983_RIGHT_ADC_BOOST_CTRL,354 4, 7, 0, boost_tlv),355 SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8983_RIGHT_ADC_BOOST_CTRL,356 0, 7, 0, boost_tlv)357};358 359static const struct snd_soc_dapm_widget wm8983_dapm_widgets[] = {360 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8983_POWER_MANAGEMENT_3,361 0, 0),362 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8983_POWER_MANAGEMENT_3,363 1, 0),364 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8983_POWER_MANAGEMENT_2,365 0, 0),366 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8983_POWER_MANAGEMENT_2,367 1, 0),368 369 SND_SOC_DAPM_MIXER("Left Output Mixer", WM8983_POWER_MANAGEMENT_3,370 2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)),371 SND_SOC_DAPM_MIXER("Right Output Mixer", WM8983_POWER_MANAGEMENT_3,372 3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)),373 374 SND_SOC_DAPM_MIXER("Left Input Mixer", WM8983_POWER_MANAGEMENT_2,375 2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)),376 SND_SOC_DAPM_MIXER("Right Input Mixer", WM8983_POWER_MANAGEMENT_2,377 3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)),378 379 SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8983_POWER_MANAGEMENT_2,380 4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)),381 SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8983_POWER_MANAGEMENT_2,382 5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)),383 384 SND_SOC_DAPM_MIXER("OUT3 Mixer", WM8983_POWER_MANAGEMENT_1,385 6, 0, out3_mixer, ARRAY_SIZE(out3_mixer)),386 387 SND_SOC_DAPM_MIXER("OUT4 Mixer", WM8983_POWER_MANAGEMENT_1,388 7, 0, out4_mixer, ARRAY_SIZE(out4_mixer)),389 390 SND_SOC_DAPM_PGA("Left Capture PGA", WM8983_LEFT_INP_PGA_GAIN_CTRL,391 6, 1, NULL, 0),392 SND_SOC_DAPM_PGA("Right Capture PGA", WM8983_RIGHT_INP_PGA_GAIN_CTRL,393 6, 1, NULL, 0),394 395 SND_SOC_DAPM_PGA("Left Headphone Out", WM8983_POWER_MANAGEMENT_2,396 7, 0, NULL, 0),397 SND_SOC_DAPM_PGA("Right Headphone Out", WM8983_POWER_MANAGEMENT_2,398 8, 0, NULL, 0),399 400 SND_SOC_DAPM_PGA("Left Speaker Out", WM8983_POWER_MANAGEMENT_3,401 5, 0, NULL, 0),402 SND_SOC_DAPM_PGA("Right Speaker Out", WM8983_POWER_MANAGEMENT_3,403 6, 0, NULL, 0),404 405 SND_SOC_DAPM_PGA("OUT3 Out", WM8983_POWER_MANAGEMENT_3,406 7, 0, NULL, 0),407 408 SND_SOC_DAPM_PGA("OUT4 Out", WM8983_POWER_MANAGEMENT_3,409 8, 0, NULL, 0),410 411 SND_SOC_DAPM_SUPPLY("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0,412 NULL, 0),413 414 SND_SOC_DAPM_INPUT("LIN"),415 SND_SOC_DAPM_INPUT("LIP"),416 SND_SOC_DAPM_INPUT("RIN"),417 SND_SOC_DAPM_INPUT("RIP"),418 SND_SOC_DAPM_INPUT("AUXL"),419 SND_SOC_DAPM_INPUT("AUXR"),420 SND_SOC_DAPM_INPUT("L2"),421 SND_SOC_DAPM_INPUT("R2"),422 SND_SOC_DAPM_OUTPUT("HPL"),423 SND_SOC_DAPM_OUTPUT("HPR"),424 SND_SOC_DAPM_OUTPUT("SPKL"),425 SND_SOC_DAPM_OUTPUT("SPKR"),426 SND_SOC_DAPM_OUTPUT("OUT3"),427 SND_SOC_DAPM_OUTPUT("OUT4")428};429 430static const struct snd_soc_dapm_route wm8983_audio_map[] = {431 { "OUT3 Mixer", "LMIX2OUT3 Switch", "Left Output Mixer" },432 { "OUT3 Mixer", "LDAC2OUT3 Switch", "Left DAC" },433 434 { "OUT3 Out", NULL, "OUT3 Mixer" },435 { "OUT3", NULL, "OUT3 Out" },436 437 { "OUT4 Mixer", "LMIX2OUT4 Switch", "Left Output Mixer" },438 { "OUT4 Mixer", "RMIX2OUT4 Switch", "Right Output Mixer" },439 { "OUT4 Mixer", "LDAC2OUT4 Switch", "Left DAC" },440 { "OUT4 Mixer", "RDAC2OUT4 Switch", "Right DAC" },441 442 { "OUT4 Out", NULL, "OUT4 Mixer" },443 { "OUT4", NULL, "OUT4 Out" },444 445 { "Right Output Mixer", "PCM Switch", "Right DAC" },446 { "Right Output Mixer", "Aux Switch", "AUXR" },447 { "Right Output Mixer", "Line Switch", "Right Boost Mixer" },448 449 { "Left Output Mixer", "PCM Switch", "Left DAC" },450 { "Left Output Mixer", "Aux Switch", "AUXL" },451 { "Left Output Mixer", "Line Switch", "Left Boost Mixer" },452 453 { "Right Headphone Out", NULL, "Right Output Mixer" },454 { "HPR", NULL, "Right Headphone Out" },455 456 { "Left Headphone Out", NULL, "Left Output Mixer" },457 { "HPL", NULL, "Left Headphone Out" },458 459 { "Right Speaker Out", NULL, "Right Output Mixer" },460 { "SPKR", NULL, "Right Speaker Out" },461 462 { "Left Speaker Out", NULL, "Left Output Mixer" },463 { "SPKL", NULL, "Left Speaker Out" },464 465 { "Right ADC", NULL, "Right Boost Mixer" },466 467 { "Right Boost Mixer", "AUXR Volume", "AUXR" },468 { "Right Boost Mixer", NULL, "Right Capture PGA" },469 { "Right Boost Mixer", "R2 Volume", "R2" },470 471 { "Left ADC", NULL, "Left Boost Mixer" },472 473 { "Left Boost Mixer", "AUXL Volume", "AUXL" },474 { "Left Boost Mixer", NULL, "Left Capture PGA" },475 { "Left Boost Mixer", "L2 Volume", "L2" },476 477 { "Right Capture PGA", NULL, "Right Input Mixer" },478 { "Left Capture PGA", NULL, "Left Input Mixer" },479 480 { "Right Input Mixer", "R2 Switch", "R2" },481 { "Right Input Mixer", "MicN Switch", "RIN" },482 { "Right Input Mixer", "MicP Switch", "RIP" },483 484 { "Left Input Mixer", "L2 Switch", "L2" },485 { "Left Input Mixer", "MicN Switch", "LIN" },486 { "Left Input Mixer", "MicP Switch", "LIP" },487};488 489static int eqmode_get(struct snd_kcontrol *kcontrol,490 struct snd_ctl_elem_value *ucontrol)491{492 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);493 unsigned int reg;494 495 reg = snd_soc_component_read(component, WM8983_EQ1_LOW_SHELF);496 if (reg & WM8983_EQ3DMODE)497 ucontrol->value.enumerated.item[0] = 1;498 else499 ucontrol->value.enumerated.item[0] = 0;500 501 return 0;502}503 504static int eqmode_put(struct snd_kcontrol *kcontrol,505 struct snd_ctl_elem_value *ucontrol)506{507 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);508 unsigned int regpwr2, regpwr3;509 unsigned int reg_eq;510 511 if (ucontrol->value.enumerated.item[0] != 0512 && ucontrol->value.enumerated.item[0] != 1)513 return -EINVAL;514 515 reg_eq = snd_soc_component_read(component, WM8983_EQ1_LOW_SHELF);516 switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) {517 case 0:518 if (!ucontrol->value.enumerated.item[0])519 return 0;520 break;521 case 1:522 if (ucontrol->value.enumerated.item[0])523 return 0;524 break;525 }526 527 regpwr2 = snd_soc_component_read(component, WM8983_POWER_MANAGEMENT_2);528 regpwr3 = snd_soc_component_read(component, WM8983_POWER_MANAGEMENT_3);529 /* disable the DACs and ADCs */530 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_2,531 WM8983_ADCENR_MASK | WM8983_ADCENL_MASK, 0);532 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_3,533 WM8983_DACENR_MASK | WM8983_DACENL_MASK, 0);534 /* set the desired eqmode */535 snd_soc_component_update_bits(component, WM8983_EQ1_LOW_SHELF,536 WM8983_EQ3DMODE_MASK,537 ucontrol->value.enumerated.item[0]538 << WM8983_EQ3DMODE_SHIFT);539 /* restore DAC/ADC configuration */540 snd_soc_component_write(component, WM8983_POWER_MANAGEMENT_2, regpwr2);541 snd_soc_component_write(component, WM8983_POWER_MANAGEMENT_3, regpwr3);542 return 0;543}544 545static bool wm8983_writeable(struct device *dev, unsigned int reg)546{547 switch (reg) {548 case WM8983_SOFTWARE_RESET ... WM8983_RIGHT_ADC_DIGITAL_VOL:549 case WM8983_EQ1_LOW_SHELF ... WM8983_DAC_LIMITER_2:550 case WM8983_NOTCH_FILTER_1 ... WM8983_NOTCH_FILTER_4:551 case WM8983_ALC_CONTROL_1 ... WM8983_PLL_K_3:552 case WM8983_3D_CONTROL ... WM8983_OUT4_MONO_MIX_CTRL:553 case WM8983_BIAS_CTRL:554 return true;555 default:556 return false;557 }558}559 560static int wm8983_dac_mute(struct snd_soc_dai *dai, int mute, int direction)561{562 struct snd_soc_component *component = dai->component;563 564 return snd_soc_component_update_bits(component, WM8983_DAC_CONTROL,565 WM8983_SOFTMUTE_MASK,566 !!mute << WM8983_SOFTMUTE_SHIFT);567}568 569static int wm8983_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)570{571 struct snd_soc_component *component = dai->component;572 u16 format, master, bcp, lrp;573 574 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {575 case SND_SOC_DAIFMT_I2S:576 format = 0x2;577 break;578 case SND_SOC_DAIFMT_RIGHT_J:579 format = 0x0;580 break;581 case SND_SOC_DAIFMT_LEFT_J:582 format = 0x1;583 break;584 case SND_SOC_DAIFMT_DSP_A:585 case SND_SOC_DAIFMT_DSP_B:586 format = 0x3;587 break;588 default:589 dev_err(dai->dev, "Unknown dai format\n");590 return -EINVAL;591 }592 593 snd_soc_component_update_bits(component, WM8983_AUDIO_INTERFACE,594 WM8983_FMT_MASK, format << WM8983_FMT_SHIFT);595 596 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {597 case SND_SOC_DAIFMT_CBM_CFM:598 master = 1;599 break;600 case SND_SOC_DAIFMT_CBS_CFS:601 master = 0;602 break;603 default:604 dev_err(dai->dev, "Unknown master/slave configuration\n");605 return -EINVAL;606 }607 608 snd_soc_component_update_bits(component, WM8983_CLOCK_GEN_CONTROL,609 WM8983_MS_MASK, master << WM8983_MS_SHIFT);610 611 /* FIXME: We don't currently support DSP A/B modes */612 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {613 case SND_SOC_DAIFMT_DSP_A:614 case SND_SOC_DAIFMT_DSP_B:615 dev_err(dai->dev, "DSP A/B modes are not supported\n");616 return -EINVAL;617 default:618 break;619 }620 621 bcp = lrp = 0;622 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {623 case SND_SOC_DAIFMT_NB_NF:624 break;625 case SND_SOC_DAIFMT_IB_IF:626 bcp = lrp = 1;627 break;628 case SND_SOC_DAIFMT_IB_NF:629 bcp = 1;630 break;631 case SND_SOC_DAIFMT_NB_IF:632 lrp = 1;633 break;634 default:635 dev_err(dai->dev, "Unknown polarity configuration\n");636 return -EINVAL;637 }638 639 snd_soc_component_update_bits(component, WM8983_AUDIO_INTERFACE,640 WM8983_LRCP_MASK, lrp << WM8983_LRCP_SHIFT);641 snd_soc_component_update_bits(component, WM8983_AUDIO_INTERFACE,642 WM8983_BCP_MASK, bcp << WM8983_BCP_SHIFT);643 return 0;644}645 646static int wm8983_hw_params(struct snd_pcm_substream *substream,647 struct snd_pcm_hw_params *params,648 struct snd_soc_dai *dai)649{650 int i;651 struct snd_soc_component *component = dai->component;652 struct wm8983_priv *wm8983 = snd_soc_component_get_drvdata(component);653 u16 blen, srate_idx;654 u32 tmp;655 int srate_best;656 int ret;657 658 ret = snd_soc_params_to_bclk(params);659 if (ret < 0) {660 dev_err(component->dev, "Failed to convert params to bclk: %d\n", ret);661 return ret;662 }663 664 wm8983->bclk = ret;665 666 switch (params_width(params)) {667 case 16:668 blen = 0x0;669 break;670 case 20:671 blen = 0x1;672 break;673 case 24:674 blen = 0x2;675 break;676 case 32:677 blen = 0x3;678 break;679 default:680 dev_err(dai->dev, "Unsupported word length %u\n",681 params_width(params));682 return -EINVAL;683 }684 685 snd_soc_component_update_bits(component, WM8983_AUDIO_INTERFACE,686 WM8983_WL_MASK, blen << WM8983_WL_SHIFT);687 688 /*689 * match to the nearest possible sample rate and rely690 * on the array index to configure the SR register691 */692 srate_idx = 0;693 srate_best = abs(srates[0] - params_rate(params));694 for (i = 1; i < ARRAY_SIZE(srates); ++i) {695 if (abs(srates[i] - params_rate(params)) >= srate_best)696 continue;697 srate_idx = i;698 srate_best = abs(srates[i] - params_rate(params));699 }700 701 dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]);702 snd_soc_component_update_bits(component, WM8983_ADDITIONAL_CONTROL,703 WM8983_SR_MASK, srate_idx << WM8983_SR_SHIFT);704 705 dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8983->bclk);706 dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8983->sysclk);707 708 for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) {709 if (wm8983->sysclk / params_rate(params)710 == fs_ratios[i].ratio)711 break;712 }713 714 if (i == ARRAY_SIZE(fs_ratios)) {715 dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n",716 wm8983->sysclk, params_rate(params));717 return -EINVAL;718 }719 720 dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio);721 snd_soc_component_update_bits(component, WM8983_CLOCK_GEN_CONTROL,722 WM8983_MCLKDIV_MASK, i << WM8983_MCLKDIV_SHIFT);723 724 /* select the appropriate bclk divider */725 tmp = (wm8983->sysclk / fs_ratios[i].div) * 10;726 for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) {727 if (wm8983->bclk == tmp / bclk_divs[i])728 break;729 }730 731 if (i == ARRAY_SIZE(bclk_divs)) {732 dev_err(dai->dev, "No matching BCLK divider found\n");733 return -EINVAL;734 }735 736 dev_dbg(dai->dev, "BCLK div = %d\n", i);737 snd_soc_component_update_bits(component, WM8983_CLOCK_GEN_CONTROL,738 WM8983_BCLKDIV_MASK, i << WM8983_BCLKDIV_SHIFT);739 740 return 0;741}742 743struct pll_div {744 u32 div2:1;745 u32 n:4;746 u32 k:24;747};748 749#define FIXED_PLL_SIZE ((1ULL << 24) * 10)750static int pll_factors(struct pll_div *pll_div, unsigned int target,751 unsigned int source)752{753 u64 Kpart;754 unsigned long int K, Ndiv, Nmod;755 756 pll_div->div2 = 0;757 Ndiv = target / source;758 if (Ndiv < 6) {759 source >>= 1;760 pll_div->div2 = 1;761 Ndiv = target / source;762 }763 764 if (Ndiv < 6 || Ndiv > 12) {765 printk(KERN_ERR "%s: WM8983 N value is not within"766 " the recommended range: %lu\n", __func__, Ndiv);767 return -EINVAL;768 }769 pll_div->n = Ndiv;770 771 Nmod = target % source;772 Kpart = FIXED_PLL_SIZE * (u64)Nmod;773 774 do_div(Kpart, source);775 776 K = Kpart & 0xffffffff;777 if ((K % 10) >= 5)778 K += 5;779 K /= 10;780 pll_div->k = K;781 return 0;782}783 784static int wm8983_set_pll(struct snd_soc_dai *dai, int pll_id,785 int source, unsigned int freq_in,786 unsigned int freq_out)787{788 int ret;789 struct snd_soc_component *component;790 struct pll_div pll_div;791 792 component = dai->component;793 if (!freq_in || !freq_out) {794 /* disable the PLL */795 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_1,796 WM8983_PLLEN_MASK, 0);797 return 0;798 } else {799 ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in);800 if (ret)801 return ret;802 803 /* disable the PLL before re-programming it */804 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_1,805 WM8983_PLLEN_MASK, 0);806 807 /* set PLLN and PRESCALE */808 snd_soc_component_write(component, WM8983_PLL_N,809 (pll_div.div2 << WM8983_PLL_PRESCALE_SHIFT)810 | pll_div.n);811 /* set PLLK */812 snd_soc_component_write(component, WM8983_PLL_K_3, pll_div.k & 0x1ff);813 snd_soc_component_write(component, WM8983_PLL_K_2, (pll_div.k >> 9) & 0x1ff);814 snd_soc_component_write(component, WM8983_PLL_K_1, (pll_div.k >> 18));815 /* enable the PLL */816 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_1,817 WM8983_PLLEN_MASK, WM8983_PLLEN);818 }819 820 return 0;821}822 823static int wm8983_set_sysclk(struct snd_soc_dai *dai,824 int clk_id, unsigned int freq, int dir)825{826 struct snd_soc_component *component = dai->component;827 struct wm8983_priv *wm8983 = snd_soc_component_get_drvdata(component);828 829 switch (clk_id) {830 case WM8983_CLKSRC_MCLK:831 snd_soc_component_update_bits(component, WM8983_CLOCK_GEN_CONTROL,832 WM8983_CLKSEL_MASK, 0);833 break;834 case WM8983_CLKSRC_PLL:835 snd_soc_component_update_bits(component, WM8983_CLOCK_GEN_CONTROL,836 WM8983_CLKSEL_MASK, WM8983_CLKSEL);837 break;838 default:839 dev_err(dai->dev, "Unknown clock source: %d\n", clk_id);840 return -EINVAL;841 }842 843 wm8983->sysclk = freq;844 return 0;845}846 847static int wm8983_set_bias_level(struct snd_soc_component *component,848 enum snd_soc_bias_level level)849{850 struct wm8983_priv *wm8983 = snd_soc_component_get_drvdata(component);851 int ret;852 853 switch (level) {854 case SND_SOC_BIAS_ON:855 case SND_SOC_BIAS_PREPARE:856 /* VMID at 100k */857 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_1,858 WM8983_VMIDSEL_MASK,859 1 << WM8983_VMIDSEL_SHIFT);860 break;861 case SND_SOC_BIAS_STANDBY:862 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {863 ret = regcache_sync(wm8983->regmap);864 if (ret < 0) {865 dev_err(component->dev, "Failed to sync cache: %d\n", ret);866 return ret;867 }868 /* enable anti-pop features */869 snd_soc_component_update_bits(component, WM8983_OUT4_TO_ADC,870 WM8983_POBCTRL_MASK | WM8983_DELEN_MASK,871 WM8983_POBCTRL | WM8983_DELEN);872 /* enable thermal shutdown */873 snd_soc_component_update_bits(component, WM8983_OUTPUT_CTRL,874 WM8983_TSDEN_MASK, WM8983_TSDEN);875 /* enable BIASEN */876 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_1,877 WM8983_BIASEN_MASK, WM8983_BIASEN);878 /* VMID at 100k */879 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_1,880 WM8983_VMIDSEL_MASK,881 1 << WM8983_VMIDSEL_SHIFT);882 msleep(250);883 /* disable anti-pop features */884 snd_soc_component_update_bits(component, WM8983_OUT4_TO_ADC,885 WM8983_POBCTRL_MASK |886 WM8983_DELEN_MASK, 0);887 }888 889 /* VMID at 500k */890 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_1,891 WM8983_VMIDSEL_MASK,892 2 << WM8983_VMIDSEL_SHIFT);893 break;894 case SND_SOC_BIAS_OFF:895 /* disable thermal shutdown */896 snd_soc_component_update_bits(component, WM8983_OUTPUT_CTRL,897 WM8983_TSDEN_MASK, 0);898 /* disable VMIDSEL and BIASEN */899 snd_soc_component_update_bits(component, WM8983_POWER_MANAGEMENT_1,900 WM8983_VMIDSEL_MASK | WM8983_BIASEN_MASK,901 0);902 /* wait for VMID to discharge */903 msleep(100);904 snd_soc_component_write(component, WM8983_POWER_MANAGEMENT_1, 0);905 snd_soc_component_write(component, WM8983_POWER_MANAGEMENT_2, 0);906 snd_soc_component_write(component, WM8983_POWER_MANAGEMENT_3, 0);907 break;908 }909 910 return 0;911}912 913static int wm8983_probe(struct snd_soc_component *component)914{915 int ret;916 int i;917 918 ret = snd_soc_component_write(component, WM8983_SOFTWARE_RESET, 0);919 if (ret < 0) {920 dev_err(component->dev, "Failed to issue reset: %d\n", ret);921 return ret;922 }923 924 /* set the vol/gain update bits */925 for (i = 0; i < ARRAY_SIZE(vol_update_regs); ++i)926 snd_soc_component_update_bits(component, vol_update_regs[i],927 0x100, 0x100);928 929 /* mute all outputs and set PGAs to minimum gain */930 for (i = WM8983_LOUT1_HP_VOLUME_CTRL;931 i <= WM8983_OUT4_MONO_MIX_CTRL; ++i)932 snd_soc_component_update_bits(component, i, 0x40, 0x40);933 934 /* enable soft mute */935 snd_soc_component_update_bits(component, WM8983_DAC_CONTROL,936 WM8983_SOFTMUTE_MASK,937 WM8983_SOFTMUTE);938 939 /* enable BIASCUT */940 snd_soc_component_update_bits(component, WM8983_BIAS_CTRL,941 WM8983_BIASCUT, WM8983_BIASCUT);942 return 0;943}944 945static const struct snd_soc_dai_ops wm8983_dai_ops = {946 .mute_stream = wm8983_dac_mute,947 .hw_params = wm8983_hw_params,948 .set_fmt = wm8983_set_fmt,949 .set_sysclk = wm8983_set_sysclk,950 .set_pll = wm8983_set_pll,951 .no_capture_mute = 1,952};953 954#define WM8983_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \955 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)956 957static struct snd_soc_dai_driver wm8983_dai = {958 .name = "wm8983-hifi",959 .playback = {960 .stream_name = "Playback",961 .channels_min = 2,962 .channels_max = 2,963 .rates = SNDRV_PCM_RATE_8000_48000,964 .formats = WM8983_FORMATS,965 },966 .capture = {967 .stream_name = "Capture",968 .channels_min = 2,969 .channels_max = 2,970 .rates = SNDRV_PCM_RATE_8000_48000,971 .formats = WM8983_FORMATS,972 },973 .ops = &wm8983_dai_ops,974 .symmetric_rate = 1975};976 977static const struct snd_soc_component_driver soc_component_dev_wm8983 = {978 .probe = wm8983_probe,979 .set_bias_level = wm8983_set_bias_level,980 .controls = wm8983_snd_controls,981 .num_controls = ARRAY_SIZE(wm8983_snd_controls),982 .dapm_widgets = wm8983_dapm_widgets,983 .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets),984 .dapm_routes = wm8983_audio_map,985 .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map),986 .suspend_bias_off = 1,987 .idle_bias_on = 1,988 .use_pmdown_time = 1,989 .endianness = 1,990};991 992static const struct regmap_config wm8983_regmap = {993 .reg_bits = 7,994 .val_bits = 9,995 996 .reg_defaults = wm8983_defaults,997 .num_reg_defaults = ARRAY_SIZE(wm8983_defaults),998 .cache_type = REGCACHE_MAPLE,999 .max_register = WM8983_MAX_REGISTER,1000 1001 .writeable_reg = wm8983_writeable,1002};1003 1004#if defined(CONFIG_SPI_MASTER)1005static int wm8983_spi_probe(struct spi_device *spi)1006{1007 struct wm8983_priv *wm8983;1008 int ret;1009 1010 wm8983 = devm_kzalloc(&spi->dev, sizeof *wm8983, GFP_KERNEL);1011 if (!wm8983)1012 return -ENOMEM;1013 1014 wm8983->regmap = devm_regmap_init_spi(spi, &wm8983_regmap);1015 if (IS_ERR(wm8983->regmap)) {1016 ret = PTR_ERR(wm8983->regmap);1017 dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);1018 return ret;1019 }1020 1021 spi_set_drvdata(spi, wm8983);1022 1023 ret = devm_snd_soc_register_component(&spi->dev,1024 &soc_component_dev_wm8983, &wm8983_dai, 1);1025 return ret;1026}1027 1028static struct spi_driver wm8983_spi_driver = {1029 .driver = {1030 .name = "wm8983",1031 },1032 .probe = wm8983_spi_probe,1033};1034#endif1035 1036#if IS_ENABLED(CONFIG_I2C)1037static int wm8983_i2c_probe(struct i2c_client *i2c)1038{1039 struct wm8983_priv *wm8983;1040 int ret;1041 1042 wm8983 = devm_kzalloc(&i2c->dev, sizeof *wm8983, GFP_KERNEL);1043 if (!wm8983)1044 return -ENOMEM;1045 1046 wm8983->regmap = devm_regmap_init_i2c(i2c, &wm8983_regmap);1047 if (IS_ERR(wm8983->regmap)) {1048 ret = PTR_ERR(wm8983->regmap);1049 dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);1050 return ret;1051 }1052 1053 i2c_set_clientdata(i2c, wm8983);1054 1055 ret = devm_snd_soc_register_component(&i2c->dev,1056 &soc_component_dev_wm8983, &wm8983_dai, 1);1057 1058 return ret;1059}1060 1061static const struct i2c_device_id wm8983_i2c_id[] = {1062 { "wm8983" },1063 { }1064};1065MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id);1066 1067static struct i2c_driver wm8983_i2c_driver = {1068 .driver = {1069 .name = "wm8983",1070 },1071 .probe = wm8983_i2c_probe,1072 .id_table = wm8983_i2c_id1073};1074#endif1075 1076static int __init wm8983_modinit(void)1077{1078 int ret = 0;1079 1080#if IS_ENABLED(CONFIG_I2C)1081 ret = i2c_add_driver(&wm8983_i2c_driver);1082 if (ret) {1083 printk(KERN_ERR "Failed to register wm8983 I2C driver: %d\n",1084 ret);1085 }1086#endif1087#if defined(CONFIG_SPI_MASTER)1088 ret = spi_register_driver(&wm8983_spi_driver);1089 if (ret != 0) {1090 printk(KERN_ERR "Failed to register wm8983 SPI driver: %d\n",1091 ret);1092 }1093#endif1094 return ret;1095}1096module_init(wm8983_modinit);1097 1098static void __exit wm8983_exit(void)1099{1100#if IS_ENABLED(CONFIG_I2C)1101 i2c_del_driver(&wm8983_i2c_driver);1102#endif1103#if defined(CONFIG_SPI_MASTER)1104 spi_unregister_driver(&wm8983_spi_driver);1105#endif1106}1107module_exit(wm8983_exit);1108 1109MODULE_DESCRIPTION("ASoC WM8983 driver");1110MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");1111MODULE_LICENSE("GPL");1112