949 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * wm8988.c -- WM8988 ALSA SoC audio driver4 *5 * Copyright 2009 Wolfson Microelectronics plc6 * Copyright 2005 Openedhand Ltd.7 *8 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>9 */10 11#include <linux/module.h>12#include <linux/moduleparam.h>13#include <linux/init.h>14#include <linux/delay.h>15#include <linux/pm.h>16#include <linux/i2c.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/tlv.h>23#include <sound/soc.h>24#include <sound/initval.h>25 26#include "wm8988.h"27 28/*29 * wm8988 register cache30 * We can't read the WM8988 register space when we31 * are using 2 wire for device control, so we cache them instead.32 */33static const struct reg_default wm8988_reg_defaults[] = {34 { 0, 0x0097 },35 { 1, 0x0097 },36 { 2, 0x0079 },37 { 3, 0x0079 },38 { 5, 0x0008 },39 { 7, 0x000a },40 { 8, 0x0000 },41 { 10, 0x00ff },42 { 11, 0x00ff },43 { 12, 0x000f },44 { 13, 0x000f },45 { 16, 0x0000 },46 { 17, 0x007b },47 { 18, 0x0000 },48 { 19, 0x0032 },49 { 20, 0x0000 },50 { 21, 0x00c3 },51 { 22, 0x00c3 },52 { 23, 0x00c0 },53 { 24, 0x0000 },54 { 25, 0x0000 },55 { 26, 0x0000 },56 { 27, 0x0000 },57 { 31, 0x0000 },58 { 32, 0x0000 },59 { 33, 0x0000 },60 { 34, 0x0050 },61 { 35, 0x0050 },62 { 36, 0x0050 },63 { 37, 0x0050 },64 { 40, 0x0079 },65 { 41, 0x0079 },66 { 42, 0x0079 },67};68 69static bool wm8988_writeable(struct device *dev, unsigned int reg)70{71 switch (reg) {72 case WM8988_LINVOL:73 case WM8988_RINVOL:74 case WM8988_LOUT1V:75 case WM8988_ROUT1V:76 case WM8988_ADCDAC:77 case WM8988_IFACE:78 case WM8988_SRATE:79 case WM8988_LDAC:80 case WM8988_RDAC:81 case WM8988_BASS:82 case WM8988_TREBLE:83 case WM8988_RESET:84 case WM8988_3D:85 case WM8988_ALC1:86 case WM8988_ALC2:87 case WM8988_ALC3:88 case WM8988_NGATE:89 case WM8988_LADC:90 case WM8988_RADC:91 case WM8988_ADCTL1:92 case WM8988_ADCTL2:93 case WM8988_PWR1:94 case WM8988_PWR2:95 case WM8988_ADCTL3:96 case WM8988_ADCIN:97 case WM8988_LADCIN:98 case WM8988_RADCIN:99 case WM8988_LOUTM1:100 case WM8988_LOUTM2:101 case WM8988_ROUTM1:102 case WM8988_ROUTM2:103 case WM8988_LOUT2V:104 case WM8988_ROUT2V:105 case WM8988_LPPB:106 return true;107 default:108 return false;109 }110}111 112/* codec private data */113struct wm8988_priv {114 struct regmap *regmap;115 unsigned int sysclk;116 const struct snd_pcm_hw_constraint_list *sysclk_constraints;117};118 119#define wm8988_reset(c) snd_soc_component_write(c, WM8988_RESET, 0)120 121/*122 * WM8988 Controls123 */124 125static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};126static SOC_ENUM_SINGLE_DECL(bass_boost,127 WM8988_BASS, 7, bass_boost_txt);128 129static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };130static SOC_ENUM_SINGLE_DECL(bass_filter,131 WM8988_BASS, 6, bass_filter_txt);132 133static const char *treble_txt[] = {"8kHz", "4kHz"};134static SOC_ENUM_SINGLE_DECL(treble,135 WM8988_TREBLE, 6, treble_txt);136 137static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"};138static SOC_ENUM_SINGLE_DECL(stereo_3d_lc,139 WM8988_3D, 5, stereo_3d_lc_txt);140 141static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"};142static SOC_ENUM_SINGLE_DECL(stereo_3d_uc,143 WM8988_3D, 6, stereo_3d_uc_txt);144 145static const char *stereo_3d_func_txt[] = {"Capture", "Playback"};146static SOC_ENUM_SINGLE_DECL(stereo_3d_func,147 WM8988_3D, 7, stereo_3d_func_txt);148 149static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"};150static SOC_ENUM_SINGLE_DECL(alc_func,151 WM8988_ALC1, 7, alc_func_txt);152 153static const char *ng_type_txt[] = {"Constant PGA Gain",154 "Mute ADC Output"};155static SOC_ENUM_SINGLE_DECL(ng_type,156 WM8988_NGATE, 1, ng_type_txt);157 158static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"};159static SOC_ENUM_SINGLE_DECL(deemph,160 WM8988_ADCDAC, 1, deemph_txt);161 162static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert",163 "L + R Invert"};164static SOC_ENUM_SINGLE_DECL(adcpol,165 WM8988_ADCDAC, 5, adcpol_txt);166 167static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);168static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);169static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);170static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);171static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);172 173static const struct snd_kcontrol_new wm8988_snd_controls[] = {174 175SOC_ENUM("Bass Boost", bass_boost),176SOC_ENUM("Bass Filter", bass_filter),177SOC_SINGLE("Bass Volume", WM8988_BASS, 0, 15, 1),178 179SOC_SINGLE("Treble Volume", WM8988_TREBLE, 0, 15, 0),180SOC_ENUM("Treble Cut-off", treble),181 182SOC_SINGLE("3D Switch", WM8988_3D, 0, 1, 0),183SOC_SINGLE("3D Volume", WM8988_3D, 1, 15, 0),184SOC_ENUM("3D Lower Cut-off", stereo_3d_lc),185SOC_ENUM("3D Upper Cut-off", stereo_3d_uc),186SOC_ENUM("3D Mode", stereo_3d_func),187 188SOC_SINGLE("ALC Capture Target Volume", WM8988_ALC1, 0, 7, 0),189SOC_SINGLE("ALC Capture Max Volume", WM8988_ALC1, 4, 7, 0),190SOC_ENUM("ALC Capture Function", alc_func),191SOC_SINGLE("ALC Capture ZC Switch", WM8988_ALC2, 7, 1, 0),192SOC_SINGLE("ALC Capture Hold Time", WM8988_ALC2, 0, 15, 0),193SOC_SINGLE("ALC Capture Decay Time", WM8988_ALC3, 4, 15, 0),194SOC_SINGLE("ALC Capture Attack Time", WM8988_ALC3, 0, 15, 0),195SOC_SINGLE("ALC Capture NG Threshold", WM8988_NGATE, 3, 31, 0),196SOC_ENUM("ALC Capture NG Type", ng_type),197SOC_SINGLE("ALC Capture NG Switch", WM8988_NGATE, 0, 1, 0),198 199SOC_SINGLE("ZC Timeout Switch", WM8988_ADCTL1, 0, 1, 0),200 201SOC_DOUBLE_R_TLV("Capture Digital Volume", WM8988_LADC, WM8988_RADC,202 0, 255, 0, adc_tlv),203SOC_DOUBLE_R_TLV("Capture Volume", WM8988_LINVOL, WM8988_RINVOL,204 0, 63, 0, pga_tlv),205SOC_DOUBLE_R("Capture ZC Switch", WM8988_LINVOL, WM8988_RINVOL, 6, 1, 0),206SOC_DOUBLE_R("Capture Switch", WM8988_LINVOL, WM8988_RINVOL, 7, 1, 1),207 208SOC_ENUM("Playback De-emphasis", deemph),209 210SOC_ENUM("Capture Polarity", adcpol),211SOC_SINGLE("Playback 6dB Attenuate", WM8988_ADCDAC, 7, 1, 0),212SOC_SINGLE("Capture 6dB Attenuate", WM8988_ADCDAC, 8, 1, 0),213 214SOC_DOUBLE_R_TLV("PCM Volume", WM8988_LDAC, WM8988_RDAC, 0, 255, 0, dac_tlv),215 216SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", WM8988_LOUTM1, 4, 7, 1,217 bypass_tlv),218SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", WM8988_LOUTM2, 4, 7, 1,219 bypass_tlv),220SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", WM8988_ROUTM1, 4, 7, 1,221 bypass_tlv),222SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", WM8988_ROUTM2, 4, 7, 1,223 bypass_tlv),224 225SOC_DOUBLE_R("Output 1 Playback ZC Switch", WM8988_LOUT1V,226 WM8988_ROUT1V, 7, 1, 0),227SOC_DOUBLE_R_TLV("Output 1 Playback Volume", WM8988_LOUT1V, WM8988_ROUT1V,228 0, 127, 0, out_tlv),229 230SOC_DOUBLE_R("Output 2 Playback ZC Switch", WM8988_LOUT2V,231 WM8988_ROUT2V, 7, 1, 0),232SOC_DOUBLE_R_TLV("Output 2 Playback Volume", WM8988_LOUT2V, WM8988_ROUT2V,233 0, 127, 0, out_tlv),234 235};236 237/*238 * DAPM Controls239 */240 241static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,242 struct snd_kcontrol *kcontrol, int event)243{244 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);245 u16 adctl2 = snd_soc_component_read(component, WM8988_ADCTL2);246 247 /* Use the DAC to gate LRC if active, otherwise use ADC */248 if (snd_soc_component_read(component, WM8988_PWR2) & 0x180)249 adctl2 &= ~0x4;250 else251 adctl2 |= 0x4;252 253 return snd_soc_component_write(component, WM8988_ADCTL2, adctl2);254}255 256static const char *wm8988_line_texts[] = {257 "Line 1", "Line 2", "PGA", "Differential"};258 259static const unsigned int wm8988_line_values[] = {260 0, 1, 3, 4};261 262static const struct soc_enum wm8988_lline_enum =263 SOC_VALUE_ENUM_SINGLE(WM8988_LOUTM1, 0, 7,264 ARRAY_SIZE(wm8988_line_texts),265 wm8988_line_texts,266 wm8988_line_values);267static const struct snd_kcontrol_new wm8988_left_line_controls =268 SOC_DAPM_ENUM("Route", wm8988_lline_enum);269 270static const struct soc_enum wm8988_rline_enum =271 SOC_VALUE_ENUM_SINGLE(WM8988_ROUTM1, 0, 7,272 ARRAY_SIZE(wm8988_line_texts),273 wm8988_line_texts,274 wm8988_line_values);275static const struct snd_kcontrol_new wm8988_right_line_controls =276 SOC_DAPM_ENUM("Route", wm8988_rline_enum);277 278/* Left Mixer */279static const struct snd_kcontrol_new wm8988_left_mixer_controls[] = {280 SOC_DAPM_SINGLE("Playback Switch", WM8988_LOUTM1, 8, 1, 0),281 SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_LOUTM1, 7, 1, 0),282 SOC_DAPM_SINGLE("Right Playback Switch", WM8988_LOUTM2, 8, 1, 0),283 SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_LOUTM2, 7, 1, 0),284};285 286/* Right Mixer */287static const struct snd_kcontrol_new wm8988_right_mixer_controls[] = {288 SOC_DAPM_SINGLE("Left Playback Switch", WM8988_ROUTM1, 8, 1, 0),289 SOC_DAPM_SINGLE("Left Bypass Switch", WM8988_ROUTM1, 7, 1, 0),290 SOC_DAPM_SINGLE("Playback Switch", WM8988_ROUTM2, 8, 1, 0),291 SOC_DAPM_SINGLE("Right Bypass Switch", WM8988_ROUTM2, 7, 1, 0),292};293 294static const char *wm8988_pga_sel[] = {"Line 1", "Line 2", "Differential"};295static const unsigned int wm8988_pga_val[] = { 0, 1, 3 };296 297/* Left PGA Mux */298static const struct soc_enum wm8988_lpga_enum =299 SOC_VALUE_ENUM_SINGLE(WM8988_LADCIN, 6, 3,300 ARRAY_SIZE(wm8988_pga_sel),301 wm8988_pga_sel,302 wm8988_pga_val);303static const struct snd_kcontrol_new wm8988_left_pga_controls =304 SOC_DAPM_ENUM("Route", wm8988_lpga_enum);305 306/* Right PGA Mux */307static const struct soc_enum wm8988_rpga_enum =308 SOC_VALUE_ENUM_SINGLE(WM8988_RADCIN, 6, 3,309 ARRAY_SIZE(wm8988_pga_sel),310 wm8988_pga_sel,311 wm8988_pga_val);312static const struct snd_kcontrol_new wm8988_right_pga_controls =313 SOC_DAPM_ENUM("Route", wm8988_rpga_enum);314 315/* Differential Mux */316static const char *wm8988_diff_sel[] = {"Line 1", "Line 2"};317static SOC_ENUM_SINGLE_DECL(diffmux,318 WM8988_ADCIN, 8, wm8988_diff_sel);319static const struct snd_kcontrol_new wm8988_diffmux_controls =320 SOC_DAPM_ENUM("Route", diffmux);321 322/* Mono ADC Mux */323static const char *wm8988_mono_mux[] = {"Stereo", "Mono (Left)",324 "Mono (Right)", "Digital Mono"};325static SOC_ENUM_SINGLE_DECL(monomux,326 WM8988_ADCIN, 6, wm8988_mono_mux);327static const struct snd_kcontrol_new wm8988_monomux_controls =328 SOC_DAPM_ENUM("Route", monomux);329 330static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {331 SND_SOC_DAPM_SUPPLY("Mic Bias", WM8988_PWR1, 1, 0, NULL, 0),332 333 SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,334 &wm8988_diffmux_controls),335 SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,336 &wm8988_monomux_controls),337 SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,338 &wm8988_monomux_controls),339 340 SND_SOC_DAPM_MUX("Left PGA Mux", WM8988_PWR1, 5, 0,341 &wm8988_left_pga_controls),342 SND_SOC_DAPM_MUX("Right PGA Mux", WM8988_PWR1, 4, 0,343 &wm8988_right_pga_controls),344 345 SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,346 &wm8988_left_line_controls),347 SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,348 &wm8988_right_line_controls),349 350 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8988_PWR1, 2, 0),351 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8988_PWR1, 3, 0),352 353 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8988_PWR2, 7, 0),354 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8988_PWR2, 8, 0),355 356 SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,357 &wm8988_left_mixer_controls[0],358 ARRAY_SIZE(wm8988_left_mixer_controls)),359 SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,360 &wm8988_right_mixer_controls[0],361 ARRAY_SIZE(wm8988_right_mixer_controls)),362 363 SND_SOC_DAPM_PGA("Right Out 2", WM8988_PWR2, 3, 0, NULL, 0),364 SND_SOC_DAPM_PGA("Left Out 2", WM8988_PWR2, 4, 0, NULL, 0),365 SND_SOC_DAPM_PGA("Right Out 1", WM8988_PWR2, 5, 0, NULL, 0),366 SND_SOC_DAPM_PGA("Left Out 1", WM8988_PWR2, 6, 0, NULL, 0),367 368 SND_SOC_DAPM_POST("LRC control", wm8988_lrc_control),369 370 SND_SOC_DAPM_OUTPUT("LOUT1"),371 SND_SOC_DAPM_OUTPUT("ROUT1"),372 SND_SOC_DAPM_OUTPUT("LOUT2"),373 SND_SOC_DAPM_OUTPUT("ROUT2"),374 SND_SOC_DAPM_OUTPUT("VREF"),375 376 SND_SOC_DAPM_INPUT("LINPUT1"),377 SND_SOC_DAPM_INPUT("LINPUT2"),378 SND_SOC_DAPM_INPUT("RINPUT1"),379 SND_SOC_DAPM_INPUT("RINPUT2"),380};381 382static const struct snd_soc_dapm_route wm8988_dapm_routes[] = {383 384 { "Left Line Mux", "Line 1", "LINPUT1" },385 { "Left Line Mux", "Line 2", "LINPUT2" },386 { "Left Line Mux", "PGA", "Left PGA Mux" },387 { "Left Line Mux", "Differential", "Differential Mux" },388 389 { "Right Line Mux", "Line 1", "RINPUT1" },390 { "Right Line Mux", "Line 2", "RINPUT2" },391 { "Right Line Mux", "PGA", "Right PGA Mux" },392 { "Right Line Mux", "Differential", "Differential Mux" },393 394 { "Left PGA Mux", "Line 1", "LINPUT1" },395 { "Left PGA Mux", "Line 2", "LINPUT2" },396 { "Left PGA Mux", "Differential", "Differential Mux" },397 398 { "Right PGA Mux", "Line 1", "RINPUT1" },399 { "Right PGA Mux", "Line 2", "RINPUT2" },400 { "Right PGA Mux", "Differential", "Differential Mux" },401 402 { "Differential Mux", "Line 1", "LINPUT1" },403 { "Differential Mux", "Line 1", "RINPUT1" },404 { "Differential Mux", "Line 2", "LINPUT2" },405 { "Differential Mux", "Line 2", "RINPUT2" },406 407 { "Left ADC Mux", "Stereo", "Left PGA Mux" },408 { "Left ADC Mux", "Mono (Left)", "Left PGA Mux" },409 { "Left ADC Mux", "Digital Mono", "Left PGA Mux" },410 411 { "Right ADC Mux", "Stereo", "Right PGA Mux" },412 { "Right ADC Mux", "Mono (Right)", "Right PGA Mux" },413 { "Right ADC Mux", "Digital Mono", "Right PGA Mux" },414 415 { "Left ADC", NULL, "Left ADC Mux" },416 { "Right ADC", NULL, "Right ADC Mux" },417 418 { "Left Line Mux", "Line 1", "LINPUT1" },419 { "Left Line Mux", "Line 2", "LINPUT2" },420 { "Left Line Mux", "PGA", "Left PGA Mux" },421 { "Left Line Mux", "Differential", "Differential Mux" },422 423 { "Right Line Mux", "Line 1", "RINPUT1" },424 { "Right Line Mux", "Line 2", "RINPUT2" },425 { "Right Line Mux", "PGA", "Right PGA Mux" },426 { "Right Line Mux", "Differential", "Differential Mux" },427 428 { "Left Mixer", "Playback Switch", "Left DAC" },429 { "Left Mixer", "Left Bypass Switch", "Left Line Mux" },430 { "Left Mixer", "Right Playback Switch", "Right DAC" },431 { "Left Mixer", "Right Bypass Switch", "Right Line Mux" },432 433 { "Right Mixer", "Left Playback Switch", "Left DAC" },434 { "Right Mixer", "Left Bypass Switch", "Left Line Mux" },435 { "Right Mixer", "Playback Switch", "Right DAC" },436 { "Right Mixer", "Right Bypass Switch", "Right Line Mux" },437 438 { "Left Out 1", NULL, "Left Mixer" },439 { "LOUT1", NULL, "Left Out 1" },440 { "Right Out 1", NULL, "Right Mixer" },441 { "ROUT1", NULL, "Right Out 1" },442 443 { "Left Out 2", NULL, "Left Mixer" },444 { "LOUT2", NULL, "Left Out 2" },445 { "Right Out 2", NULL, "Right Mixer" },446 { "ROUT2", NULL, "Right Out 2" },447};448 449struct _coeff_div {450 u32 mclk;451 u32 rate;452 u16 fs;453 u8 sr:5;454 u8 usb:1;455};456 457/* codec hifi mclk clock divider coefficients */458static const struct _coeff_div coeff_div[] = {459 /* 8k */460 {12288000, 8000, 1536, 0x6, 0x0},461 {11289600, 8000, 1408, 0x16, 0x0},462 {18432000, 8000, 2304, 0x7, 0x0},463 {16934400, 8000, 2112, 0x17, 0x0},464 {12000000, 8000, 1500, 0x6, 0x1},465 466 /* 11.025k */467 {11289600, 11025, 1024, 0x18, 0x0},468 {16934400, 11025, 1536, 0x19, 0x0},469 {12000000, 11025, 1088, 0x19, 0x1},470 471 /* 16k */472 {12288000, 16000, 768, 0xa, 0x0},473 {18432000, 16000, 1152, 0xb, 0x0},474 {12000000, 16000, 750, 0xa, 0x1},475 476 /* 22.05k */477 {11289600, 22050, 512, 0x1a, 0x0},478 {16934400, 22050, 768, 0x1b, 0x0},479 {12000000, 22050, 544, 0x1b, 0x1},480 481 /* 32k */482 {12288000, 32000, 384, 0xc, 0x0},483 {18432000, 32000, 576, 0xd, 0x0},484 {12000000, 32000, 375, 0xa, 0x1},485 486 /* 44.1k */487 {11289600, 44100, 256, 0x10, 0x0},488 {16934400, 44100, 384, 0x11, 0x0},489 {12000000, 44100, 272, 0x11, 0x1},490 491 /* 48k */492 {12288000, 48000, 256, 0x0, 0x0},493 {18432000, 48000, 384, 0x1, 0x0},494 {12000000, 48000, 250, 0x0, 0x1},495 496 /* 88.2k */497 {11289600, 88200, 128, 0x1e, 0x0},498 {16934400, 88200, 192, 0x1f, 0x0},499 {12000000, 88200, 136, 0x1f, 0x1},500 501 /* 96k */502 {12288000, 96000, 128, 0xe, 0x0},503 {18432000, 96000, 192, 0xf, 0x0},504 {12000000, 96000, 125, 0xe, 0x1},505};506 507static inline int get_coeff(int mclk, int rate)508{509 int i;510 511 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {512 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)513 return i;514 }515 516 return -EINVAL;517}518 519/* The set of rates we can generate from the above for each SYSCLK */520 521static const unsigned int rates_12288[] = {522 8000, 12000, 16000, 24000, 32000, 48000, 96000,523};524 525static const struct snd_pcm_hw_constraint_list constraints_12288 = {526 .count = ARRAY_SIZE(rates_12288),527 .list = rates_12288,528};529 530static const unsigned int rates_112896[] = {531 8000, 11025, 22050, 44100,532};533 534static const struct snd_pcm_hw_constraint_list constraints_112896 = {535 .count = ARRAY_SIZE(rates_112896),536 .list = rates_112896,537};538 539static const unsigned int rates_12[] = {540 8000, 11025, 12000, 16000, 22050, 24000, 32000, 41100, 48000,541 48000, 88235, 96000,542};543 544static const struct snd_pcm_hw_constraint_list constraints_12 = {545 .count = ARRAY_SIZE(rates_12),546 .list = rates_12,547};548 549/*550 * Note that this should be called from init rather than from hw_params.551 */552static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai,553 int clk_id, unsigned int freq, int dir)554{555 struct snd_soc_component *component = codec_dai->component;556 struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component);557 558 switch (freq) {559 case 11289600:560 case 18432000:561 case 22579200:562 case 36864000:563 wm8988->sysclk_constraints = &constraints_112896;564 wm8988->sysclk = freq;565 return 0;566 567 case 12288000:568 case 16934400:569 case 24576000:570 case 33868800:571 wm8988->sysclk_constraints = &constraints_12288;572 wm8988->sysclk = freq;573 return 0;574 575 case 12000000:576 case 24000000:577 wm8988->sysclk_constraints = &constraints_12;578 wm8988->sysclk = freq;579 return 0;580 }581 return -EINVAL;582}583 584static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,585 unsigned int fmt)586{587 struct snd_soc_component *component = codec_dai->component;588 u16 iface = 0;589 590 /* set master/slave audio interface */591 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {592 case SND_SOC_DAIFMT_CBM_CFM:593 iface = 0x0040;594 break;595 case SND_SOC_DAIFMT_CBS_CFS:596 break;597 default:598 return -EINVAL;599 }600 601 /* interface format */602 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {603 case SND_SOC_DAIFMT_I2S:604 iface |= 0x0002;605 break;606 case SND_SOC_DAIFMT_RIGHT_J:607 break;608 case SND_SOC_DAIFMT_LEFT_J:609 iface |= 0x0001;610 break;611 case SND_SOC_DAIFMT_DSP_A:612 iface |= 0x0003;613 break;614 case SND_SOC_DAIFMT_DSP_B:615 iface |= 0x0013;616 break;617 default:618 return -EINVAL;619 }620 621 /* clock inversion */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 iface |= 0x0090;627 break;628 case SND_SOC_DAIFMT_IB_NF:629 iface |= 0x0080;630 break;631 case SND_SOC_DAIFMT_NB_IF:632 iface |= 0x0010;633 break;634 default:635 return -EINVAL;636 }637 638 snd_soc_component_write(component, WM8988_IFACE, iface);639 return 0;640}641 642static int wm8988_pcm_startup(struct snd_pcm_substream *substream,643 struct snd_soc_dai *dai)644{645 struct snd_soc_component *component = dai->component;646 struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component);647 648 /* The set of sample rates that can be supported depends on the649 * MCLK supplied to the CODEC - enforce this.650 */651 if (!wm8988->sysclk) {652 dev_err(component->dev,653 "No MCLK configured, call set_sysclk() on init\n");654 return -EINVAL;655 }656 657 snd_pcm_hw_constraint_list(substream->runtime, 0,658 SNDRV_PCM_HW_PARAM_RATE,659 wm8988->sysclk_constraints);660 661 return 0;662}663 664static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,665 struct snd_pcm_hw_params *params,666 struct snd_soc_dai *dai)667{668 struct snd_soc_component *component = dai->component;669 struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component);670 u16 iface = snd_soc_component_read(component, WM8988_IFACE) & 0x1f3;671 u16 srate = snd_soc_component_read(component, WM8988_SRATE) & 0x180;672 int coeff;673 674 coeff = get_coeff(wm8988->sysclk, params_rate(params));675 if (coeff < 0) {676 coeff = get_coeff(wm8988->sysclk / 2, params_rate(params));677 srate |= 0x40;678 }679 if (coeff < 0) {680 dev_err(component->dev,681 "Unable to configure sample rate %dHz with %dHz MCLK\n",682 params_rate(params), wm8988->sysclk);683 return coeff;684 }685 686 /* bit size */687 switch (params_width(params)) {688 case 16:689 break;690 case 20:691 iface |= 0x0004;692 break;693 case 24:694 iface |= 0x0008;695 break;696 case 32:697 iface |= 0x000c;698 break;699 }700 701 /* set iface & srate */702 snd_soc_component_write(component, WM8988_IFACE, iface);703 if (coeff >= 0)704 snd_soc_component_write(component, WM8988_SRATE, srate |705 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);706 707 return 0;708}709 710static int wm8988_mute(struct snd_soc_dai *dai, int mute, int direction)711{712 struct snd_soc_component *component = dai->component;713 u16 mute_reg = snd_soc_component_read(component, WM8988_ADCDAC) & 0xfff7;714 715 if (mute)716 snd_soc_component_write(component, WM8988_ADCDAC, mute_reg | 0x8);717 else718 snd_soc_component_write(component, WM8988_ADCDAC, mute_reg);719 return 0;720}721 722static int wm8988_set_bias_level(struct snd_soc_component *component,723 enum snd_soc_bias_level level)724{725 struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component);726 u16 pwr_reg = snd_soc_component_read(component, WM8988_PWR1) & ~0x1c1;727 728 switch (level) {729 case SND_SOC_BIAS_ON:730 break;731 732 case SND_SOC_BIAS_PREPARE:733 /* VREF, VMID=2x50k, digital enabled */734 snd_soc_component_write(component, WM8988_PWR1, pwr_reg | 0x00c0);735 break;736 737 case SND_SOC_BIAS_STANDBY:738 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {739 regcache_sync(wm8988->regmap);740 741 /* VREF, VMID=2x5k */742 snd_soc_component_write(component, WM8988_PWR1, pwr_reg | 0x1c1);743 744 /* Charge caps */745 msleep(100);746 }747 748 /* VREF, VMID=2*500k, digital stopped */749 snd_soc_component_write(component, WM8988_PWR1, pwr_reg | 0x0141);750 break;751 752 case SND_SOC_BIAS_OFF:753 snd_soc_component_write(component, WM8988_PWR1, 0x0000);754 break;755 }756 return 0;757}758 759#define WM8988_RATES SNDRV_PCM_RATE_8000_96000760 761#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\762 SNDRV_PCM_FMTBIT_S24_LE)763 764static const struct snd_soc_dai_ops wm8988_ops = {765 .startup = wm8988_pcm_startup,766 .hw_params = wm8988_pcm_hw_params,767 .set_fmt = wm8988_set_dai_fmt,768 .set_sysclk = wm8988_set_dai_sysclk,769 .mute_stream = wm8988_mute,770 .no_capture_mute = 1,771};772 773static struct snd_soc_dai_driver wm8988_dai = {774 .name = "wm8988-hifi",775 .playback = {776 .stream_name = "Playback",777 .channels_min = 1,778 .channels_max = 2,779 .rates = WM8988_RATES,780 .formats = WM8988_FORMATS,781 },782 .capture = {783 .stream_name = "Capture",784 .channels_min = 1,785 .channels_max = 2,786 .rates = WM8988_RATES,787 .formats = WM8988_FORMATS,788 },789 .ops = &wm8988_ops,790 .symmetric_rate = 1,791};792 793static int wm8988_probe(struct snd_soc_component *component)794{795 int ret = 0;796 797 ret = wm8988_reset(component);798 if (ret < 0) {799 dev_err(component->dev, "Failed to issue reset\n");800 return ret;801 }802 803 /* set the update bits (we always update left then right) */804 snd_soc_component_update_bits(component, WM8988_RADC, 0x0100, 0x0100);805 snd_soc_component_update_bits(component, WM8988_RDAC, 0x0100, 0x0100);806 snd_soc_component_update_bits(component, WM8988_ROUT1V, 0x0100, 0x0100);807 snd_soc_component_update_bits(component, WM8988_ROUT2V, 0x0100, 0x0100);808 snd_soc_component_update_bits(component, WM8988_RINVOL, 0x0100, 0x0100);809 810 return 0;811}812 813static const struct snd_soc_component_driver soc_component_dev_wm8988 = {814 .probe = wm8988_probe,815 .set_bias_level = wm8988_set_bias_level,816 .controls = wm8988_snd_controls,817 .num_controls = ARRAY_SIZE(wm8988_snd_controls),818 .dapm_widgets = wm8988_dapm_widgets,819 .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets),820 .dapm_routes = wm8988_dapm_routes,821 .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),822 .suspend_bias_off = 1,823 .idle_bias_on = 1,824 .use_pmdown_time = 1,825 .endianness = 1,826};827 828static const struct regmap_config wm8988_regmap = {829 .reg_bits = 7,830 .val_bits = 9,831 832 .max_register = WM8988_LPPB,833 .writeable_reg = wm8988_writeable,834 835 .cache_type = REGCACHE_MAPLE,836 .reg_defaults = wm8988_reg_defaults,837 .num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults),838};839 840#if defined(CONFIG_SPI_MASTER)841static int wm8988_spi_probe(struct spi_device *spi)842{843 struct wm8988_priv *wm8988;844 int ret;845 846 wm8988 = devm_kzalloc(&spi->dev, sizeof(struct wm8988_priv),847 GFP_KERNEL);848 if (wm8988 == NULL)849 return -ENOMEM;850 851 wm8988->regmap = devm_regmap_init_spi(spi, &wm8988_regmap);852 if (IS_ERR(wm8988->regmap)) {853 ret = PTR_ERR(wm8988->regmap);854 dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);855 return ret;856 }857 858 spi_set_drvdata(spi, wm8988);859 860 ret = devm_snd_soc_register_component(&spi->dev,861 &soc_component_dev_wm8988, &wm8988_dai, 1);862 return ret;863}864 865static struct spi_driver wm8988_spi_driver = {866 .driver = {867 .name = "wm8988",868 },869 .probe = wm8988_spi_probe,870};871#endif /* CONFIG_SPI_MASTER */872 873#if IS_ENABLED(CONFIG_I2C)874static int wm8988_i2c_probe(struct i2c_client *i2c)875{876 struct wm8988_priv *wm8988;877 int ret;878 879 wm8988 = devm_kzalloc(&i2c->dev, sizeof(struct wm8988_priv),880 GFP_KERNEL);881 if (wm8988 == NULL)882 return -ENOMEM;883 884 i2c_set_clientdata(i2c, wm8988);885 886 wm8988->regmap = devm_regmap_init_i2c(i2c, &wm8988_regmap);887 if (IS_ERR(wm8988->regmap)) {888 ret = PTR_ERR(wm8988->regmap);889 dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);890 return ret;891 }892 893 ret = devm_snd_soc_register_component(&i2c->dev,894 &soc_component_dev_wm8988, &wm8988_dai, 1);895 return ret;896}897 898static const struct i2c_device_id wm8988_i2c_id[] = {899 { "wm8988" },900 { }901};902MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);903 904static struct i2c_driver wm8988_i2c_driver = {905 .driver = {906 .name = "wm8988",907 },908 .probe = wm8988_i2c_probe,909 .id_table = wm8988_i2c_id,910};911#endif912 913static int __init wm8988_modinit(void)914{915 int ret = 0;916#if IS_ENABLED(CONFIG_I2C)917 ret = i2c_add_driver(&wm8988_i2c_driver);918 if (ret != 0) {919 printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n",920 ret);921 }922#endif923#if defined(CONFIG_SPI_MASTER)924 ret = spi_register_driver(&wm8988_spi_driver);925 if (ret != 0) {926 printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n",927 ret);928 }929#endif930 return ret;931}932module_init(wm8988_modinit);933 934static void __exit wm8988_exit(void)935{936#if IS_ENABLED(CONFIG_I2C)937 i2c_del_driver(&wm8988_i2c_driver);938#endif939#if defined(CONFIG_SPI_MASTER)940 spi_unregister_driver(&wm8988_spi_driver);941#endif942}943module_exit(wm8988_exit);944 945 946MODULE_DESCRIPTION("ASoC WM8988 driver");947MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");948MODULE_LICENSE("GPL");949