cs35l45.c (6085f9e6dc1973cf98ee7f5dcf629939e50f1b84) | cs35l45.c (74b14e2850a34740c121cf2758d4181063d4c77c) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2// 3// cs35l45.c - CS35L45 ALSA SoC audio driver 4// 5// Copyright 2019-2022 Cirrus Logic, Inc. 6// 7// Author: James Schulman <james.schulman@cirrus.com> 8 9#include <linux/gpio/consumer.h> 10#include <linux/module.h> 11#include <linux/pm_runtime.h> 12#include <linux/property.h> | 1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2// 3// cs35l45.c - CS35L45 ALSA SoC audio driver 4// 5// Copyright 2019-2022 Cirrus Logic, Inc. 6// 7// Author: James Schulman <james.schulman@cirrus.com> 8 9#include <linux/gpio/consumer.h> 10#include <linux/module.h> 11#include <linux/pm_runtime.h> 12#include <linux/property.h> |
13#include <linux/firmware.h> |
|
13#include <linux/regulator/consumer.h> 14#include <sound/core.h> 15#include <sound/pcm.h> 16#include <sound/pcm_params.h> 17#include <sound/soc.h> 18#include <sound/tlv.h> 19 20#include "cs35l45.h" 21 | 14#include <linux/regulator/consumer.h> 15#include <sound/core.h> 16#include <sound/pcm.h> 17#include <sound/pcm_params.h> 18#include <sound/soc.h> 19#include <sound/tlv.h> 20 21#include "cs35l45.h" 22 |
23static bool cs35l45_check_cspl_mbox_sts(const enum cs35l45_cspl_mboxcmd cmd, 24 enum cs35l45_cspl_mboxstate sts) 25{ 26 switch (cmd) { 27 case CSPL_MBOX_CMD_NONE: 28 case CSPL_MBOX_CMD_UNKNOWN_CMD: 29 return true; 30 case CSPL_MBOX_CMD_PAUSE: 31 case CSPL_MBOX_CMD_OUT_OF_HIBERNATE: 32 return (sts == CSPL_MBOX_STS_PAUSED); 33 case CSPL_MBOX_CMD_RESUME: 34 return (sts == CSPL_MBOX_STS_RUNNING); 35 case CSPL_MBOX_CMD_REINIT: 36 return (sts == CSPL_MBOX_STS_RUNNING); 37 case CSPL_MBOX_CMD_STOP_PRE_REINIT: 38 return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); 39 default: 40 return false; 41 } 42} 43 44static int cs35l45_set_cspl_mbox_cmd(struct cs35l45_private *cs35l45, 45 struct regmap *regmap, 46 const enum cs35l45_cspl_mboxcmd cmd) 47{ 48 unsigned int sts = 0, i; 49 int ret; 50 51 if (!cs35l45->dsp.cs_dsp.running) { 52 dev_err(cs35l45->dev, "DSP not running\n"); 53 return -EPERM; 54 } 55 56 // Set mailbox cmd 57 ret = regmap_write(regmap, CS35L45_DSP_VIRT1_MBOX_1, cmd); 58 if (ret < 0) { 59 if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) 60 dev_err(cs35l45->dev, "Failed to write MBOX: %d\n", ret); 61 return ret; 62 } 63 64 // Read mailbox status and verify it is appropriate for the given cmd 65 for (i = 0; i < 5; i++) { 66 usleep_range(1000, 1100); 67 68 ret = regmap_read(regmap, CS35L45_DSP_MBOX_2, &sts); 69 if (ret < 0) { 70 dev_err(cs35l45->dev, "Failed to read MBOX STS: %d\n", ret); 71 continue; 72 } 73 74 if (!cs35l45_check_cspl_mbox_sts(cmd, sts)) 75 dev_dbg(cs35l45->dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts); 76 else 77 return 0; 78 } 79 80 if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) 81 dev_err(cs35l45->dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); 82 83 return -ENOMSG; 84} 85 |
|
22static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, 23 struct snd_kcontrol *kcontrol, int event) 24{ 25 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 26 struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); 27 28 dev_dbg(cs35l45->dev, "%s event : %x\n", __func__, event); 29 --- 11 unchanged lines hidden (view full) --- 41 break; 42 default: 43 break; 44 } 45 46 return 0; 47} 48 | 86static int cs35l45_global_en_ev(struct snd_soc_dapm_widget *w, 87 struct snd_kcontrol *kcontrol, int event) 88{ 89 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 90 struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); 91 92 dev_dbg(cs35l45->dev, "%s event : %x\n", __func__, event); 93 --- 11 unchanged lines hidden (view full) --- 105 break; 106 default: 107 break; 108 } 109 110 return 0; 111} 112 |
113static int cs35l45_dsp_preload_ev(struct snd_soc_dapm_widget *w, 114 struct snd_kcontrol *kcontrol, int event) 115{ 116 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 117 struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); 118 int ret; 119 120 switch (event) { 121 case SND_SOC_DAPM_PRE_PMU: 122 if (cs35l45->dsp.cs_dsp.booted) 123 return 0; 124 125 return wm_adsp_early_event(w, kcontrol, event); 126 case SND_SOC_DAPM_POST_PMU: 127 if (cs35l45->dsp.cs_dsp.running) 128 return 0; 129 130 regmap_set_bits(cs35l45->regmap, CS35L45_PWRMGT_CTL, 131 CS35L45_MEM_RDY_MASK); 132 133 return wm_adsp_event(w, kcontrol, event); 134 case SND_SOC_DAPM_PRE_PMD: 135 if (cs35l45->dsp.preloaded) 136 return 0; 137 138 if (cs35l45->dsp.cs_dsp.running) { 139 ret = wm_adsp_event(w, kcontrol, event); 140 if (ret) 141 return ret; 142 } 143 144 return wm_adsp_early_event(w, kcontrol, event); 145 default: 146 return 0; 147 } 148} 149 150static int cs35l45_dsp_audio_ev(struct snd_soc_dapm_widget *w, 151 struct snd_kcontrol *kcontrol, int event) 152{ 153 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 154 struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); 155 156 switch (event) { 157 case SND_SOC_DAPM_POST_PMU: 158 return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, 159 CSPL_MBOX_CMD_RESUME); 160 case SND_SOC_DAPM_PRE_PMD: 161 return cs35l45_set_cspl_mbox_cmd(cs35l45, cs35l45->regmap, 162 CSPL_MBOX_CMD_PAUSE); 163 default: 164 return 0; 165 } 166 167 return 0; 168} 169 |
|
49static const char * const cs35l45_asp_tx_txt[] = { 50 "Zero", "ASP_RX1", "ASP_RX2", 51 "VMON", "IMON", "ERR_VOL", 52 "VDD_BATTMON", "VDD_BSTMON", | 170static const char * const cs35l45_asp_tx_txt[] = { 171 "Zero", "ASP_RX1", "ASP_RX2", 172 "VMON", "IMON", "ERR_VOL", 173 "VDD_BATTMON", "VDD_BSTMON", |
174 "DSP_TX1", "DSP_TX2", |
|
53 "Interpolator", "IL_TARGET", 54}; 55 56static const unsigned int cs35l45_asp_tx_val[] = { 57 CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, 58 CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, 59 CS35L45_PCM_SRC_VDD_BATTMON, CS35L45_PCM_SRC_VDD_BSTMON, | 175 "Interpolator", "IL_TARGET", 176}; 177 178static const unsigned int cs35l45_asp_tx_val[] = { 179 CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, 180 CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, 181 CS35L45_PCM_SRC_VDD_BATTMON, CS35L45_PCM_SRC_VDD_BSTMON, |
182 CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2, |
|
60 CS35L45_PCM_SRC_INTERPOLATOR, CS35L45_PCM_SRC_IL_TARGET, 61}; 62 63static const struct soc_enum cs35l45_asp_tx_enums[] = { 64 SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX1_INPUT, 0, CS35L45_PCM_SRC_MASK, 65 ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt, 66 cs35l45_asp_tx_val), 67 SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX2_INPUT, 0, CS35L45_PCM_SRC_MASK, --- 5 unchanged lines hidden (view full) --- 73 SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX4_INPUT, 0, CS35L45_PCM_SRC_MASK, 74 ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt, 75 cs35l45_asp_tx_val), 76 SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX5_INPUT, 0, CS35L45_PCM_SRC_MASK, 77 ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt, 78 cs35l45_asp_tx_val), 79}; 80 | 183 CS35L45_PCM_SRC_INTERPOLATOR, CS35L45_PCM_SRC_IL_TARGET, 184}; 185 186static const struct soc_enum cs35l45_asp_tx_enums[] = { 187 SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX1_INPUT, 0, CS35L45_PCM_SRC_MASK, 188 ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt, 189 cs35l45_asp_tx_val), 190 SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX2_INPUT, 0, CS35L45_PCM_SRC_MASK, --- 5 unchanged lines hidden (view full) --- 196 SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX4_INPUT, 0, CS35L45_PCM_SRC_MASK, 197 ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt, 198 cs35l45_asp_tx_val), 199 SOC_VALUE_ENUM_SINGLE(CS35L45_ASPTX5_INPUT, 0, CS35L45_PCM_SRC_MASK, 200 ARRAY_SIZE(cs35l45_asp_tx_txt), cs35l45_asp_tx_txt, 201 cs35l45_asp_tx_val), 202}; 203 |
204static const char * const cs35l45_dsp_rx_txt[] = { 205 "Zero", "ASP_RX1", "ASP_RX2", 206 "VMON", "IMON", "ERR_VOL", 207 "CLASSH_TGT", "VDD_BATTMON", 208 "VDD_BSTMON", "TEMPMON", 209}; 210 211static const unsigned int cs35l45_dsp_rx_val[] = { 212 CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, 213 CS35L45_PCM_SRC_VMON, CS35L45_PCM_SRC_IMON, CS35L45_PCM_SRC_ERR_VOL, 214 CS35L45_PCM_SRC_CLASSH_TGT, CS35L45_PCM_SRC_VDD_BATTMON, 215 CS35L45_PCM_SRC_VDD_BSTMON, CS35L45_PCM_SRC_TEMPMON, 216}; 217 218static const struct soc_enum cs35l45_dsp_rx_enums[] = { 219 SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX1_INPUT, 0, CS35L45_PCM_SRC_MASK, 220 ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, 221 cs35l45_dsp_rx_val), 222 SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX2_INPUT, 0, CS35L45_PCM_SRC_MASK, 223 ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, 224 cs35l45_dsp_rx_val), 225 SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX3_INPUT, 0, CS35L45_PCM_SRC_MASK, 226 ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, 227 cs35l45_dsp_rx_val), 228 SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX4_INPUT, 0, CS35L45_PCM_SRC_MASK, 229 ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, 230 cs35l45_dsp_rx_val), 231 SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX5_INPUT, 0, CS35L45_PCM_SRC_MASK, 232 ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, 233 cs35l45_dsp_rx_val), 234 SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX6_INPUT, 0, CS35L45_PCM_SRC_MASK, 235 ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, 236 cs35l45_dsp_rx_val), 237 SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX7_INPUT, 0, CS35L45_PCM_SRC_MASK, 238 ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, 239 cs35l45_dsp_rx_val), 240 SOC_VALUE_ENUM_SINGLE(CS35L45_DSP1RX8_INPUT, 0, CS35L45_PCM_SRC_MASK, 241 ARRAY_SIZE(cs35l45_dsp_rx_txt), cs35l45_dsp_rx_txt, 242 cs35l45_dsp_rx_val), 243}; 244 |
|
81static const char * const cs35l45_dac_txt[] = { | 245static const char * const cs35l45_dac_txt[] = { |
82 "Zero", "ASP_RX1", "ASP_RX2" | 246 "Zero", "ASP_RX1", "ASP_RX2", "DSP_TX1", "DSP_TX2" |
83}; 84 85static const unsigned int cs35l45_dac_val[] = { | 247}; 248 249static const unsigned int cs35l45_dac_val[] = { |
86 CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2 | 250 CS35L45_PCM_SRC_ZERO, CS35L45_PCM_SRC_ASP_RX1, CS35L45_PCM_SRC_ASP_RX2, 251 CS35L45_PCM_SRC_DSP_TX1, CS35L45_PCM_SRC_DSP_TX2 |
87}; 88 89static const struct soc_enum cs35l45_dacpcm_enums[] = { 90 SOC_VALUE_ENUM_SINGLE(CS35L45_DACPCM1_INPUT, 0, CS35L45_PCM_SRC_MASK, 91 ARRAY_SIZE(cs35l45_dac_txt), cs35l45_dac_txt, 92 cs35l45_dac_val), 93}; 94 95static const struct snd_kcontrol_new cs35l45_asp_muxes[] = { 96 SOC_DAPM_ENUM("ASP_TX1 Source", cs35l45_asp_tx_enums[0]), 97 SOC_DAPM_ENUM("ASP_TX2 Source", cs35l45_asp_tx_enums[1]), 98 SOC_DAPM_ENUM("ASP_TX3 Source", cs35l45_asp_tx_enums[2]), 99 SOC_DAPM_ENUM("ASP_TX4 Source", cs35l45_asp_tx_enums[3]), 100 SOC_DAPM_ENUM("ASP_TX5 Source", cs35l45_asp_tx_enums[4]), 101}; 102 | 252}; 253 254static const struct soc_enum cs35l45_dacpcm_enums[] = { 255 SOC_VALUE_ENUM_SINGLE(CS35L45_DACPCM1_INPUT, 0, CS35L45_PCM_SRC_MASK, 256 ARRAY_SIZE(cs35l45_dac_txt), cs35l45_dac_txt, 257 cs35l45_dac_val), 258}; 259 260static const struct snd_kcontrol_new cs35l45_asp_muxes[] = { 261 SOC_DAPM_ENUM("ASP_TX1 Source", cs35l45_asp_tx_enums[0]), 262 SOC_DAPM_ENUM("ASP_TX2 Source", cs35l45_asp_tx_enums[1]), 263 SOC_DAPM_ENUM("ASP_TX3 Source", cs35l45_asp_tx_enums[2]), 264 SOC_DAPM_ENUM("ASP_TX4 Source", cs35l45_asp_tx_enums[3]), 265 SOC_DAPM_ENUM("ASP_TX5 Source", cs35l45_asp_tx_enums[4]), 266}; 267 |
268static const struct snd_kcontrol_new cs35l45_dsp_muxes[] = { 269 SOC_DAPM_ENUM("DSP_RX1 Source", cs35l45_dsp_rx_enums[0]), 270 SOC_DAPM_ENUM("DSP_RX2 Source", cs35l45_dsp_rx_enums[1]), 271 SOC_DAPM_ENUM("DSP_RX3 Source", cs35l45_dsp_rx_enums[2]), 272 SOC_DAPM_ENUM("DSP_RX4 Source", cs35l45_dsp_rx_enums[3]), 273 SOC_DAPM_ENUM("DSP_RX5 Source", cs35l45_dsp_rx_enums[4]), 274 SOC_DAPM_ENUM("DSP_RX6 Source", cs35l45_dsp_rx_enums[5]), 275 SOC_DAPM_ENUM("DSP_RX7 Source", cs35l45_dsp_rx_enums[6]), 276 SOC_DAPM_ENUM("DSP_RX8 Source", cs35l45_dsp_rx_enums[7]), 277}; 278 |
|
103static const struct snd_kcontrol_new cs35l45_dac_muxes[] = { 104 SOC_DAPM_ENUM("DACPCM1 Source", cs35l45_dacpcm_enums[0]), 105}; 106 107static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { | 279static const struct snd_kcontrol_new cs35l45_dac_muxes[] = { 280 SOC_DAPM_ENUM("DACPCM1 Source", cs35l45_dacpcm_enums[0]), 281}; 282 283static const struct snd_soc_dapm_widget cs35l45_dapm_widgets[] = { |
284 SND_SOC_DAPM_SPK("DSP1 Preload", NULL), 285 SND_SOC_DAPM_SUPPLY_S("DSP1 Preloader", 100, SND_SOC_NOPM, 0, 0, 286 cs35l45_dsp_preload_ev, 287 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 288 SND_SOC_DAPM_OUT_DRV_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, 289 cs35l45_dsp_audio_ev, 290 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
|
108 SND_SOC_DAPM_SUPPLY("GLOBAL_EN", SND_SOC_NOPM, 0, 0, 109 cs35l45_global_en_ev, 110 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 111 SND_SOC_DAPM_SUPPLY("ASP_EN", CS35L45_BLOCK_ENABLES2, CS35L45_ASP_EN_SHIFT, 0, NULL, 0), 112 113 SND_SOC_DAPM_SIGGEN("VMON_SRC"), 114 SND_SOC_DAPM_SIGGEN("IMON_SRC"), 115 SND_SOC_DAPM_SIGGEN("VDD_BATTMON_SRC"), --- 18 unchanged lines hidden (view full) --- 134 SND_SOC_DAPM_AIF_OUT("ASP_TX5", NULL, 3, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX5_EN_SHIFT, 0), 135 136 SND_SOC_DAPM_MUX("ASP_TX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[0]), 137 SND_SOC_DAPM_MUX("ASP_TX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[1]), 138 SND_SOC_DAPM_MUX("ASP_TX3 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[2]), 139 SND_SOC_DAPM_MUX("ASP_TX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[3]), 140 SND_SOC_DAPM_MUX("ASP_TX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[4]), 141 | 291 SND_SOC_DAPM_SUPPLY("GLOBAL_EN", SND_SOC_NOPM, 0, 0, 292 cs35l45_global_en_ev, 293 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 294 SND_SOC_DAPM_SUPPLY("ASP_EN", CS35L45_BLOCK_ENABLES2, CS35L45_ASP_EN_SHIFT, 0, NULL, 0), 295 296 SND_SOC_DAPM_SIGGEN("VMON_SRC"), 297 SND_SOC_DAPM_SIGGEN("IMON_SRC"), 298 SND_SOC_DAPM_SIGGEN("VDD_BATTMON_SRC"), --- 18 unchanged lines hidden (view full) --- 317 SND_SOC_DAPM_AIF_OUT("ASP_TX5", NULL, 3, CS35L45_ASP_ENABLES1, CS35L45_ASP_TX5_EN_SHIFT, 0), 318 319 SND_SOC_DAPM_MUX("ASP_TX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[0]), 320 SND_SOC_DAPM_MUX("ASP_TX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[1]), 321 SND_SOC_DAPM_MUX("ASP_TX3 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[2]), 322 SND_SOC_DAPM_MUX("ASP_TX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[3]), 323 SND_SOC_DAPM_MUX("ASP_TX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_asp_muxes[4]), 324 |
325 SND_SOC_DAPM_MUX("DSP_RX1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[0]), 326 SND_SOC_DAPM_MUX("DSP_RX2 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[1]), 327 SND_SOC_DAPM_MUX("DSP_RX3 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[2]), 328 SND_SOC_DAPM_MUX("DSP_RX4 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[3]), 329 SND_SOC_DAPM_MUX("DSP_RX5 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[4]), 330 SND_SOC_DAPM_MUX("DSP_RX6 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[5]), 331 SND_SOC_DAPM_MUX("DSP_RX7 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[6]), 332 SND_SOC_DAPM_MUX("DSP_RX8 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dsp_muxes[7]), 333 |
|
142 SND_SOC_DAPM_MUX("DACPCM1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dac_muxes[0]), 143 144 SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), 145 146 SND_SOC_DAPM_OUTPUT("SPK"), 147}; 148 149#define CS35L45_ASP_MUX_ROUTE(name) \ 150 { name" Source", "ASP_RX1", "ASP_RX1" }, \ 151 { name" Source", "ASP_RX2", "ASP_RX2" }, \ | 334 SND_SOC_DAPM_MUX("DACPCM1 Source", SND_SOC_NOPM, 0, 0, &cs35l45_dac_muxes[0]), 335 336 SND_SOC_DAPM_OUT_DRV("AMP", SND_SOC_NOPM, 0, 0, NULL, 0), 337 338 SND_SOC_DAPM_OUTPUT("SPK"), 339}; 340 341#define CS35L45_ASP_MUX_ROUTE(name) \ 342 { name" Source", "ASP_RX1", "ASP_RX1" }, \ 343 { name" Source", "ASP_RX2", "ASP_RX2" }, \ |
344 { name" Source", "DSP_TX1", "DSP1" }, \ 345 { name" Source", "DSP_TX2", "DSP1" }, \ |
|
152 { name" Source", "VMON", "VMON" }, \ 153 { name" Source", "IMON", "IMON" }, \ 154 { name" Source", "ERR_VOL", "ERR_VOL" }, \ 155 { name" Source", "VDD_BATTMON", "VDD_BATTMON" }, \ 156 { name" Source", "VDD_BSTMON", "VDD_BSTMON" }, \ 157 { name" Source", "Interpolator", "AMP_INTP" }, \ 158 { name" Source", "IL_TARGET", "IL_TARGET" } 159 | 346 { name" Source", "VMON", "VMON" }, \ 347 { name" Source", "IMON", "IMON" }, \ 348 { name" Source", "ERR_VOL", "ERR_VOL" }, \ 349 { name" Source", "VDD_BATTMON", "VDD_BATTMON" }, \ 350 { name" Source", "VDD_BSTMON", "VDD_BSTMON" }, \ 351 { name" Source", "Interpolator", "AMP_INTP" }, \ 352 { name" Source", "IL_TARGET", "IL_TARGET" } 353 |
160#define CS35L45_DAC_MUX_ROUTE(name) \ | 354#define CS35L45_DSP_MUX_ROUTE(name) \ |
161 { name" Source", "ASP_RX1", "ASP_RX1" }, \ 162 { name" Source", "ASP_RX2", "ASP_RX2" } 163 | 355 { name" Source", "ASP_RX1", "ASP_RX1" }, \ 356 { name" Source", "ASP_RX2", "ASP_RX2" } 357 |
358#define CS35L45_DAC_MUX_ROUTE(name) \ 359 { name" Source", "ASP_RX1", "ASP_RX1" }, \ 360 { name" Source", "ASP_RX2", "ASP_RX2" }, \ 361 { name" Source", "DSP_TX1", "DSP1" }, \ 362 { name" Source", "DSP_TX2", "DSP1" } 363 |
|
164static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { 165 /* Feedback */ 166 { "VMON", NULL, "VMON_SRC" }, 167 { "IMON", NULL, "IMON_SRC" }, 168 { "VDD_BATTMON", NULL, "VDD_BATTMON_SRC" }, 169 { "VDD_BSTMON", NULL, "VDD_BSTMON_SRC" }, 170 171 { "Capture", NULL, "ASP_TX1"}, --- 27 unchanged lines hidden (view full) --- 199 { "ASP_RX1", NULL, "Playback" }, 200 { "ASP_RX2", NULL, "Playback" }, 201 { "ASP_RX1", NULL, "ASP_EN" }, 202 { "ASP_RX2", NULL, "ASP_EN" }, 203 204 { "AMP", NULL, "DACPCM1 Source"}, 205 { "AMP", NULL, "GLOBAL_EN"}, 206 | 364static const struct snd_soc_dapm_route cs35l45_dapm_routes[] = { 365 /* Feedback */ 366 { "VMON", NULL, "VMON_SRC" }, 367 { "IMON", NULL, "IMON_SRC" }, 368 { "VDD_BATTMON", NULL, "VDD_BATTMON_SRC" }, 369 { "VDD_BSTMON", NULL, "VDD_BSTMON_SRC" }, 370 371 { "Capture", NULL, "ASP_TX1"}, --- 27 unchanged lines hidden (view full) --- 399 { "ASP_RX1", NULL, "Playback" }, 400 { "ASP_RX2", NULL, "Playback" }, 401 { "ASP_RX1", NULL, "ASP_EN" }, 402 { "ASP_RX2", NULL, "ASP_EN" }, 403 404 { "AMP", NULL, "DACPCM1 Source"}, 405 { "AMP", NULL, "GLOBAL_EN"}, 406 |
407 CS35L45_DSP_MUX_ROUTE("DSP_RX1"), 408 CS35L45_DSP_MUX_ROUTE("DSP_RX2"), 409 CS35L45_DSP_MUX_ROUTE("DSP_RX3"), 410 CS35L45_DSP_MUX_ROUTE("DSP_RX4"), 411 CS35L45_DSP_MUX_ROUTE("DSP_RX5"), 412 CS35L45_DSP_MUX_ROUTE("DSP_RX6"), 413 CS35L45_DSP_MUX_ROUTE("DSP_RX7"), 414 CS35L45_DSP_MUX_ROUTE("DSP_RX8"), 415 416 {"DSP1", NULL, "DSP_RX1 Source"}, 417 {"DSP1", NULL, "DSP_RX2 Source"}, 418 {"DSP1", NULL, "DSP_RX3 Source"}, 419 {"DSP1", NULL, "DSP_RX4 Source"}, 420 {"DSP1", NULL, "DSP_RX5 Source"}, 421 {"DSP1", NULL, "DSP_RX6 Source"}, 422 {"DSP1", NULL, "DSP_RX7 Source"}, 423 {"DSP1", NULL, "DSP_RX8 Source"}, 424 425 {"DSP1 Preload", NULL, "DSP1 Preloader"}, 426 {"DSP1", NULL, "DSP1 Preloader"}, 427 |
|
207 CS35L45_DAC_MUX_ROUTE("DACPCM1"), 208 209 { "SPK", NULL, "AMP"}, 210}; 211 212static const DECLARE_TLV_DB_SCALE(cs35l45_dig_pcm_vol_tlv, -10225, 25, true); 213 214static const struct snd_kcontrol_new cs35l45_controls[] = { 215 /* Ignore bit 0: it is beyond the resolution of TLV_DB_SCALE */ 216 SOC_SINGLE_S_TLV("Digital PCM Volume", 217 CS35L45_AMP_PCM_CONTROL, 218 CS35L45_AMP_VOL_PCM_SHIFT + 1, 219 -409, 48, 220 (CS35L45_AMP_VOL_PCM_WIDTH - 1) - 1, 221 0, cs35l45_dig_pcm_vol_tlv), | 428 CS35L45_DAC_MUX_ROUTE("DACPCM1"), 429 430 { "SPK", NULL, "AMP"}, 431}; 432 433static const DECLARE_TLV_DB_SCALE(cs35l45_dig_pcm_vol_tlv, -10225, 25, true); 434 435static const struct snd_kcontrol_new cs35l45_controls[] = { 436 /* Ignore bit 0: it is beyond the resolution of TLV_DB_SCALE */ 437 SOC_SINGLE_S_TLV("Digital PCM Volume", 438 CS35L45_AMP_PCM_CONTROL, 439 CS35L45_AMP_VOL_PCM_SHIFT + 1, 440 -409, 48, 441 (CS35L45_AMP_VOL_PCM_WIDTH - 1) - 1, 442 0, cs35l45_dig_pcm_vol_tlv), |
443 WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), 444 WM_ADSP_FW_CONTROL("DSP1", 0), |
|
222}; 223 224static int cs35l45_set_pll(struct cs35l45_private *cs35l45, unsigned int freq) 225{ 226 unsigned int val; 227 int freq_id; 228 229 freq_id = cs35l45_get_clk_freq_id(freq); --- 254 unchanged lines hidden (view full) --- 484 .formats = CS35L45_FORMATS, 485 }, 486 .symmetric_rate = true, 487 .symmetric_sample_bits = true, 488 .ops = &cs35l45_asp_dai_ops, 489 }, 490}; 491 | 445}; 446 447static int cs35l45_set_pll(struct cs35l45_private *cs35l45, unsigned int freq) 448{ 449 unsigned int val; 450 int freq_id; 451 452 freq_id = cs35l45_get_clk_freq_id(freq); --- 254 unchanged lines hidden (view full) --- 707 .formats = CS35L45_FORMATS, 708 }, 709 .symmetric_rate = true, 710 .symmetric_sample_bits = true, 711 .ops = &cs35l45_asp_dai_ops, 712 }, 713}; 714 |
715static int cs35l45_component_probe(struct snd_soc_component *component) 716{ 717 struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); 718 719 return wm_adsp2_component_probe(&cs35l45->dsp, component); 720} 721 722static void cs35l45_component_remove(struct snd_soc_component *component) 723{ 724 struct cs35l45_private *cs35l45 = snd_soc_component_get_drvdata(component); 725 726 wm_adsp2_component_remove(&cs35l45->dsp, component); 727} 728 |
|
492static const struct snd_soc_component_driver cs35l45_component = { | 729static const struct snd_soc_component_driver cs35l45_component = { |
730 .probe = cs35l45_component_probe, 731 .remove = cs35l45_component_remove, 732 |
|
493 .dapm_widgets = cs35l45_dapm_widgets, 494 .num_dapm_widgets = ARRAY_SIZE(cs35l45_dapm_widgets), 495 496 .dapm_routes = cs35l45_dapm_routes, 497 .num_dapm_routes = ARRAY_SIZE(cs35l45_dapm_routes), 498 499 .controls = cs35l45_controls, 500 .num_controls = ARRAY_SIZE(cs35l45_controls), --- 101 unchanged lines hidden (view full) --- 602 regmap_update_bits(cs35l45->regmap, CS35L45_ASP_CONTROL3, 603 CS35L45_ASP_DOUT_HIZ_CTRL_MASK, 604 val << CS35L45_ASP_DOUT_HIZ_CTRL_SHIFT); 605 } 606 607 return 0; 608} 609 | 733 .dapm_widgets = cs35l45_dapm_widgets, 734 .num_dapm_widgets = ARRAY_SIZE(cs35l45_dapm_widgets), 735 736 .dapm_routes = cs35l45_dapm_routes, 737 .num_dapm_routes = ARRAY_SIZE(cs35l45_dapm_routes), 738 739 .controls = cs35l45_controls, 740 .num_controls = ARRAY_SIZE(cs35l45_controls), --- 101 unchanged lines hidden (view full) --- 842 regmap_update_bits(cs35l45->regmap, CS35L45_ASP_CONTROL3, 843 CS35L45_ASP_DOUT_HIZ_CTRL_MASK, 844 val << CS35L45_ASP_DOUT_HIZ_CTRL_SHIFT); 845 } 846 847 return 0; 848} 849 |
850static int cs35l45_dsp_virt2_mbox3_irq_handle(struct cs35l45_private *cs35l45, 851 const unsigned int cmd, 852 unsigned int data) 853{ 854 static char *speak_status = "Unknown"; 855 856 switch (cmd) { 857 case EVENT_SPEAKER_STATUS: 858 switch (data) { 859 case 1: 860 speak_status = "All Clear"; 861 break; 862 case 2: 863 speak_status = "Open Circuit"; 864 break; 865 case 4: 866 speak_status = "Short Circuit"; 867 break; 868 } 869 870 dev_info(cs35l45->dev, "MBOX event (SPEAKER_STATUS): %s\n", 871 speak_status); 872 break; 873 case EVENT_BOOT_DONE: 874 dev_dbg(cs35l45->dev, "MBOX event (BOOT_DONE)\n"); 875 break; 876 default: 877 dev_err(cs35l45->dev, "MBOX event not supported %u\n", cmd); 878 return -EINVAL; 879 } 880 881 return 0; 882} 883 884static irqreturn_t cs35l45_dsp_virt2_mbox_cb(int irq, void *data) 885{ 886 struct cs35l45_private *cs35l45 = data; 887 unsigned int mbox_val; 888 int ret = 0; 889 890 ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_3, &mbox_val); 891 if (!ret && mbox_val) 892 ret = cs35l45_dsp_virt2_mbox3_irq_handle(cs35l45, mbox_val & CS35L45_MBOX3_CMD_MASK, 893 (mbox_val & CS35L45_MBOX3_DATA_MASK) >> CS35L45_MBOX3_DATA_SHIFT); 894 895 /* Handle DSP trace log IRQ */ 896 ret = regmap_read(cs35l45->regmap, CS35L45_DSP_VIRT2_MBOX_4, &mbox_val); 897 if (!ret && mbox_val != 0) { 898 dev_err(cs35l45->dev, "Spurious DSP MBOX4 IRQ\n"); 899 } 900 901 return IRQ_RETVAL(ret); 902} 903 |
|
610static irqreturn_t cs35l45_pll_unlock(int irq, void *data) 611{ 612 struct cs35l45_private *cs35l45 = data; 613 614 dev_dbg(cs35l45->dev, "PLL unlock detected!"); 615 616 return IRQ_HANDLED; 617} --- 16 unchanged lines hidden (view full) --- 634 CS35L45_IRQ(BST_UVP_ERR, "Boost undervoltage error", cs35l45_spk_safe_err), 635 CS35L45_IRQ(TEMP_ERR, "Overtemperature error", cs35l45_spk_safe_err), 636 CS35L45_IRQ(AMP_CAL_ERR, "Amplifier calibration error", cs35l45_spk_safe_err), 637 CS35L45_IRQ(UVLO_VDDLV_ERR, "LV threshold detector error", cs35l45_spk_safe_err), 638 CS35L45_IRQ(GLOBAL_ERROR, "Global error", cs35l45_spk_safe_err), 639 CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err), 640 CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock), 641 CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock), | 904static irqreturn_t cs35l45_pll_unlock(int irq, void *data) 905{ 906 struct cs35l45_private *cs35l45 = data; 907 908 dev_dbg(cs35l45->dev, "PLL unlock detected!"); 909 910 return IRQ_HANDLED; 911} --- 16 unchanged lines hidden (view full) --- 928 CS35L45_IRQ(BST_UVP_ERR, "Boost undervoltage error", cs35l45_spk_safe_err), 929 CS35L45_IRQ(TEMP_ERR, "Overtemperature error", cs35l45_spk_safe_err), 930 CS35L45_IRQ(AMP_CAL_ERR, "Amplifier calibration error", cs35l45_spk_safe_err), 931 CS35L45_IRQ(UVLO_VDDLV_ERR, "LV threshold detector error", cs35l45_spk_safe_err), 932 CS35L45_IRQ(GLOBAL_ERROR, "Global error", cs35l45_spk_safe_err), 933 CS35L45_IRQ(DSP_WDT_EXPIRE, "DSP Watchdog Timer", cs35l45_spk_safe_err), 934 CS35L45_IRQ(PLL_UNLOCK_FLAG_RISE, "PLL unlock", cs35l45_pll_unlock), 935 CS35L45_IRQ(PLL_LOCK_FLAG, "PLL lock", cs35l45_pll_lock), |
936 CS35L45_IRQ(DSP_VIRT2_MBOX, "DSP virtual MBOX 2 write flag", cs35l45_dsp_virt2_mbox_cb), |
|
642}; 643 644static irqreturn_t cs35l45_spk_safe_err(int irq, void *data) 645{ 646 struct cs35l45_private *cs35l45 = data; 647 int i; 648 649 i = irq - regmap_irq_get_virq(cs35l45->irq_data, 0); --- 10 unchanged lines hidden (view full) --- 660 CS35L45_REG_IRQ(IRQ1_EINT_1, BST_UVP_ERR), 661 CS35L45_REG_IRQ(IRQ1_EINT_1, TEMP_ERR), 662 CS35L45_REG_IRQ(IRQ1_EINT_3, AMP_CAL_ERR), 663 CS35L45_REG_IRQ(IRQ1_EINT_18, UVLO_VDDLV_ERR), 664 CS35L45_REG_IRQ(IRQ1_EINT_18, GLOBAL_ERROR), 665 CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE), 666 CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE), 667 CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG), | 937}; 938 939static irqreturn_t cs35l45_spk_safe_err(int irq, void *data) 940{ 941 struct cs35l45_private *cs35l45 = data; 942 int i; 943 944 i = irq - regmap_irq_get_virq(cs35l45->irq_data, 0); --- 10 unchanged lines hidden (view full) --- 955 CS35L45_REG_IRQ(IRQ1_EINT_1, BST_UVP_ERR), 956 CS35L45_REG_IRQ(IRQ1_EINT_1, TEMP_ERR), 957 CS35L45_REG_IRQ(IRQ1_EINT_3, AMP_CAL_ERR), 958 CS35L45_REG_IRQ(IRQ1_EINT_18, UVLO_VDDLV_ERR), 959 CS35L45_REG_IRQ(IRQ1_EINT_18, GLOBAL_ERROR), 960 CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_WDT_EXPIRE), 961 CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_UNLOCK_FLAG_RISE), 962 CS35L45_REG_IRQ(IRQ1_EINT_3, PLL_LOCK_FLAG), |
963 CS35L45_REG_IRQ(IRQ1_EINT_2, DSP_VIRT2_MBOX), |
|
668}; 669 670static const struct regmap_irq_chip cs35l45_regmap_irq_chip = { 671 .name = "cs35l45 IRQ1 Controller", 672 .main_status = CS35L45_IRQ1_STATUS, 673 .status_base = CS35L45_IRQ1_EINT_1, 674 .mask_base = CS35L45_IRQ1_MASK_1, 675 .ack_base = CS35L45_IRQ1_EINT_1, --- 43 unchanged lines hidden (view full) --- 719 dev_err(dev, "Failed to apply init patch %d\n", ret); 720 return ret; 721 } 722 723 ret = cs35l45_apply_property_config(cs35l45); 724 if (ret < 0) 725 return ret; 726 | 964}; 965 966static const struct regmap_irq_chip cs35l45_regmap_irq_chip = { 967 .name = "cs35l45 IRQ1 Controller", 968 .main_status = CS35L45_IRQ1_STATUS, 969 .status_base = CS35L45_IRQ1_EINT_1, 970 .mask_base = CS35L45_IRQ1_MASK_1, 971 .ack_base = CS35L45_IRQ1_EINT_1, --- 43 unchanged lines hidden (view full) --- 1015 dev_err(dev, "Failed to apply init patch %d\n", ret); 1016 return ret; 1017 } 1018 1019 ret = cs35l45_apply_property_config(cs35l45); 1020 if (ret < 0) 1021 return ret; 1022 |
727 pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000); 728 pm_runtime_use_autosuspend(cs35l45->dev); 729 pm_runtime_set_active(cs35l45->dev); 730 pm_runtime_enable(cs35l45->dev); 731 | |
732 return 0; 733} 734 | 1023 return 0; 1024} 1025 |
1026static const struct reg_sequence cs35l45_fs_errata_patch[] = { 1027 {0x02B80080, 0x00000001}, 1028 {0x02B80088, 0x00000001}, 1029 {0x02B80090, 0x00000001}, 1030 {0x02B80098, 0x00000001}, 1031 {0x02B800A0, 0x00000001}, 1032 {0x02B800A8, 0x00000001}, 1033 {0x02B800B0, 0x00000001}, 1034 {0x02B800B8, 0x00000001}, 1035 {0x02B80280, 0x00000001}, 1036 {0x02B80288, 0x00000001}, 1037 {0x02B80290, 0x00000001}, 1038 {0x02B80298, 0x00000001}, 1039 {0x02B802A0, 0x00000001}, 1040 {0x02B802A8, 0x00000001}, 1041 {0x02B802B0, 0x00000001}, 1042 {0x02B802B8, 0x00000001}, 1043}; 1044 1045static const struct cs_dsp_region cs35l45_dsp1_regions[] = { 1046 { .type = WMFW_HALO_PM_PACKED, .base = CS35L45_DSP1_PMEM_0 }, 1047 { .type = WMFW_HALO_XM_PACKED, .base = CS35L45_DSP1_XMEM_PACK_0 }, 1048 { .type = WMFW_HALO_YM_PACKED, .base = CS35L45_DSP1_YMEM_PACK_0 }, 1049 {. type = WMFW_ADSP2_XM, .base = CS35L45_DSP1_XMEM_UNPACK24_0}, 1050 {. type = WMFW_ADSP2_YM, .base = CS35L45_DSP1_YMEM_UNPACK24_0}, 1051}; 1052 1053static int cs35l45_dsp_init(struct cs35l45_private *cs35l45) 1054{ 1055 struct wm_adsp *dsp = &cs35l45->dsp; 1056 int ret; 1057 1058 dsp->part = "cs35l45"; 1059 dsp->fw = 9; /* 9 is WM_ADSP_FW_SPK_PROT in wm_adsp.c */ 1060 dsp->toggle_preload = true; 1061 dsp->cs_dsp.num = 1; 1062 dsp->cs_dsp.type = WMFW_HALO; 1063 dsp->cs_dsp.rev = 0; 1064 dsp->cs_dsp.dev = cs35l45->dev; 1065 dsp->cs_dsp.regmap = cs35l45->regmap; 1066 dsp->cs_dsp.base = CS35L45_DSP1_CLOCK_FREQ; 1067 dsp->cs_dsp.base_sysinfo = CS35L45_DSP1_SYS_ID; 1068 dsp->cs_dsp.mem = cs35l45_dsp1_regions; 1069 dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l45_dsp1_regions); 1070 dsp->cs_dsp.lock_regions = 0xFFFFFFFF; 1071 1072 ret = wm_halo_init(dsp); 1073 1074 regmap_multi_reg_write(cs35l45->regmap, cs35l45_fs_errata_patch, 1075 ARRAY_SIZE(cs35l45_fs_errata_patch)); 1076 1077 return ret; 1078} 1079 |
|
735int cs35l45_probe(struct cs35l45_private *cs35l45) 736{ 737 struct device *dev = cs35l45->dev; 738 unsigned long irq_pol = IRQF_ONESHOT | IRQF_SHARED; 739 int ret, i, irq; 740 741 cs35l45->vdd_batt = devm_regulator_get(dev, "vdd-batt"); 742 if (IS_ERR(cs35l45->vdd_batt)) --- 33 unchanged lines hidden (view full) --- 776 } 777 778 usleep_range(CS35L45_RESET_US, CS35L45_RESET_US + 100); 779 780 ret = cs35l45_initialize(cs35l45); 781 if (ret < 0) 782 goto err_reset; 783 | 1080int cs35l45_probe(struct cs35l45_private *cs35l45) 1081{ 1082 struct device *dev = cs35l45->dev; 1083 unsigned long irq_pol = IRQF_ONESHOT | IRQF_SHARED; 1084 int ret, i, irq; 1085 1086 cs35l45->vdd_batt = devm_regulator_get(dev, "vdd-batt"); 1087 if (IS_ERR(cs35l45->vdd_batt)) --- 33 unchanged lines hidden (view full) --- 1121 } 1122 1123 usleep_range(CS35L45_RESET_US, CS35L45_RESET_US + 100); 1124 1125 ret = cs35l45_initialize(cs35l45); 1126 if (ret < 0) 1127 goto err_reset; 1128 |
1129 ret = cs35l45_dsp_init(cs35l45); 1130 if (ret < 0) 1131 goto err_reset; 1132 1133 pm_runtime_set_autosuspend_delay(cs35l45->dev, 3000); 1134 pm_runtime_use_autosuspend(cs35l45->dev); 1135 pm_runtime_mark_last_busy(cs35l45->dev); 1136 pm_runtime_set_active(cs35l45->dev); 1137 pm_runtime_get_noresume(cs35l45->dev); 1138 pm_runtime_enable(cs35l45->dev); 1139 |
|
784 if (cs35l45->irq) { 785 if (cs35l45->irq_invert) 786 irq_pol |= IRQF_TRIGGER_HIGH; 787 else 788 irq_pol |= IRQF_TRIGGER_LOW; 789 790 ret = devm_regmap_add_irq_chip(dev, cs35l45->regmap, cs35l45->irq, irq_pol, 0, 791 &cs35l45_regmap_irq_chip, &cs35l45->irq_data); 792 if (ret) { 793 dev_err(dev, "Failed to register IRQ chip: %d\n", ret); | 1140 if (cs35l45->irq) { 1141 if (cs35l45->irq_invert) 1142 irq_pol |= IRQF_TRIGGER_HIGH; 1143 else 1144 irq_pol |= IRQF_TRIGGER_LOW; 1145 1146 ret = devm_regmap_add_irq_chip(dev, cs35l45->regmap, cs35l45->irq, irq_pol, 0, 1147 &cs35l45_regmap_irq_chip, &cs35l45->irq_data); 1148 if (ret) { 1149 dev_err(dev, "Failed to register IRQ chip: %d\n", ret); |
794 goto err_reset; | 1150 goto err_dsp; |
795 } 796 797 for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) { 798 irq = regmap_irq_get_virq(cs35l45->irq_data, cs35l45_irqs[i].irq); 799 if (irq < 0) { 800 dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name); 801 ret = irq; | 1151 } 1152 1153 for (i = 0; i < ARRAY_SIZE(cs35l45_irqs); i++) { 1154 irq = regmap_irq_get_virq(cs35l45->irq_data, cs35l45_irqs[i].irq); 1155 if (irq < 0) { 1156 dev_err(dev, "Failed to get %s\n", cs35l45_irqs[i].name); 1157 ret = irq; |
802 goto err_reset; | 1158 goto err_dsp; |
803 } 804 805 ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler, 806 irq_pol, cs35l45_irqs[i].name, cs35l45); 807 if (ret) { 808 dev_err(dev, "Failed to request IRQ %s: %d\n", 809 cs35l45_irqs[i].name, ret); | 1159 } 1160 1161 ret = devm_request_threaded_irq(dev, irq, NULL, cs35l45_irqs[i].handler, 1162 irq_pol, cs35l45_irqs[i].name, cs35l45); 1163 if (ret) { 1164 dev_err(dev, "Failed to request IRQ %s: %d\n", 1165 cs35l45_irqs[i].name, ret); |
810 goto err_reset; | 1166 goto err_dsp; |
811 } 812 } 813 } 814 815 ret = devm_snd_soc_register_component(dev, &cs35l45_component, 816 cs35l45_dai, 817 ARRAY_SIZE(cs35l45_dai)); 818 if (ret < 0) | 1167 } 1168 } 1169 } 1170 1171 ret = devm_snd_soc_register_component(dev, &cs35l45_component, 1172 cs35l45_dai, 1173 ARRAY_SIZE(cs35l45_dai)); 1174 if (ret < 0) |
819 goto err_reset; | 1175 goto err_dsp; |
820 | 1176 |
1177 pm_runtime_put_autosuspend(cs35l45->dev); 1178 |
|
821 return 0; 822 | 1179 return 0; 1180 |
1181err_dsp: 1182 pm_runtime_disable(cs35l45->dev); 1183 pm_runtime_put_noidle(cs35l45->dev); 1184 wm_adsp2_remove(&cs35l45->dsp); 1185 |
|
823err_reset: 824 gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); 825err: 826 regulator_disable(cs35l45->vdd_a); 827 regulator_disable(cs35l45->vdd_batt); 828 829 return ret; 830} 831EXPORT_SYMBOL_NS_GPL(cs35l45_probe, SND_SOC_CS35L45); 832 833void cs35l45_remove(struct cs35l45_private *cs35l45) 834{ | 1186err_reset: 1187 gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); 1188err: 1189 regulator_disable(cs35l45->vdd_a); 1190 regulator_disable(cs35l45->vdd_batt); 1191 1192 return ret; 1193} 1194EXPORT_SYMBOL_NS_GPL(cs35l45_probe, SND_SOC_CS35L45); 1195 1196void cs35l45_remove(struct cs35l45_private *cs35l45) 1197{ |
1198 pm_runtime_get_sync(cs35l45->dev); |
|
835 pm_runtime_disable(cs35l45->dev); | 1199 pm_runtime_disable(cs35l45->dev); |
1200 wm_adsp2_remove(&cs35l45->dsp); |
|
836 837 gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); | 1201 1202 gpiod_set_value_cansleep(cs35l45->reset_gpio, 0); |
1203 1204 pm_runtime_put_noidle(cs35l45->dev); |
|
838 regulator_disable(cs35l45->vdd_a); 839 /* VDD_BATT must be the last to power-off */ 840 regulator_disable(cs35l45->vdd_batt); 841} 842EXPORT_SYMBOL_NS_GPL(cs35l45_remove, SND_SOC_CS35L45); 843 844const struct dev_pm_ops cs35l45_pm_ops = { 845 SET_RUNTIME_PM_OPS(cs35l45_runtime_suspend, cs35l45_runtime_resume, NULL) 846}; 847EXPORT_SYMBOL_NS_GPL(cs35l45_pm_ops, SND_SOC_CS35L45); 848 849MODULE_DESCRIPTION("ASoC CS35L45 driver"); 850MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>"); 851MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 852MODULE_LICENSE("Dual BSD/GPL"); | 1205 regulator_disable(cs35l45->vdd_a); 1206 /* VDD_BATT must be the last to power-off */ 1207 regulator_disable(cs35l45->vdd_batt); 1208} 1209EXPORT_SYMBOL_NS_GPL(cs35l45_remove, SND_SOC_CS35L45); 1210 1211const struct dev_pm_ops cs35l45_pm_ops = { 1212 SET_RUNTIME_PM_OPS(cs35l45_runtime_suspend, cs35l45_runtime_resume, NULL) 1213}; 1214EXPORT_SYMBOL_NS_GPL(cs35l45_pm_ops, SND_SOC_CS35L45); 1215 1216MODULE_DESCRIPTION("ASoC CS35L45 driver"); 1217MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>"); 1218MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 1219MODULE_LICENSE("Dual BSD/GPL"); |