1590 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * wm8960.c -- WM8960 ALSA SoC Audio driver4 *5 * Copyright 2007-11 Wolfson Microelectronics, plc6 *7 * Author: Liam Girdwood8 */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/clk.h>16#include <linux/i2c.h>17#include <linux/acpi.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#include <sound/wm8960.h>26 27#include "wm8960.h"28 29/* R25 - Power 1 */30#define WM8960_VMID_MASK 0x18031#define WM8960_VREF 0x4032 33/* R26 - Power 2 */34#define WM8960_PWR2_LOUT1 0x4035#define WM8960_PWR2_ROUT1 0x2036#define WM8960_PWR2_OUT3 0x0237 38/* R28 - Anti-pop 1 */39#define WM8960_POBCTRL 0x8040#define WM8960_BUFDCOPEN 0x1041#define WM8960_BUFIOEN 0x0842#define WM8960_SOFT_ST 0x0443#define WM8960_HPSTBY 0x0144 45/* R29 - Anti-pop 2 */46#define WM8960_DISOP 0x4047#define WM8960_DRES_MASK 0x3048 49#define WM8960_DSCH_TOUT 600 /* discharge timeout, ms */50 51static bool is_pll_freq_available(unsigned int source, unsigned int target);52static int wm8960_set_pll(struct snd_soc_component *component,53 unsigned int freq_in, unsigned int freq_out);54/*55 * wm8960 register cache56 * We can't read the WM8960 register space when we are57 * using 2 wire for device control, so we cache them instead.58 */59static const struct reg_default wm8960_reg_defaults[] = {60 { 0x0, 0x00a7 },61 { 0x1, 0x00a7 },62 { 0x2, 0x0000 },63 { 0x3, 0x0000 },64 { 0x4, 0x0000 },65 { 0x5, 0x0008 },66 { 0x6, 0x0000 },67 { 0x7, 0x000a },68 { 0x8, 0x01c0 },69 { 0x9, 0x0000 },70 { 0xa, 0x00ff },71 { 0xb, 0x00ff },72 73 { 0x10, 0x0000 },74 { 0x11, 0x007b },75 { 0x12, 0x0100 },76 { 0x13, 0x0032 },77 { 0x14, 0x0000 },78 { 0x15, 0x00c3 },79 { 0x16, 0x00c3 },80 { 0x17, 0x01c0 },81 { 0x18, 0x0000 },82 { 0x19, 0x0000 },83 { 0x1a, 0x0000 },84 { 0x1b, 0x0000 },85 { 0x1c, 0x0000 },86 { 0x1d, 0x0000 },87 88 { 0x20, 0x0100 },89 { 0x21, 0x0100 },90 { 0x22, 0x0050 },91 92 { 0x25, 0x0050 },93 { 0x26, 0x0000 },94 { 0x27, 0x0000 },95 { 0x28, 0x0000 },96 { 0x29, 0x0000 },97 { 0x2a, 0x0040 },98 { 0x2b, 0x0000 },99 { 0x2c, 0x0000 },100 { 0x2d, 0x0050 },101 { 0x2e, 0x0050 },102 { 0x2f, 0x0000 },103 { 0x30, 0x0002 },104 { 0x31, 0x0037 },105 106 { 0x33, 0x0080 },107 { 0x34, 0x0008 },108 { 0x35, 0x0031 },109 { 0x36, 0x0026 },110 { 0x37, 0x00e9 },111};112 113static bool wm8960_volatile(struct device *dev, unsigned int reg)114{115 switch (reg) {116 case WM8960_RESET:117 return true;118 default:119 return false;120 }121}122 123#define WM8960_NUM_SUPPLIES 5124static const char *wm8960_supply_names[WM8960_NUM_SUPPLIES] = {125 "DCVDD",126 "DBVDD",127 "AVDD",128 "SPKVDD1",129 "SPKVDD2",130};131 132struct wm8960_priv {133 struct clk *mclk;134 struct regmap *regmap;135 int (*set_bias_level)(struct snd_soc_component *,136 enum snd_soc_bias_level level);137 struct snd_soc_dapm_widget *lout1;138 struct snd_soc_dapm_widget *rout1;139 struct snd_soc_dapm_widget *out3;140 bool deemph;141 int lrclk;142 int bclk;143 int sysclk;144 int clk_id;145 int freq_in;146 bool is_stream_in_use[2];147 struct wm8960_data pdata;148 ktime_t dsch_start;149 struct regulator_bulk_data supplies[WM8960_NUM_SUPPLIES];150};151 152#define wm8960_reset(c) regmap_write(c, WM8960_RESET, 0)153 154/* enumerated controls */155static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted",156 "Right Inverted", "Stereo Inversion"};157static const char *wm8960_3d_upper_cutoff[] = {"High", "Low"};158static const char *wm8960_3d_lower_cutoff[] = {"Low", "High"};159static const char *wm8960_alcfunc[] = {"Off", "Right", "Left", "Stereo"};160static const char *wm8960_alcmode[] = {"ALC", "Limiter"};161static const char *wm8960_adc_data_output_sel[] = {162 "Left Data = Left ADC; Right Data = Right ADC",163 "Left Data = Left ADC; Right Data = Left ADC",164 "Left Data = Right ADC; Right Data = Right ADC",165 "Left Data = Right ADC; Right Data = Left ADC",166};167static const char *wm8960_dmonomix[] = {"Stereo", "Mono"};168static const char *wm8960_dacslope[] = {"Normal", "Sloping"};169 170static const struct soc_enum wm8960_enum[] = {171 SOC_ENUM_SINGLE(WM8960_DACCTL1, 5, 4, wm8960_polarity),172 SOC_ENUM_SINGLE(WM8960_DACCTL2, 5, 4, wm8960_polarity),173 SOC_ENUM_SINGLE(WM8960_3D, 6, 2, wm8960_3d_upper_cutoff),174 SOC_ENUM_SINGLE(WM8960_3D, 5, 2, wm8960_3d_lower_cutoff),175 SOC_ENUM_SINGLE(WM8960_ALC1, 7, 4, wm8960_alcfunc),176 SOC_ENUM_SINGLE(WM8960_ALC3, 8, 2, wm8960_alcmode),177 SOC_ENUM_SINGLE(WM8960_ADDCTL1, 2, 4, wm8960_adc_data_output_sel),178 SOC_ENUM_SINGLE(WM8960_ADDCTL1, 4, 2, wm8960_dmonomix),179 SOC_ENUM_SINGLE(WM8960_DACCTL2, 1, 2, wm8960_dacslope),180};181 182static const int deemph_settings[] = { 0, 32000, 44100, 48000 };183 184static int wm8960_set_deemph(struct snd_soc_component *component)185{186 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);187 int val, i, best;188 189 /* If we're using deemphasis select the nearest available sample190 * rate.191 */192 if (wm8960->deemph) {193 best = 1;194 for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) {195 if (abs(deemph_settings[i] - wm8960->lrclk) <196 abs(deemph_settings[best] - wm8960->lrclk))197 best = i;198 }199 200 val = best << 1;201 } else {202 val = 0;203 }204 205 dev_dbg(component->dev, "Set deemphasis %d\n", val);206 207 return snd_soc_component_update_bits(component, WM8960_DACCTL1,208 0x6, val);209}210 211static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,212 struct snd_ctl_elem_value *ucontrol)213{214 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);215 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);216 217 ucontrol->value.integer.value[0] = wm8960->deemph;218 return 0;219}220 221static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,222 struct snd_ctl_elem_value *ucontrol)223{224 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);225 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);226 unsigned int deemph = ucontrol->value.integer.value[0];227 228 if (deemph > 1)229 return -EINVAL;230 231 wm8960->deemph = deemph;232 233 return wm8960_set_deemph(component);234}235 236static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);237static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1725, 75, 0);238static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);239static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);240static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);241static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1);242static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(micboost_tlv,243 0, 1, TLV_DB_SCALE_ITEM(0, 1300, 0),244 2, 3, TLV_DB_SCALE_ITEM(2000, 900, 0),245);246 247static const struct snd_kcontrol_new wm8960_snd_controls[] = {248SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,249 0, 63, 0, inpga_tlv),250SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,251 6, 1, 0),252SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,253 7, 1, 1),254 255SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT3 Volume",256 WM8960_INBMIX1, 4, 7, 0, lineinboost_tlv),257SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT2 Volume",258 WM8960_INBMIX1, 1, 7, 0, lineinboost_tlv),259SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT3 Volume",260 WM8960_INBMIX2, 4, 7, 0, lineinboost_tlv),261SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT2 Volume",262 WM8960_INBMIX2, 1, 7, 0, lineinboost_tlv),263SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT1 Volume",264 WM8960_RINPATH, 4, 3, 0, micboost_tlv),265SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT1 Volume",266 WM8960_LINPATH, 4, 3, 0, micboost_tlv),267 268SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,269 0, 255, 0, dac_tlv),270 271SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8960_LOUT1, WM8960_ROUT1,272 0, 127, 0, out_tlv),273SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8960_LOUT1, WM8960_ROUT1,274 7, 1, 0),275 276SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8960_LOUT2, WM8960_ROUT2,277 0, 127, 0, out_tlv),278SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8960_LOUT2, WM8960_ROUT2,279 7, 1, 0),280SOC_SINGLE("Speaker DC Volume", WM8960_CLASSD3, 3, 5, 0),281SOC_SINGLE("Speaker AC Volume", WM8960_CLASSD3, 0, 5, 0),282 283SOC_SINGLE("PCM Playback -6dB Switch", WM8960_DACCTL1, 7, 1, 0),284SOC_ENUM("ADC Polarity", wm8960_enum[0]),285SOC_SINGLE("ADC High Pass Filter Switch", WM8960_DACCTL1, 0, 1, 0),286 287SOC_ENUM("DAC Polarity", wm8960_enum[1]),288SOC_SINGLE_BOOL_EXT("DAC Deemphasis Switch", 0,289 wm8960_get_deemph, wm8960_put_deemph),290 291SOC_ENUM("3D Filter Upper Cut-Off", wm8960_enum[2]),292SOC_ENUM("3D Filter Lower Cut-Off", wm8960_enum[3]),293SOC_SINGLE("3D Volume", WM8960_3D, 1, 15, 0),294SOC_SINGLE("3D Switch", WM8960_3D, 0, 1, 0),295 296SOC_ENUM("ALC Function", wm8960_enum[4]),297SOC_SINGLE("ALC Max Gain", WM8960_ALC1, 4, 7, 0),298SOC_SINGLE("ALC Target", WM8960_ALC1, 0, 15, 1),299SOC_SINGLE("ALC Min Gain", WM8960_ALC2, 4, 7, 0),300SOC_SINGLE("ALC Hold Time", WM8960_ALC2, 0, 15, 0),301SOC_ENUM("ALC Mode", wm8960_enum[5]),302SOC_SINGLE("ALC Decay", WM8960_ALC3, 4, 15, 0),303SOC_SINGLE("ALC Attack", WM8960_ALC3, 0, 15, 0),304 305SOC_SINGLE("Noise Gate Threshold", WM8960_NOISEG, 3, 31, 0),306SOC_SINGLE("Noise Gate Switch", WM8960_NOISEG, 0, 1, 0),307 308SOC_DOUBLE_R_TLV("ADC PCM Capture Volume", WM8960_LADC, WM8960_RADC,309 0, 255, 0, adc_tlv),310 311SOC_SINGLE_TLV("Left Output Mixer Boost Bypass Volume",312 WM8960_BYPASS1, 4, 7, 1, bypass_tlv),313SOC_SINGLE_TLV("Left Output Mixer LINPUT3 Volume",314 WM8960_LOUTMIX, 4, 7, 1, bypass_tlv),315SOC_SINGLE_TLV("Right Output Mixer Boost Bypass Volume",316 WM8960_BYPASS2, 4, 7, 1, bypass_tlv),317SOC_SINGLE_TLV("Right Output Mixer RINPUT3 Volume",318 WM8960_ROUTMIX, 4, 7, 1, bypass_tlv),319 320SOC_ENUM("ADC Data Output Select", wm8960_enum[6]),321SOC_ENUM("DAC Mono Mix", wm8960_enum[7]),322SOC_ENUM("DAC Filter Characteristics", wm8960_enum[8]),323};324 325static const struct snd_kcontrol_new wm8960_lin_boost[] = {326SOC_DAPM_SINGLE("LINPUT2 Switch", WM8960_LINPATH, 6, 1, 0),327SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LINPATH, 7, 1, 0),328SOC_DAPM_SINGLE("LINPUT1 Switch", WM8960_LINPATH, 8, 1, 0),329};330 331static const struct snd_kcontrol_new wm8960_lin[] = {332SOC_DAPM_SINGLE("Boost Switch", WM8960_LINPATH, 3, 1, 0),333};334 335static const struct snd_kcontrol_new wm8960_rin_boost[] = {336SOC_DAPM_SINGLE("RINPUT2 Switch", WM8960_RINPATH, 6, 1, 0),337SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_RINPATH, 7, 1, 0),338SOC_DAPM_SINGLE("RINPUT1 Switch", WM8960_RINPATH, 8, 1, 0),339};340 341static const struct snd_kcontrol_new wm8960_rin[] = {342SOC_DAPM_SINGLE("Boost Switch", WM8960_RINPATH, 3, 1, 0),343};344 345static const struct snd_kcontrol_new wm8960_loutput_mixer[] = {346SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_LOUTMIX, 8, 1, 0),347SOC_DAPM_SINGLE("LINPUT3 Switch", WM8960_LOUTMIX, 7, 1, 0),348SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS1, 7, 1, 0),349};350 351static const struct snd_kcontrol_new wm8960_routput_mixer[] = {352SOC_DAPM_SINGLE("PCM Playback Switch", WM8960_ROUTMIX, 8, 1, 0),353SOC_DAPM_SINGLE("RINPUT3 Switch", WM8960_ROUTMIX, 7, 1, 0),354SOC_DAPM_SINGLE("Boost Bypass Switch", WM8960_BYPASS2, 7, 1, 0),355};356 357static const struct snd_kcontrol_new wm8960_mono_out[] = {358SOC_DAPM_SINGLE("Left Switch", WM8960_MONOMIX1, 7, 1, 0),359SOC_DAPM_SINGLE("Right Switch", WM8960_MONOMIX2, 7, 1, 0),360};361 362static const struct snd_soc_dapm_widget wm8960_dapm_widgets[] = {363SND_SOC_DAPM_INPUT("LINPUT1"),364SND_SOC_DAPM_INPUT("RINPUT1"),365SND_SOC_DAPM_INPUT("LINPUT2"),366SND_SOC_DAPM_INPUT("RINPUT2"),367SND_SOC_DAPM_INPUT("LINPUT3"),368SND_SOC_DAPM_INPUT("RINPUT3"),369 370SND_SOC_DAPM_SUPPLY("MICB", WM8960_POWER1, 1, 0, NULL, 0),371 372SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,373 wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)),374SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8960_POWER1, 4, 0,375 wm8960_rin_boost, ARRAY_SIZE(wm8960_rin_boost)),376 377SND_SOC_DAPM_MIXER("Left Input Mixer", WM8960_POWER3, 5, 0,378 wm8960_lin, ARRAY_SIZE(wm8960_lin)),379SND_SOC_DAPM_MIXER("Right Input Mixer", WM8960_POWER3, 4, 0,380 wm8960_rin, ARRAY_SIZE(wm8960_rin)),381 382SND_SOC_DAPM_ADC("Left ADC", "Capture", WM8960_POWER1, 3, 0),383SND_SOC_DAPM_ADC("Right ADC", "Capture", WM8960_POWER1, 2, 0),384 385SND_SOC_DAPM_DAC("Left DAC", "Playback", WM8960_POWER2, 8, 0),386SND_SOC_DAPM_DAC("Right DAC", "Playback", WM8960_POWER2, 7, 0),387 388SND_SOC_DAPM_MIXER("Left Output Mixer", WM8960_POWER3, 3, 0,389 &wm8960_loutput_mixer[0],390 ARRAY_SIZE(wm8960_loutput_mixer)),391SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0,392 &wm8960_routput_mixer[0],393 ARRAY_SIZE(wm8960_routput_mixer)),394 395SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0),396SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0),397 398SND_SOC_DAPM_PGA("Left Speaker PGA", WM8960_POWER2, 4, 0, NULL, 0),399SND_SOC_DAPM_PGA("Right Speaker PGA", WM8960_POWER2, 3, 0, NULL, 0),400 401SND_SOC_DAPM_PGA("Right Speaker Output", WM8960_CLASSD1, 7, 0, NULL, 0),402SND_SOC_DAPM_PGA("Left Speaker Output", WM8960_CLASSD1, 6, 0, NULL, 0),403 404SND_SOC_DAPM_OUTPUT("SPK_LP"),405SND_SOC_DAPM_OUTPUT("SPK_LN"),406SND_SOC_DAPM_OUTPUT("HP_L"),407SND_SOC_DAPM_OUTPUT("HP_R"),408SND_SOC_DAPM_OUTPUT("SPK_RP"),409SND_SOC_DAPM_OUTPUT("SPK_RN"),410SND_SOC_DAPM_OUTPUT("OUT3"),411};412 413static const struct snd_soc_dapm_widget wm8960_dapm_widgets_out3[] = {414SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0,415 &wm8960_mono_out[0],416 ARRAY_SIZE(wm8960_mono_out)),417};418 419/* Represent OUT3 as a PGA so that it gets turned on with LOUT1/ROUT1 */420static const struct snd_soc_dapm_widget wm8960_dapm_widgets_capless[] = {421SND_SOC_DAPM_PGA("OUT3 VMID", WM8960_POWER2, 1, 0, NULL, 0),422};423 424static const struct snd_soc_dapm_route audio_paths[] = {425 { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" },426 { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" },427 { "Left Boost Mixer", "LINPUT3 Switch", "LINPUT3" },428 429 { "Left Input Mixer", "Boost Switch", "Left Boost Mixer" },430 { "Left Input Mixer", "Boost Switch", "LINPUT1" }, /* Really Boost Switch */431 { "Left Input Mixer", NULL, "LINPUT2" },432 { "Left Input Mixer", NULL, "LINPUT3" },433 434 { "Right Boost Mixer", "RINPUT1 Switch", "RINPUT1" },435 { "Right Boost Mixer", "RINPUT2 Switch", "RINPUT2" },436 { "Right Boost Mixer", "RINPUT3 Switch", "RINPUT3" },437 438 { "Right Input Mixer", "Boost Switch", "Right Boost Mixer" },439 { "Right Input Mixer", "Boost Switch", "RINPUT1" }, /* Really Boost Switch */440 { "Right Input Mixer", NULL, "RINPUT2" },441 { "Right Input Mixer", NULL, "RINPUT3" },442 443 { "Left ADC", NULL, "Left Input Mixer" },444 { "Right ADC", NULL, "Right Input Mixer" },445 446 { "Left Output Mixer", "LINPUT3 Switch", "LINPUT3" },447 { "Left Output Mixer", "Boost Bypass Switch", "Left Boost Mixer" },448 { "Left Output Mixer", "PCM Playback Switch", "Left DAC" },449 450 { "Right Output Mixer", "RINPUT3 Switch", "RINPUT3" },451 { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" },452 { "Right Output Mixer", "PCM Playback Switch", "Right DAC" },453 454 { "LOUT1 PGA", NULL, "Left Output Mixer" },455 { "ROUT1 PGA", NULL, "Right Output Mixer" },456 457 { "HP_L", NULL, "LOUT1 PGA" },458 { "HP_R", NULL, "ROUT1 PGA" },459 460 { "Left Speaker PGA", NULL, "Left Output Mixer" },461 { "Right Speaker PGA", NULL, "Right Output Mixer" },462 463 { "Left Speaker Output", NULL, "Left Speaker PGA" },464 { "Right Speaker Output", NULL, "Right Speaker PGA" },465 466 { "SPK_LN", NULL, "Left Speaker Output" },467 { "SPK_LP", NULL, "Left Speaker Output" },468 { "SPK_RN", NULL, "Right Speaker Output" },469 { "SPK_RP", NULL, "Right Speaker Output" },470};471 472static const struct snd_soc_dapm_route audio_paths_out3[] = {473 { "Mono Output Mixer", "Left Switch", "Left Output Mixer" },474 { "Mono Output Mixer", "Right Switch", "Right Output Mixer" },475 476 { "OUT3", NULL, "Mono Output Mixer", }477};478 479static const struct snd_soc_dapm_route audio_paths_capless[] = {480 { "HP_L", NULL, "OUT3 VMID" },481 { "HP_R", NULL, "OUT3 VMID" },482 483 { "OUT3 VMID", NULL, "Left Output Mixer" },484 { "OUT3 VMID", NULL, "Right Output Mixer" },485};486 487static int wm8960_add_widgets(struct snd_soc_component *component)488{489 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);490 struct wm8960_data *pdata = &wm8960->pdata;491 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);492 struct snd_soc_dapm_widget *w;493 494 snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets,495 ARRAY_SIZE(wm8960_dapm_widgets));496 497 snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));498 499 /* In capless mode OUT3 is used to provide VMID for the500 * headphone outputs, otherwise it is used as a mono mixer.501 */502 if (pdata && pdata->capless) {503 snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets_capless,504 ARRAY_SIZE(wm8960_dapm_widgets_capless));505 506 snd_soc_dapm_add_routes(dapm, audio_paths_capless,507 ARRAY_SIZE(audio_paths_capless));508 } else {509 snd_soc_dapm_new_controls(dapm, wm8960_dapm_widgets_out3,510 ARRAY_SIZE(wm8960_dapm_widgets_out3));511 512 snd_soc_dapm_add_routes(dapm, audio_paths_out3,513 ARRAY_SIZE(audio_paths_out3));514 }515 516 /* We need to power up the headphone output stage out of517 * sequence for capless mode. To save scanning the widget518 * list each time to find the desired power state do so now519 * and save the result.520 */521 list_for_each_entry(w, &component->card->widgets, list) {522 if (w->dapm != dapm)523 continue;524 if (strcmp(w->name, "LOUT1 PGA") == 0)525 wm8960->lout1 = w;526 if (strcmp(w->name, "ROUT1 PGA") == 0)527 wm8960->rout1 = w;528 if (strcmp(w->name, "OUT3 VMID") == 0)529 wm8960->out3 = w;530 }531 532 return 0;533}534 535static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,536 unsigned int fmt)537{538 struct snd_soc_component *component = codec_dai->component;539 u16 iface = 0;540 541 /* set master/slave audio interface */542 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {543 case SND_SOC_DAIFMT_CBM_CFM:544 iface |= 0x0040;545 break;546 case SND_SOC_DAIFMT_CBS_CFS:547 break;548 default:549 return -EINVAL;550 }551 552 /* interface format */553 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {554 case SND_SOC_DAIFMT_I2S:555 iface |= 0x0002;556 break;557 case SND_SOC_DAIFMT_RIGHT_J:558 break;559 case SND_SOC_DAIFMT_LEFT_J:560 iface |= 0x0001;561 break;562 case SND_SOC_DAIFMT_DSP_A:563 iface |= 0x0003;564 break;565 case SND_SOC_DAIFMT_DSP_B:566 iface |= 0x0013;567 break;568 default:569 return -EINVAL;570 }571 572 /* clock inversion */573 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {574 case SND_SOC_DAIFMT_NB_NF:575 break;576 case SND_SOC_DAIFMT_IB_IF:577 iface |= 0x0090;578 break;579 case SND_SOC_DAIFMT_IB_NF:580 iface |= 0x0080;581 break;582 case SND_SOC_DAIFMT_NB_IF:583 iface |= 0x0010;584 break;585 default:586 return -EINVAL;587 }588 589 /* set iface */590 snd_soc_component_write(component, WM8960_IFACE1, iface);591 return 0;592}593 594static struct {595 int rate;596 unsigned int val;597} alc_rates[] = {598 { 48000, 0 },599 { 44100, 0 },600 { 32000, 1 },601 { 22050, 2 },602 { 24000, 2 },603 { 16000, 3 },604 { 11025, 4 },605 { 12000, 4 },606 { 8000, 5 },607};608 609/* -1 for reserved value */610static const int sysclk_divs[] = { 1, -1, 2, -1 };611 612/* Multiply 256 for internal 256 div */613static const int dac_divs[] = { 256, 384, 512, 768, 1024, 1408, 1536 };614 615/* Multiply 10 to eliminate decimials */616static const int bclk_divs[] = {617 10, 15, 20, 30, 40, 55, 60, 80, 110,618 120, 160, 220, 240, 320, 320, 320619};620 621/**622 * wm8960_configure_sysclk - checks if there is a sysclk frequency available623 * The sysclk must be chosen such that:624 * - sysclk = MCLK / sysclk_divs625 * - lrclk = sysclk / dac_divs626 * - 10 * bclk = sysclk / bclk_divs627 *628 * @wm8960: codec private data629 * @mclk: MCLK used to derive sysclk630 * @sysclk_idx: sysclk_divs index for found sysclk631 * @dac_idx: dac_divs index for found lrclk632 * @bclk_idx: bclk_divs index for found bclk633 *634 * Returns:635 * -1, in case no sysclk frequency available found636 * >=0, in case we could derive bclk and lrclk from sysclk using637 * (@sysclk_idx, @dac_idx, @bclk_idx) dividers638 */639static640int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,641 int *sysclk_idx, int *dac_idx, int *bclk_idx)642{643 int sysclk, bclk, lrclk;644 int i, j, k;645 int diff;646 647 /* marker for no match */648 *bclk_idx = -1;649 650 bclk = wm8960->bclk;651 lrclk = wm8960->lrclk;652 653 /* check if the sysclk frequency is available. */654 for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {655 if (sysclk_divs[i] == -1)656 continue;657 sysclk = mclk / sysclk_divs[i];658 for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {659 if (sysclk != dac_divs[j] * lrclk)660 continue;661 for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) {662 diff = sysclk - bclk * bclk_divs[k] / 10;663 if (diff == 0) {664 *sysclk_idx = i;665 *dac_idx = j;666 *bclk_idx = k;667 break;668 }669 }670 if (k != ARRAY_SIZE(bclk_divs))671 break;672 }673 if (j != ARRAY_SIZE(dac_divs))674 break;675 }676 return *bclk_idx;677}678 679/**680 * wm8960_configure_pll - checks if there is a PLL out frequency available681 * The PLL out frequency must be chosen such that:682 * - sysclk = lrclk * dac_divs683 * - freq_out = sysclk * sysclk_divs684 * - 10 * sysclk = bclk * bclk_divs685 *686 * If we cannot find an exact match for (sysclk, lrclk, bclk)687 * triplet, we relax the bclk such that bclk is chosen as the688 * closest available frequency greater than expected bclk.689 *690 * @component: component structure691 * @freq_in: input frequency used to derive freq out via PLL692 * @sysclk_idx: sysclk_divs index for found sysclk693 * @dac_idx: dac_divs index for found lrclk694 * @bclk_idx: bclk_divs index for found bclk695 *696 * Returns:697 * < 0, in case no PLL frequency out available was found698 * >=0, in case we could derive bclk, lrclk, sysclk from PLL out using699 * (@sysclk_idx, @dac_idx, @bclk_idx) dividers700 */701static702int wm8960_configure_pll(struct snd_soc_component *component, int freq_in,703 int *sysclk_idx, int *dac_idx, int *bclk_idx)704{705 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);706 int sysclk, bclk, lrclk, freq_out;707 int diff, closest, best_freq_out;708 int i, j, k;709 710 bclk = wm8960->bclk;711 lrclk = wm8960->lrclk;712 closest = freq_in;713 714 best_freq_out = -EINVAL;715 *sysclk_idx = *dac_idx = *bclk_idx = -1;716 717 /*718 * From Datasheet, the PLL performs best when f2 is between719 * 90MHz and 100MHz, the desired sysclk output is 11.2896MHz720 * or 12.288MHz, then sysclkdiv = 2 is the best choice.721 * So search sysclk_divs from 2 to 1 other than from 1 to 2.722 */723 for (i = ARRAY_SIZE(sysclk_divs) - 1; i >= 0; --i) {724 if (sysclk_divs[i] == -1)725 continue;726 for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {727 sysclk = lrclk * dac_divs[j];728 freq_out = sysclk * sysclk_divs[i];729 730 for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) {731 if (!is_pll_freq_available(freq_in, freq_out))732 continue;733 734 diff = sysclk - bclk * bclk_divs[k] / 10;735 if (diff == 0) {736 *sysclk_idx = i;737 *dac_idx = j;738 *bclk_idx = k;739 return freq_out;740 }741 if (diff > 0 && closest > diff) {742 *sysclk_idx = i;743 *dac_idx = j;744 *bclk_idx = k;745 closest = diff;746 best_freq_out = freq_out;747 }748 }749 }750 }751 752 return best_freq_out;753}754static int wm8960_configure_clocking(struct snd_soc_component *component)755{756 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);757 int freq_out, freq_in;758 u16 iface1 = snd_soc_component_read(component, WM8960_IFACE1);759 int i, j, k;760 int ret;761 762 /*763 * For Slave mode clocking should still be configured,764 * so this if statement should be removed, but some platform765 * may not work if the sysclk is not configured, to avoid such766 * compatible issue, just add '!wm8960->sysclk' condition in767 * this if statement.768 */769 if (!(iface1 & (1 << 6)) && !wm8960->sysclk) {770 dev_warn(component->dev,771 "slave mode, but proceeding with no clock configuration\n");772 return 0;773 }774 775 if (wm8960->clk_id != WM8960_SYSCLK_MCLK && !wm8960->freq_in) {776 dev_err(component->dev, "No MCLK configured\n");777 return -EINVAL;778 }779 780 freq_in = wm8960->freq_in;781 /*782 * If it's sysclk auto mode, check if the MCLK can provide sysclk or783 * not. If MCLK can provide sysclk, using MCLK to provide sysclk784 * directly. Otherwise, auto select a available pll out frequency785 * and set PLL.786 */787 if (wm8960->clk_id == WM8960_SYSCLK_AUTO) {788 /* disable the PLL and using MCLK to provide sysclk */789 wm8960_set_pll(component, 0, 0);790 freq_out = freq_in;791 } else if (wm8960->sysclk) {792 freq_out = wm8960->sysclk;793 } else {794 dev_err(component->dev, "No SYSCLK configured\n");795 return -EINVAL;796 }797 798 if (wm8960->clk_id != WM8960_SYSCLK_PLL) {799 ret = wm8960_configure_sysclk(wm8960, freq_out, &i, &j, &k);800 if (ret >= 0) {801 goto configure_clock;802 } else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) {803 dev_err(component->dev, "failed to configure clock\n");804 return -EINVAL;805 }806 }807 808 freq_out = wm8960_configure_pll(component, freq_in, &i, &j, &k);809 if (freq_out < 0) {810 dev_err(component->dev, "failed to configure clock via PLL\n");811 return freq_out;812 }813 wm8960_set_pll(component, freq_in, freq_out);814 815configure_clock:816 /* configure sysclk clock */817 snd_soc_component_update_bits(component, WM8960_CLOCK1, 3 << 1, i << 1);818 819 /* configure frame clock */820 snd_soc_component_update_bits(component, WM8960_CLOCK1, 0x7 << 3, j << 3);821 snd_soc_component_update_bits(component, WM8960_CLOCK1, 0x7 << 6, j << 6);822 823 /* configure bit clock */824 snd_soc_component_update_bits(component, WM8960_CLOCK2, 0xf, k);825 826 return 0;827}828 829static int wm8960_hw_params(struct snd_pcm_substream *substream,830 struct snd_pcm_hw_params *params,831 struct snd_soc_dai *dai)832{833 struct snd_soc_component *component = dai->component;834 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);835 u16 iface = snd_soc_component_read(component, WM8960_IFACE1) & 0xfff3;836 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;837 int i;838 839 wm8960->bclk = snd_soc_params_to_bclk(params);840 if (params_channels(params) == 1)841 wm8960->bclk *= 2;842 843 /* bit size */844 switch (params_width(params)) {845 case 16:846 break;847 case 20:848 iface |= 0x0004;849 break;850 case 24:851 iface |= 0x0008;852 break;853 case 32:854 /* right justify mode does not support 32 word length */855 if ((iface & 0x3) != 0) {856 iface |= 0x000c;857 break;858 }859 fallthrough;860 default:861 dev_err(component->dev, "unsupported width %d\n",862 params_width(params));863 return -EINVAL;864 }865 866 wm8960->lrclk = params_rate(params);867 /* Update filters for the new rate */868 if (tx) {869 wm8960_set_deemph(component);870 } else {871 for (i = 0; i < ARRAY_SIZE(alc_rates); i++)872 if (alc_rates[i].rate == params_rate(params))873 snd_soc_component_update_bits(component,874 WM8960_ADDCTL3, 0x7,875 alc_rates[i].val);876 }877 878 /* set iface */879 snd_soc_component_write(component, WM8960_IFACE1, iface);880 881 wm8960->is_stream_in_use[tx] = true;882 883 if (!wm8960->is_stream_in_use[!tx])884 return wm8960_configure_clocking(component);885 886 return 0;887}888 889static int wm8960_hw_free(struct snd_pcm_substream *substream,890 struct snd_soc_dai *dai)891{892 struct snd_soc_component *component = dai->component;893 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);894 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;895 896 wm8960->is_stream_in_use[tx] = false;897 898 return 0;899}900 901static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)902{903 struct snd_soc_component *component = dai->component;904 905 if (mute)906 snd_soc_component_update_bits(component, WM8960_DACCTL1, 0x8, 0x8);907 else908 snd_soc_component_update_bits(component, WM8960_DACCTL1, 0x8, 0);909 return 0;910}911 912static int wm8960_set_bias_level_out3(struct snd_soc_component *component,913 enum snd_soc_bias_level level)914{915 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);916 u16 pm2 = snd_soc_component_read(component, WM8960_POWER2);917 int ret;918 ktime_t tout;919 920 switch (level) {921 case SND_SOC_BIAS_ON:922 break;923 924 case SND_SOC_BIAS_PREPARE:925 switch (snd_soc_component_get_bias_level(component)) {926 case SND_SOC_BIAS_STANDBY:927 if (!IS_ERR(wm8960->mclk)) {928 ret = clk_prepare_enable(wm8960->mclk);929 if (ret) {930 dev_err(component->dev,931 "Failed to enable MCLK: %d\n",932 ret);933 return ret;934 }935 }936 937 ret = wm8960_configure_clocking(component);938 if (ret)939 return ret;940 941 /* Set VMID to 2x50k */942 snd_soc_component_update_bits(component, WM8960_POWER1, 0x180, 0x80);943 break;944 945 case SND_SOC_BIAS_ON:946 /*947 * If it's sysclk auto mode, and the pll is enabled,948 * disable the pll949 */950 if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1))951 wm8960_set_pll(component, 0, 0);952 953 if (!IS_ERR(wm8960->mclk))954 clk_disable_unprepare(wm8960->mclk);955 break;956 957 default:958 break;959 }960 961 break;962 963 case SND_SOC_BIAS_STANDBY:964 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {965 /* ensure discharge is complete */966 tout = WM8960_DSCH_TOUT - ktime_ms_delta(ktime_get(), wm8960->dsch_start);967 if (tout > 0)968 msleep(tout);969 970 regcache_sync(wm8960->regmap);971 972 /* Enable anti-pop features */973 snd_soc_component_write(component, WM8960_APOP1,974 WM8960_POBCTRL | WM8960_SOFT_ST |975 WM8960_BUFDCOPEN | WM8960_BUFIOEN);976 977 /* Enable & ramp VMID at 2x50k */978 snd_soc_component_update_bits(component, WM8960_POWER1, 0x80, 0x80);979 msleep(100);980 981 /* Enable VREF */982 snd_soc_component_update_bits(component, WM8960_POWER1, WM8960_VREF,983 WM8960_VREF);984 985 /* Disable anti-pop features */986 snd_soc_component_write(component, WM8960_APOP1, WM8960_BUFIOEN);987 }988 989 /* Set VMID to 2x250k */990 snd_soc_component_update_bits(component, WM8960_POWER1, 0x180, 0x100);991 break;992 993 case SND_SOC_BIAS_OFF:994 /* Enable anti-pop features */995 snd_soc_component_write(component, WM8960_APOP1,996 WM8960_POBCTRL | WM8960_SOFT_ST |997 WM8960_BUFDCOPEN | WM8960_BUFIOEN);998 999 /* Disable VMID and VREF, mark discharge */1000 snd_soc_component_write(component, WM8960_POWER1, 0);1001 wm8960->dsch_start = ktime_get();1002 break;1003 }1004 1005 return 0;1006}1007 1008static int wm8960_set_bias_level_capless(struct snd_soc_component *component,1009 enum snd_soc_bias_level level)1010{1011 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);1012 u16 pm2 = snd_soc_component_read(component, WM8960_POWER2);1013 int reg, ret;1014 1015 switch (level) {1016 case SND_SOC_BIAS_ON:1017 break;1018 1019 case SND_SOC_BIAS_PREPARE:1020 switch (snd_soc_component_get_bias_level(component)) {1021 case SND_SOC_BIAS_STANDBY:1022 /* Enable anti pop mode */1023 snd_soc_component_update_bits(component, WM8960_APOP1,1024 WM8960_POBCTRL | WM8960_SOFT_ST |1025 WM8960_BUFDCOPEN,1026 WM8960_POBCTRL | WM8960_SOFT_ST |1027 WM8960_BUFDCOPEN);1028 1029 /* Enable LOUT1, ROUT1 and OUT3 if they're enabled */1030 reg = 0;1031 if (wm8960->lout1 && wm8960->lout1->power)1032 reg |= WM8960_PWR2_LOUT1;1033 if (wm8960->rout1 && wm8960->rout1->power)1034 reg |= WM8960_PWR2_ROUT1;1035 if (wm8960->out3 && wm8960->out3->power)1036 reg |= WM8960_PWR2_OUT3;1037 snd_soc_component_update_bits(component, WM8960_POWER2,1038 WM8960_PWR2_LOUT1 |1039 WM8960_PWR2_ROUT1 |1040 WM8960_PWR2_OUT3, reg);1041 1042 /* Enable VMID at 2*50k */1043 snd_soc_component_update_bits(component, WM8960_POWER1,1044 WM8960_VMID_MASK, 0x80);1045 1046 /* Ramp */1047 msleep(100);1048 1049 /* Enable VREF */1050 snd_soc_component_update_bits(component, WM8960_POWER1,1051 WM8960_VREF, WM8960_VREF);1052 1053 msleep(100);1054 1055 if (!IS_ERR(wm8960->mclk)) {1056 ret = clk_prepare_enable(wm8960->mclk);1057 if (ret) {1058 dev_err(component->dev,1059 "Failed to enable MCLK: %d\n",1060 ret);1061 return ret;1062 }1063 }1064 1065 ret = wm8960_configure_clocking(component);1066 if (ret)1067 return ret;1068 1069 break;1070 1071 case SND_SOC_BIAS_ON:1072 /*1073 * If it's sysclk auto mode, and the pll is enabled,1074 * disable the pll1075 */1076 if (wm8960->clk_id == WM8960_SYSCLK_AUTO && (pm2 & 0x1))1077 wm8960_set_pll(component, 0, 0);1078 1079 if (!IS_ERR(wm8960->mclk))1080 clk_disable_unprepare(wm8960->mclk);1081 1082 /* Enable anti-pop mode */1083 snd_soc_component_update_bits(component, WM8960_APOP1,1084 WM8960_POBCTRL | WM8960_SOFT_ST |1085 WM8960_BUFDCOPEN,1086 WM8960_POBCTRL | WM8960_SOFT_ST |1087 WM8960_BUFDCOPEN);1088 1089 /* Disable VMID and VREF */1090 snd_soc_component_update_bits(component, WM8960_POWER1,1091 WM8960_VREF | WM8960_VMID_MASK, 0);1092 break;1093 1094 case SND_SOC_BIAS_OFF:1095 regcache_sync(wm8960->regmap);1096 break;1097 default:1098 break;1099 }1100 break;1101 1102 case SND_SOC_BIAS_STANDBY:1103 switch (snd_soc_component_get_bias_level(component)) {1104 case SND_SOC_BIAS_PREPARE:1105 /* Disable HP discharge */1106 snd_soc_component_update_bits(component, WM8960_APOP2,1107 WM8960_DISOP | WM8960_DRES_MASK,1108 0);1109 1110 /* Disable anti-pop features */1111 snd_soc_component_update_bits(component, WM8960_APOP1,1112 WM8960_POBCTRL | WM8960_SOFT_ST |1113 WM8960_BUFDCOPEN,1114 WM8960_POBCTRL | WM8960_SOFT_ST |1115 WM8960_BUFDCOPEN);1116 break;1117 1118 default:1119 break;1120 }1121 break;1122 1123 case SND_SOC_BIAS_OFF:1124 break;1125 }1126 1127 return 0;1128}1129 1130/* PLL divisors */1131struct _pll_div {1132 u32 pre_div:1;1133 u32 n:4;1134 u32 k:24;1135};1136 1137static bool is_pll_freq_available(unsigned int source, unsigned int target)1138{1139 unsigned int Ndiv;1140 1141 if (source == 0 || target == 0)1142 return false;1143 1144 /* Scale up target to PLL operating frequency */1145 target *= 4;1146 Ndiv = target / source;1147 1148 if (Ndiv < 6) {1149 source >>= 1;1150 Ndiv = target / source;1151 }1152 1153 if ((Ndiv < 6) || (Ndiv > 12))1154 return false;1155 1156 return true;1157}1158 1159/* The size in bits of the pll divide multiplied by 101160 * to allow rounding later */1161#define FIXED_PLL_SIZE ((1 << 24) * 10)1162 1163static int pll_factors(unsigned int source, unsigned int target,1164 struct _pll_div *pll_div)1165{1166 unsigned long long Kpart;1167 unsigned int K, Ndiv, Nmod;1168 1169 pr_debug("WM8960 PLL: setting %dHz->%dHz\n", source, target);1170 1171 /* Scale up target to PLL operating frequency */1172 target *= 4;1173 1174 Ndiv = target / source;1175 if (Ndiv < 6) {1176 source >>= 1;1177 pll_div->pre_div = 1;1178 Ndiv = target / source;1179 } else1180 pll_div->pre_div = 0;1181 1182 if ((Ndiv < 6) || (Ndiv > 12)) {1183 pr_err("WM8960 PLL: Unsupported N=%d\n", Ndiv);1184 return -EINVAL;1185 }1186 1187 pll_div->n = Ndiv;1188 Nmod = target % source;1189 Kpart = FIXED_PLL_SIZE * (long long)Nmod;1190 1191 do_div(Kpart, source);1192 1193 K = Kpart & 0xFFFFFFFF;1194 1195 /* Check if we need to round */1196 if ((K % 10) >= 5)1197 K += 5;1198 1199 /* Move down to proper range now rounding is done */1200 K /= 10;1201 1202 pll_div->k = K;1203 1204 pr_debug("WM8960 PLL: N=%x K=%x pre_div=%d\n",1205 pll_div->n, pll_div->k, pll_div->pre_div);1206 1207 return 0;1208}1209 1210static int wm8960_set_pll(struct snd_soc_component *component,1211 unsigned int freq_in, unsigned int freq_out)1212{1213 u16 reg;1214 static struct _pll_div pll_div;1215 int ret;1216 1217 if (freq_in && freq_out) {1218 ret = pll_factors(freq_in, freq_out, &pll_div);1219 if (ret != 0)1220 return ret;1221 }1222 1223 /* Disable the PLL: even if we are changing the frequency the1224 * PLL needs to be disabled while we do so. */1225 snd_soc_component_update_bits(component, WM8960_CLOCK1, 0x1, 0);1226 snd_soc_component_update_bits(component, WM8960_POWER2, 0x1, 0);1227 1228 if (!freq_in || !freq_out)1229 return 0;1230 1231 reg = snd_soc_component_read(component, WM8960_PLL1) & ~0x3f;1232 reg |= pll_div.pre_div << 4;1233 reg |= pll_div.n;1234 1235 if (pll_div.k) {1236 reg |= 0x20;1237 1238 snd_soc_component_write(component, WM8960_PLL2, (pll_div.k >> 16) & 0xff);1239 snd_soc_component_write(component, WM8960_PLL3, (pll_div.k >> 8) & 0xff);1240 snd_soc_component_write(component, WM8960_PLL4, pll_div.k & 0xff);1241 }1242 snd_soc_component_write(component, WM8960_PLL1, reg);1243 1244 /* Turn it on */1245 snd_soc_component_update_bits(component, WM8960_POWER2, 0x1, 0x1);1246 msleep(250);1247 snd_soc_component_update_bits(component, WM8960_CLOCK1, 0x1, 0x1);1248 1249 return 0;1250}1251 1252static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,1253 int source, unsigned int freq_in, unsigned int freq_out)1254{1255 struct snd_soc_component *component = codec_dai->component;1256 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);1257 1258 wm8960->freq_in = freq_in;1259 1260 if (pll_id == WM8960_SYSCLK_AUTO)1261 return 0;1262 1263 return wm8960_set_pll(component, freq_in, freq_out);1264}1265 1266static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,1267 int div_id, int div)1268{1269 struct snd_soc_component *component = codec_dai->component;1270 u16 reg;1271 1272 switch (div_id) {1273 case WM8960_SYSCLKDIV:1274 reg = snd_soc_component_read(component, WM8960_CLOCK1) & 0x1f9;1275 snd_soc_component_write(component, WM8960_CLOCK1, reg | div);1276 break;1277 case WM8960_DACDIV:1278 reg = snd_soc_component_read(component, WM8960_CLOCK1) & 0x1c7;1279 snd_soc_component_write(component, WM8960_CLOCK1, reg | div);1280 break;1281 case WM8960_OPCLKDIV:1282 reg = snd_soc_component_read(component, WM8960_PLL1) & 0x03f;1283 snd_soc_component_write(component, WM8960_PLL1, reg | div);1284 break;1285 case WM8960_DCLKDIV:1286 reg = snd_soc_component_read(component, WM8960_CLOCK2) & 0x03f;1287 snd_soc_component_write(component, WM8960_CLOCK2, reg | div);1288 break;1289 case WM8960_TOCLKSEL:1290 reg = snd_soc_component_read(component, WM8960_ADDCTL1) & 0x1fd;1291 snd_soc_component_write(component, WM8960_ADDCTL1, reg | div);1292 break;1293 default:1294 return -EINVAL;1295 }1296 1297 return 0;1298}1299 1300static int wm8960_set_bias_level(struct snd_soc_component *component,1301 enum snd_soc_bias_level level)1302{1303 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);1304 1305 return wm8960->set_bias_level(component, level);1306}1307 1308static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,1309 unsigned int freq, int dir)1310{1311 struct snd_soc_component *component = dai->component;1312 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);1313 1314 switch (clk_id) {1315 case WM8960_SYSCLK_MCLK:1316 snd_soc_component_update_bits(component, WM8960_CLOCK1,1317 0x1, WM8960_SYSCLK_MCLK);1318 break;1319 case WM8960_SYSCLK_PLL:1320 snd_soc_component_update_bits(component, WM8960_CLOCK1,1321 0x1, WM8960_SYSCLK_PLL);1322 break;1323 case WM8960_SYSCLK_AUTO:1324 break;1325 default:1326 return -EINVAL;1327 }1328 1329 wm8960->sysclk = freq;1330 wm8960->clk_id = clk_id;1331 1332 return 0;1333}1334 1335#define WM8960_RATES SNDRV_PCM_RATE_8000_480001336 1337#define WM8960_FORMATS \1338 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \1339 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)1340 1341static const struct snd_soc_dai_ops wm8960_dai_ops = {1342 .hw_params = wm8960_hw_params,1343 .hw_free = wm8960_hw_free,1344 .mute_stream = wm8960_mute,1345 .set_fmt = wm8960_set_dai_fmt,1346 .set_clkdiv = wm8960_set_dai_clkdiv,1347 .set_pll = wm8960_set_dai_pll,1348 .set_sysclk = wm8960_set_dai_sysclk,1349 .no_capture_mute = 1,1350};1351 1352static struct snd_soc_dai_driver wm8960_dai = {1353 .name = "wm8960-hifi",1354 .playback = {1355 .stream_name = "Playback",1356 .channels_min = 1,1357 .channels_max = 2,1358 .rates = WM8960_RATES,1359 .formats = WM8960_FORMATS,},1360 .capture = {1361 .stream_name = "Capture",1362 .channels_min = 1,1363 .channels_max = 2,1364 .rates = WM8960_RATES,1365 .formats = WM8960_FORMATS,},1366 .ops = &wm8960_dai_ops,1367 .symmetric_rate = 1,1368};1369 1370static int wm8960_probe(struct snd_soc_component *component)1371{1372 struct wm8960_priv *wm8960 = snd_soc_component_get_drvdata(component);1373 struct wm8960_data *pdata = &wm8960->pdata;1374 1375 if (pdata->capless)1376 wm8960->set_bias_level = wm8960_set_bias_level_capless;1377 else1378 wm8960->set_bias_level = wm8960_set_bias_level_out3;1379 1380 snd_soc_add_component_controls(component, wm8960_snd_controls,1381 ARRAY_SIZE(wm8960_snd_controls));1382 wm8960_add_widgets(component);1383 1384 return 0;1385}1386 1387static const struct snd_soc_component_driver soc_component_dev_wm8960 = {1388 .probe = wm8960_probe,1389 .set_bias_level = wm8960_set_bias_level,1390 .suspend_bias_off = 1,1391 .idle_bias_on = 1,1392 .use_pmdown_time = 1,1393 .endianness = 1,1394};1395 1396static const struct regmap_config wm8960_regmap = {1397 .reg_bits = 7,1398 .val_bits = 9,1399 .max_register = WM8960_PLL4,1400 1401 .reg_defaults = wm8960_reg_defaults,1402 .num_reg_defaults = ARRAY_SIZE(wm8960_reg_defaults),1403 .cache_type = REGCACHE_MAPLE,1404 1405 .volatile_reg = wm8960_volatile,1406};1407 1408static void wm8960_set_pdata_from_of(struct i2c_client *i2c,1409 struct wm8960_data *pdata)1410{1411 const struct device_node *np = i2c->dev.of_node;1412 1413 if (of_property_read_bool(np, "wlf,capless"))1414 pdata->capless = true;1415 1416 if (of_property_read_bool(np, "wlf,shared-lrclk"))1417 pdata->shared_lrclk = true;1418 1419 of_property_read_u32_array(np, "wlf,gpio-cfg", pdata->gpio_cfg,1420 ARRAY_SIZE(pdata->gpio_cfg));1421 1422 of_property_read_u32_array(np, "wlf,hp-cfg", pdata->hp_cfg,1423 ARRAY_SIZE(pdata->hp_cfg));1424}1425 1426static int wm8960_i2c_probe(struct i2c_client *i2c)1427{1428 struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);1429 struct wm8960_priv *wm8960;1430 unsigned int i;1431 int ret;1432 u8 val;1433 1434 wm8960 = devm_kzalloc(&i2c->dev, sizeof(struct wm8960_priv),1435 GFP_KERNEL);1436 if (wm8960 == NULL)1437 return -ENOMEM;1438 1439 wm8960->mclk = devm_clk_get(&i2c->dev, "mclk");1440 if (IS_ERR(wm8960->mclk)) {1441 if (PTR_ERR(wm8960->mclk) == -EPROBE_DEFER)1442 return -EPROBE_DEFER;1443 } else {1444 ret = clk_get_rate(wm8960->mclk);1445 if (ret >= 0) {1446 wm8960->freq_in = ret;1447 } else {1448 dev_err(&i2c->dev, "Failed to read MCLK rate: %d\n",1449 ret);1450 }1451 }1452 1453 for (i = 0; i < ARRAY_SIZE(wm8960->supplies); i++)1454 wm8960->supplies[i].supply = wm8960_supply_names[i];1455 1456 ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8960->supplies),1457 wm8960->supplies);1458 if (ret < 0) {1459 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);1460 return ret;1461 }1462 1463 ret = regulator_bulk_enable(ARRAY_SIZE(wm8960->supplies),1464 wm8960->supplies);1465 if (ret < 0) {1466 dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);1467 return ret;1468 }1469 1470 wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap);1471 if (IS_ERR(wm8960->regmap)) {1472 ret = PTR_ERR(wm8960->regmap);1473 goto bulk_disable;1474 }1475 1476 if (pdata)1477 memcpy(&wm8960->pdata, pdata, sizeof(struct wm8960_data));1478 else if (i2c->dev.of_node)1479 wm8960_set_pdata_from_of(i2c, &wm8960->pdata);1480 1481 ret = i2c_master_recv(i2c, &val, sizeof(val));1482 if (ret >= 0) {1483 dev_err(&i2c->dev, "Not wm8960, wm8960 reg can not read by i2c\n");1484 ret = -EINVAL;1485 goto bulk_disable;1486 }1487 1488 ret = wm8960_reset(wm8960->regmap);1489 if (ret != 0) {1490 dev_err(&i2c->dev, "Failed to issue reset\n");1491 goto bulk_disable;1492 }1493 1494 if (wm8960->pdata.shared_lrclk) {1495 ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2,1496 0x4, 0x4);1497 if (ret != 0) {1498 dev_err(&i2c->dev, "Failed to enable LRCM: %d\n",1499 ret);1500 goto bulk_disable;1501 }1502 }1503 1504 /* Latch the update bits */1505 regmap_update_bits(wm8960->regmap, WM8960_LINVOL, 0x100, 0x100);1506 regmap_update_bits(wm8960->regmap, WM8960_RINVOL, 0x100, 0x100);1507 regmap_update_bits(wm8960->regmap, WM8960_LADC, 0x100, 0x100);1508 regmap_update_bits(wm8960->regmap, WM8960_RADC, 0x100, 0x100);1509 regmap_update_bits(wm8960->regmap, WM8960_LDAC, 0x100, 0x100);1510 regmap_update_bits(wm8960->regmap, WM8960_RDAC, 0x100, 0x100);1511 regmap_update_bits(wm8960->regmap, WM8960_LOUT1, 0x100, 0x100);1512 regmap_update_bits(wm8960->regmap, WM8960_ROUT1, 0x100, 0x100);1513 regmap_update_bits(wm8960->regmap, WM8960_LOUT2, 0x100, 0x100);1514 regmap_update_bits(wm8960->regmap, WM8960_ROUT2, 0x100, 0x100);1515 1516 /* ADCLRC pin configured as GPIO. */1517 regmap_update_bits(wm8960->regmap, WM8960_IFACE2, 1 << 6,1518 wm8960->pdata.gpio_cfg[0] << 6);1519 regmap_update_bits(wm8960->regmap, WM8960_ADDCTL4, 0xF << 4,1520 wm8960->pdata.gpio_cfg[1] << 4);1521 1522 /* Enable headphone jack detect */1523 regmap_update_bits(wm8960->regmap, WM8960_ADDCTL4, 3 << 2,1524 wm8960->pdata.hp_cfg[0] << 2);1525 regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, 3 << 5,1526 wm8960->pdata.hp_cfg[1] << 5);1527 regmap_update_bits(wm8960->regmap, WM8960_ADDCTL1, 3,1528 wm8960->pdata.hp_cfg[2]);1529 1530 i2c_set_clientdata(i2c, wm8960);1531 1532 ret = devm_snd_soc_register_component(&i2c->dev,1533 &soc_component_dev_wm8960, &wm8960_dai, 1);1534 if (ret)1535 goto bulk_disable;1536 1537 return 0;1538 1539bulk_disable:1540 regulator_bulk_disable(ARRAY_SIZE(wm8960->supplies), wm8960->supplies);1541 return ret;1542}1543 1544static void wm8960_i2c_remove(struct i2c_client *client)1545{1546 struct wm8960_priv *wm8960 = i2c_get_clientdata(client);1547 1548 regulator_bulk_disable(ARRAY_SIZE(wm8960->supplies), wm8960->supplies);1549}1550 1551static const struct i2c_device_id wm8960_i2c_id[] = {1552 { "wm8960" },1553 { }1554};1555MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);1556 1557#if defined(CONFIG_OF)1558static const struct of_device_id wm8960_of_match[] = {1559 { .compatible = "wlf,wm8960", },1560 { }1561};1562MODULE_DEVICE_TABLE(of, wm8960_of_match);1563#endif1564 1565#if defined(CONFIG_ACPI)1566static const struct acpi_device_id wm8960_acpi_match[] = {1567 { "1AEC8960", 0 }, /* Wolfson PCI ID + part ID */1568 { "10138960", 0 }, /* Cirrus Logic PCI ID + part ID */1569 { },1570};1571MODULE_DEVICE_TABLE(acpi, wm8960_acpi_match);1572#endif1573 1574static struct i2c_driver wm8960_i2c_driver = {1575 .driver = {1576 .name = "wm8960",1577 .of_match_table = of_match_ptr(wm8960_of_match),1578 .acpi_match_table = ACPI_PTR(wm8960_acpi_match),1579 },1580 .probe = wm8960_i2c_probe,1581 .remove = wm8960_i2c_remove,1582 .id_table = wm8960_i2c_id,1583};1584 1585module_i2c_driver(wm8960_i2c_driver);1586 1587MODULE_DESCRIPTION("ASoC WM8960 driver");1588MODULE_AUTHOR("Liam Girdwood");1589MODULE_LICENSE("GPL");1590