1 // SPDX-License-Identifier: GPL-2.0
3 // cs35l41.c -- CS35l41 ALSA SoC audio driver
5 // Copyright 2017-2021 Cirrus Logic, Inc.
7 // Author: David Rhodes <david.rhodes@cirrus.com>
9 #include <linux/delay.h>
10 #include <linux/err.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/of_device.h>
16 #include <linux/property.h>
17 #include <linux/slab.h>
18 #include <sound/initval.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
22 #include <sound/soc-dapm.h>
23 #include <sound/tlv.h>
27 static const char * const cs35l41_supplies[CS35L41_NUM_SUPPLIES] = {
32 struct cs35l41_pll_sysclk_config {
37 static const struct cs35l41_pll_sysclk_config cs35l41_pll_sysclk[] = {
104 struct cs35l41_fs_mon_config {
110 static const struct cs35l41_fs_mon_config cs35l41_fs_mon[] = {
111 { 32768, 2254, 3754 },
112 { 8000, 9220, 15364 },
113 { 11025, 6148, 10244 },
114 { 12000, 6148, 10244 },
115 { 16000, 4612, 7684 },
116 { 22050, 3076, 5124 },
117 { 24000, 3076, 5124 },
118 { 32000, 2308, 3844 },
119 { 44100, 1540, 2564 },
120 { 48000, 1540, 2564 },
121 { 88200, 772, 1284 },
122 { 96000, 772, 1284 },
123 { 128000, 580, 964 },
124 { 176400, 388, 644 },
125 { 192000, 388, 644 },
126 { 256000, 292, 484 },
127 { 352800, 196, 324 },
128 { 384000, 196, 324 },
129 { 512000, 148, 244 },
130 { 705600, 100, 164 },
131 { 750000, 100, 164 },
132 { 768000, 100, 164 },
133 { 1000000, 76, 124 },
134 { 1024000, 76, 124 },
135 { 1200000, 64, 104 },
154 static const unsigned char cs35l41_bst_k1_table[4][5] = {
155 { 0x24, 0x32, 0x32, 0x4F, 0x57 },
156 { 0x24, 0x32, 0x32, 0x4F, 0x57 },
157 { 0x40, 0x32, 0x32, 0x4F, 0x57 },
158 { 0x40, 0x32, 0x32, 0x4F, 0x57 }
161 static const unsigned char cs35l41_bst_k2_table[4][5] = {
162 { 0x24, 0x49, 0x66, 0xA3, 0xEA },
163 { 0x24, 0x49, 0x66, 0xA3, 0xEA },
164 { 0x48, 0x49, 0x66, 0xA3, 0xEA },
165 { 0x48, 0x49, 0x66, 0xA3, 0xEA }
168 static const unsigned char cs35l41_bst_slope_table[4] = {
169 0x75, 0x6B, 0x3B, 0x28
172 static int cs35l41_get_fs_mon_config_index(int freq)
176 for (i = 0; i < ARRAY_SIZE(cs35l41_fs_mon); i++) {
177 if (cs35l41_fs_mon[i].freq == freq)
184 static const DECLARE_TLV_DB_RANGE(dig_vol_tlv,
185 0, 0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
186 1, 913, TLV_DB_MINMAX_ITEM(-10200, 1200));
187 static DECLARE_TLV_DB_SCALE(amp_gain_tlv, 0, 1, 1);
189 static const struct snd_kcontrol_new dre_ctrl =
190 SOC_DAPM_SINGLE("Switch", CS35L41_PWR_CTRL3, 20, 1, 0);
192 static const char * const cs35l41_pcm_sftramp_text[] = {
193 "Off", ".5ms", "1ms", "2ms", "4ms", "8ms", "15ms", "30ms"
196 static SOC_ENUM_SINGLE_DECL(pcm_sft_ramp,
197 CS35L41_AMP_DIG_VOL_CTRL, 0,
198 cs35l41_pcm_sftramp_text);
200 static int cs35l41_dsp_preload_ev(struct snd_soc_dapm_widget *w,
201 struct snd_kcontrol *kcontrol, int event)
206 case SND_SOC_DAPM_PRE_PMU:
207 return wm_adsp_early_event(w, kcontrol, event);
208 case SND_SOC_DAPM_PRE_PMD:
209 ret = wm_adsp_early_event(w, kcontrol, event);
213 return wm_adsp_event(w, kcontrol, event);
219 static bool cs35l41_check_cspl_mbox_sts(enum cs35l41_cspl_mbox_cmd cmd,
220 enum cs35l41_cspl_mbox_status sts)
223 case CSPL_MBOX_CMD_NONE:
224 case CSPL_MBOX_CMD_UNKNOWN_CMD:
226 case CSPL_MBOX_CMD_PAUSE:
227 return (sts == CSPL_MBOX_STS_PAUSED);
228 case CSPL_MBOX_CMD_RESUME:
229 return (sts == CSPL_MBOX_STS_RUNNING);
230 case CSPL_MBOX_CMD_REINIT:
231 return (sts == CSPL_MBOX_STS_RUNNING);
232 case CSPL_MBOX_CMD_STOP_PRE_REINIT:
233 return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT);
239 static int cs35l41_set_cspl_mbox_cmd(struct cs35l41_private *cs35l41,
240 enum cs35l41_cspl_mbox_cmd cmd)
242 unsigned int sts = 0, i;
246 ret = regmap_write(cs35l41->regmap, CS35L41_DSP_VIRT1_MBOX_1, cmd);
248 dev_err(cs35l41->dev, "Failed to write MBOX: %d\n", ret);
252 // Read mailbox status and verify it is appropriate for the given cmd
253 for (i = 0; i < 5; i++) {
254 usleep_range(1000, 1100);
256 ret = regmap_read(cs35l41->regmap, CS35L41_DSP_MBOX_2, &sts);
258 dev_err(cs35l41->dev, "Failed to read MBOX STS: %d\n", ret);
262 if (!cs35l41_check_cspl_mbox_sts(cmd, sts)) {
263 dev_dbg(cs35l41->dev,
264 "[%u] cmd %u returned invalid sts %u",
271 dev_err(cs35l41->dev,
272 "Failed to set mailbox cmd %u (status %u)\n",
278 static int cs35l41_dsp_audio_ev(struct snd_soc_dapm_widget *w,
279 struct snd_kcontrol *kcontrol, int event)
281 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
282 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
283 unsigned int fw_status;
287 case SND_SOC_DAPM_POST_PMU:
288 if (!cs35l41->dsp.cs_dsp.running)
289 return wm_adsp_event(w, kcontrol, event);
291 ret = regmap_read(cs35l41->regmap, CS35L41_DSP_MBOX_2, &fw_status);
293 dev_err(cs35l41->dev,
294 "Failed to read firmware status: %d\n", ret);
299 case CSPL_MBOX_STS_RUNNING:
300 case CSPL_MBOX_STS_PAUSED:
303 dev_err(cs35l41->dev, "Firmware status is invalid: %u\n",
308 return cs35l41_set_cspl_mbox_cmd(cs35l41, CSPL_MBOX_CMD_RESUME);
309 case SND_SOC_DAPM_PRE_PMD:
310 return cs35l41_set_cspl_mbox_cmd(cs35l41, CSPL_MBOX_CMD_PAUSE);
316 static const char * const cs35l41_pcm_source_texts[] = {"ASP", "DSP"};
317 static const unsigned int cs35l41_pcm_source_values[] = {0x08, 0x32};
318 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_pcm_source_enum,
319 CS35L41_DAC_PCM1_SRC,
320 0, CS35L41_ASP_SOURCE_MASK,
321 cs35l41_pcm_source_texts,
322 cs35l41_pcm_source_values);
324 static const struct snd_kcontrol_new pcm_source_mux =
325 SOC_DAPM_ENUM("PCM Source", cs35l41_pcm_source_enum);
327 static const char * const cs35l41_tx_input_texts[] = {
328 "Zero", "ASPRX1", "ASPRX2", "VMON", "IMON",
329 "VPMON", "VBSTMON", "DSPTX1", "DSPTX2"
332 static const unsigned int cs35l41_tx_input_values[] = {
333 0x00, CS35L41_INPUT_SRC_ASPRX1, CS35L41_INPUT_SRC_ASPRX2,
334 CS35L41_INPUT_SRC_VMON, CS35L41_INPUT_SRC_IMON, CS35L41_INPUT_SRC_VPMON,
335 CS35L41_INPUT_SRC_VBSTMON, CS35L41_INPUT_DSP_TX1, CS35L41_INPUT_DSP_TX2
338 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_asptx1_enum,
340 0, CS35L41_ASP_SOURCE_MASK,
341 cs35l41_tx_input_texts,
342 cs35l41_tx_input_values);
344 static const struct snd_kcontrol_new asp_tx1_mux =
345 SOC_DAPM_ENUM("ASPTX1 SRC", cs35l41_asptx1_enum);
347 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_asptx2_enum,
349 0, CS35L41_ASP_SOURCE_MASK,
350 cs35l41_tx_input_texts,
351 cs35l41_tx_input_values);
353 static const struct snd_kcontrol_new asp_tx2_mux =
354 SOC_DAPM_ENUM("ASPTX2 SRC", cs35l41_asptx2_enum);
356 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_asptx3_enum,
358 0, CS35L41_ASP_SOURCE_MASK,
359 cs35l41_tx_input_texts,
360 cs35l41_tx_input_values);
362 static const struct snd_kcontrol_new asp_tx3_mux =
363 SOC_DAPM_ENUM("ASPTX3 SRC", cs35l41_asptx3_enum);
365 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_asptx4_enum,
367 0, CS35L41_ASP_SOURCE_MASK,
368 cs35l41_tx_input_texts,
369 cs35l41_tx_input_values);
371 static const struct snd_kcontrol_new asp_tx4_mux =
372 SOC_DAPM_ENUM("ASPTX4 SRC", cs35l41_asptx4_enum);
374 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_dsprx1_enum,
375 CS35L41_DSP1_RX1_SRC,
376 0, CS35L41_ASP_SOURCE_MASK,
377 cs35l41_tx_input_texts,
378 cs35l41_tx_input_values);
380 static const struct snd_kcontrol_new dsp_rx1_mux =
381 SOC_DAPM_ENUM("DSPRX1 SRC", cs35l41_dsprx1_enum);
383 static SOC_VALUE_ENUM_SINGLE_DECL(cs35l41_dsprx2_enum,
384 CS35L41_DSP1_RX2_SRC,
385 0, CS35L41_ASP_SOURCE_MASK,
386 cs35l41_tx_input_texts,
387 cs35l41_tx_input_values);
389 static const struct snd_kcontrol_new dsp_rx2_mux =
390 SOC_DAPM_ENUM("DSPRX2 SRC", cs35l41_dsprx2_enum);
392 static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
393 SOC_SINGLE_SX_TLV("Digital PCM Volume", CS35L41_AMP_DIG_VOL_CTRL,
394 3, 0x4CF, 0x391, dig_vol_tlv),
395 SOC_SINGLE_TLV("Analog PCM Volume", CS35L41_AMP_GAIN_CTRL, 5, 0x14, 0,
397 SOC_ENUM("PCM Soft Ramp", pcm_sft_ramp),
398 SOC_SINGLE("HW Noise Gate Enable", CS35L41_NG_CFG, 8, 63, 0),
399 SOC_SINGLE("HW Noise Gate Delay", CS35L41_NG_CFG, 4, 7, 0),
400 SOC_SINGLE("HW Noise Gate Threshold", CS35L41_NG_CFG, 0, 7, 0),
401 SOC_SINGLE("Aux Noise Gate CH1 Enable",
402 CS35L41_MIXER_NGATE_CH1_CFG, 16, 1, 0),
403 SOC_SINGLE("Aux Noise Gate CH1 Entry Delay",
404 CS35L41_MIXER_NGATE_CH1_CFG, 8, 15, 0),
405 SOC_SINGLE("Aux Noise Gate CH1 Threshold",
406 CS35L41_MIXER_NGATE_CH1_CFG, 0, 7, 0),
407 SOC_SINGLE("Aux Noise Gate CH2 Entry Delay",
408 CS35L41_MIXER_NGATE_CH2_CFG, 8, 15, 0),
409 SOC_SINGLE("Aux Noise Gate CH2 Enable",
410 CS35L41_MIXER_NGATE_CH2_CFG, 16, 1, 0),
411 SOC_SINGLE("Aux Noise Gate CH2 Threshold",
412 CS35L41_MIXER_NGATE_CH2_CFG, 0, 7, 0),
413 SOC_SINGLE("SCLK Force", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0),
414 SOC_SINGLE("LRCLK Force", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0),
415 SOC_SINGLE("Invert Class D", CS35L41_AMP_DIG_VOL_CTRL,
416 CS35L41_AMP_INV_PCM_SHIFT, 1, 0),
417 SOC_SINGLE("Amp Gain ZC", CS35L41_AMP_GAIN_CTRL,
418 CS35L41_AMP_GAIN_ZC_SHIFT, 1, 0),
419 WM_ADSP2_PRELOAD_SWITCH("DSP1", 1),
420 WM_ADSP_FW_CONTROL("DSP1", 0),
423 static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
427 for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
428 if (cs35l41_otp_map_map[i].id == otp_id)
429 return &cs35l41_otp_map_map[i];
435 static int cs35l41_otp_unpack(void *data)
437 const struct cs35l41_otp_map_element_t *otp_map_match;
438 const struct cs35l41_otp_packed_element_t *otp_map;
439 struct cs35l41_private *cs35l41 = data;
440 int bit_offset, word_offset, ret, i;
441 unsigned int bit_sum = 8;
442 u32 otp_val, otp_id_reg;
445 otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
449 ret = regmap_read(cs35l41->regmap, CS35L41_OTPID, &otp_id_reg);
451 dev_err(cs35l41->dev, "Read OTP ID failed: %d\n", ret);
455 otp_map_match = cs35l41_find_otp_map(otp_id_reg);
457 if (!otp_map_match) {
458 dev_err(cs35l41->dev, "OTP Map matching ID %d not found\n",
464 ret = regmap_bulk_read(cs35l41->regmap, CS35L41_OTP_MEM0, otp_mem,
465 CS35L41_OTP_SIZE_WORDS);
467 dev_err(cs35l41->dev, "Read OTP Mem failed: %d\n", ret);
471 otp_map = otp_map_match->map;
473 bit_offset = otp_map_match->bit_offset;
474 word_offset = otp_map_match->word_offset;
476 ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x00000055);
478 dev_err(cs35l41->dev, "Write Unlock key failed 1/2: %d\n", ret);
481 ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x000000AA);
483 dev_err(cs35l41->dev, "Write Unlock key failed 2/2: %d\n", ret);
487 for (i = 0; i < otp_map_match->num_elements; i++) {
488 dev_dbg(cs35l41->dev,
489 "bitoffset= %d, word_offset=%d, bit_sum mod 32=%d\n",
490 bit_offset, word_offset, bit_sum % 32);
491 if (bit_offset + otp_map[i].size - 1 >= 32) {
492 otp_val = (otp_mem[word_offset] &
493 GENMASK(31, bit_offset)) >>
495 otp_val |= (otp_mem[++word_offset] &
497 otp_map[i].size - 33, 0)) <<
499 bit_offset += otp_map[i].size - 32;
501 otp_val = (otp_mem[word_offset] &
502 GENMASK(bit_offset + otp_map[i].size - 1,
503 bit_offset)) >> bit_offset;
504 bit_offset += otp_map[i].size;
506 bit_sum += otp_map[i].size;
508 if (bit_offset == 32) {
513 if (otp_map[i].reg != 0) {
514 ret = regmap_update_bits(cs35l41->regmap,
516 GENMASK(otp_map[i].shift +
519 otp_val << otp_map[i].shift);
521 dev_err(cs35l41->dev, "Write OTP val failed: %d\n",
528 ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x000000CC);
530 dev_err(cs35l41->dev, "Write Lock key failed 1/2: %d\n", ret);
533 ret = regmap_write(cs35l41->regmap, CS35L41_TEST_KEY_CTL, 0x00000033);
535 dev_err(cs35l41->dev, "Write Lock key failed 2/2: %d\n", ret);
545 static irqreturn_t cs35l41_irq(int irq, void *data)
547 struct cs35l41_private *cs35l41 = data;
548 unsigned int status[4] = { 0, 0, 0, 0 };
549 unsigned int masks[4] = { 0, 0, 0, 0 };
553 for (i = 0; i < ARRAY_SIZE(status); i++) {
554 regmap_read(cs35l41->regmap,
555 CS35L41_IRQ1_STATUS1 + (i * CS35L41_REGSTRIDE),
557 regmap_read(cs35l41->regmap,
558 CS35L41_IRQ1_MASK1 + (i * CS35L41_REGSTRIDE),
562 /* Check to see if unmasked bits are active */
563 if (!(status[0] & ~masks[0]) && !(status[1] & ~masks[1]) &&
564 !(status[2] & ~masks[2]) && !(status[3] & ~masks[3]))
567 if (status[3] & CS35L41_OTP_BOOT_DONE) {
568 regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK4,
569 CS35L41_OTP_BOOT_DONE, CS35L41_OTP_BOOT_DONE);
573 * The following interrupts require a
574 * protection release cycle to get the
575 * speaker out of Safe-Mode.
577 if (status[0] & CS35L41_AMP_SHORT_ERR) {
578 dev_crit_ratelimited(cs35l41->dev, "Amp short error\n");
579 regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
580 CS35L41_AMP_SHORT_ERR);
581 regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
582 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
583 CS35L41_AMP_SHORT_ERR_RLS,
584 CS35L41_AMP_SHORT_ERR_RLS);
585 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
586 CS35L41_AMP_SHORT_ERR_RLS, 0);
590 if (status[0] & CS35L41_TEMP_WARN) {
591 dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n");
592 regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
594 regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
595 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
596 CS35L41_TEMP_WARN_ERR_RLS,
597 CS35L41_TEMP_WARN_ERR_RLS);
598 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
599 CS35L41_TEMP_WARN_ERR_RLS, 0);
603 if (status[0] & CS35L41_TEMP_ERR) {
604 dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n");
605 regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
607 regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
608 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
609 CS35L41_TEMP_ERR_RLS,
610 CS35L41_TEMP_ERR_RLS);
611 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
612 CS35L41_TEMP_ERR_RLS, 0);
616 if (status[0] & CS35L41_BST_OVP_ERR) {
617 dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n");
618 regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
619 CS35L41_BST_EN_MASK, 0);
620 regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
621 CS35L41_BST_OVP_ERR);
622 regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
623 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
624 CS35L41_BST_OVP_ERR_RLS,
625 CS35L41_BST_OVP_ERR_RLS);
626 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
627 CS35L41_BST_OVP_ERR_RLS, 0);
628 regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
630 CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT);
634 if (status[0] & CS35L41_BST_DCM_UVP_ERR) {
635 dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n");
636 regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
637 CS35L41_BST_EN_MASK, 0);
638 regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
639 CS35L41_BST_DCM_UVP_ERR);
640 regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
641 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
642 CS35L41_BST_UVP_ERR_RLS,
643 CS35L41_BST_UVP_ERR_RLS);
644 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
645 CS35L41_BST_UVP_ERR_RLS, 0);
646 regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
648 CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT);
652 if (status[0] & CS35L41_BST_SHORT_ERR) {
653 dev_crit_ratelimited(cs35l41->dev, "LBST error: powering off!\n");
654 regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
655 CS35L41_BST_EN_MASK, 0);
656 regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
657 CS35L41_BST_SHORT_ERR);
658 regmap_write(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);
659 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
660 CS35L41_BST_SHORT_ERR_RLS,
661 CS35L41_BST_SHORT_ERR_RLS);
662 regmap_update_bits(cs35l41->regmap, CS35L41_PROTECT_REL_ERR_IGN,
663 CS35L41_BST_SHORT_ERR_RLS, 0);
664 regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
666 CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT);
673 static const struct reg_sequence cs35l41_pup_patch[] = {
674 { 0x00000040, 0x00000055 },
675 { 0x00000040, 0x000000AA },
676 { 0x00002084, 0x002F1AA0 },
677 { 0x00000040, 0x000000CC },
678 { 0x00000040, 0x00000033 },
681 static const struct reg_sequence cs35l41_pdn_patch[] = {
682 { 0x00000040, 0x00000055 },
683 { 0x00000040, 0x000000AA },
684 { 0x00002084, 0x002F1AA3 },
685 { 0x00000040, 0x000000CC },
686 { 0x00000040, 0x00000033 },
689 static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w,
690 struct snd_kcontrol *kcontrol, int event)
692 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
693 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
698 case SND_SOC_DAPM_POST_PMU:
699 regmap_multi_reg_write_bypassed(cs35l41->regmap,
701 ARRAY_SIZE(cs35l41_pup_patch));
703 regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL1,
704 CS35L41_GLOBAL_EN_MASK,
705 1 << CS35L41_GLOBAL_EN_SHIFT);
707 usleep_range(1000, 1100);
709 case SND_SOC_DAPM_POST_PMD:
710 regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL1,
711 CS35L41_GLOBAL_EN_MASK, 0);
713 ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
714 val, val & CS35L41_PDN_DONE_MASK,
717 dev_warn(cs35l41->dev, "PDN failed: %d\n", ret);
719 regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1,
720 CS35L41_PDN_DONE_MASK);
722 regmap_multi_reg_write_bypassed(cs35l41->regmap,
724 ARRAY_SIZE(cs35l41_pdn_patch));
727 dev_err(cs35l41->dev, "Invalid event = 0x%x\n", event);
734 static const struct snd_soc_dapm_widget cs35l41_dapm_widgets[] = {
735 SND_SOC_DAPM_SPK("DSP1 Preload", NULL),
736 SND_SOC_DAPM_SUPPLY_S("DSP1 Preloader", 100, SND_SOC_NOPM, 0, 0,
737 cs35l41_dsp_preload_ev,
738 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
739 SND_SOC_DAPM_OUT_DRV_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0,
740 cs35l41_dsp_audio_ev,
741 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
743 SND_SOC_DAPM_OUTPUT("SPK"),
745 SND_SOC_DAPM_AIF_IN("ASPRX1", NULL, 0, CS35L41_SP_ENABLES, 16, 0),
746 SND_SOC_DAPM_AIF_IN("ASPRX2", NULL, 0, CS35L41_SP_ENABLES, 17, 0),
747 SND_SOC_DAPM_AIF_OUT("ASPTX1", NULL, 0, CS35L41_SP_ENABLES, 0, 0),
748 SND_SOC_DAPM_AIF_OUT("ASPTX2", NULL, 0, CS35L41_SP_ENABLES, 1, 0),
749 SND_SOC_DAPM_AIF_OUT("ASPTX3", NULL, 0, CS35L41_SP_ENABLES, 2, 0),
750 SND_SOC_DAPM_AIF_OUT("ASPTX4", NULL, 0, CS35L41_SP_ENABLES, 3, 0),
752 SND_SOC_DAPM_SIGGEN("VSENSE"),
753 SND_SOC_DAPM_SIGGEN("ISENSE"),
754 SND_SOC_DAPM_SIGGEN("VP"),
755 SND_SOC_DAPM_SIGGEN("VBST"),
756 SND_SOC_DAPM_SIGGEN("TEMP"),
758 SND_SOC_DAPM_SUPPLY("VMON", CS35L41_PWR_CTRL2, 12, 0, NULL, 0),
759 SND_SOC_DAPM_SUPPLY("IMON", CS35L41_PWR_CTRL2, 13, 0, NULL, 0),
760 SND_SOC_DAPM_SUPPLY("VPMON", CS35L41_PWR_CTRL2, 8, 0, NULL, 0),
761 SND_SOC_DAPM_SUPPLY("VBSTMON", CS35L41_PWR_CTRL2, 9, 0, NULL, 0),
762 SND_SOC_DAPM_SUPPLY("TEMPMON", CS35L41_PWR_CTRL2, 10, 0, NULL, 0),
764 SND_SOC_DAPM_ADC("VMON ADC", NULL, SND_SOC_NOPM, 0, 0),
765 SND_SOC_DAPM_ADC("IMON ADC", NULL, SND_SOC_NOPM, 0, 0),
766 SND_SOC_DAPM_ADC("VPMON ADC", NULL, SND_SOC_NOPM, 0, 0),
767 SND_SOC_DAPM_ADC("VBSTMON ADC", NULL, SND_SOC_NOPM, 0, 0),
768 SND_SOC_DAPM_ADC("TEMPMON ADC", NULL, SND_SOC_NOPM, 0, 0),
770 SND_SOC_DAPM_ADC("CLASS H", NULL, CS35L41_PWR_CTRL3, 4, 0),
772 SND_SOC_DAPM_OUT_DRV_E("Main AMP", CS35L41_PWR_CTRL2, 0, 0, NULL, 0,
773 cs35l41_main_amp_event,
774 SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
776 SND_SOC_DAPM_MUX("ASP TX1 Source", SND_SOC_NOPM, 0, 0, &asp_tx1_mux),
777 SND_SOC_DAPM_MUX("ASP TX2 Source", SND_SOC_NOPM, 0, 0, &asp_tx2_mux),
778 SND_SOC_DAPM_MUX("ASP TX3 Source", SND_SOC_NOPM, 0, 0, &asp_tx3_mux),
779 SND_SOC_DAPM_MUX("ASP TX4 Source", SND_SOC_NOPM, 0, 0, &asp_tx4_mux),
780 SND_SOC_DAPM_MUX("DSP RX1 Source", SND_SOC_NOPM, 0, 0, &dsp_rx1_mux),
781 SND_SOC_DAPM_MUX("DSP RX2 Source", SND_SOC_NOPM, 0, 0, &dsp_rx2_mux),
782 SND_SOC_DAPM_MUX("PCM Source", SND_SOC_NOPM, 0, 0, &pcm_source_mux),
783 SND_SOC_DAPM_SWITCH("DRE", SND_SOC_NOPM, 0, 0, &dre_ctrl),
786 static const struct snd_soc_dapm_route cs35l41_audio_map[] = {
787 {"DSP RX1 Source", "ASPRX1", "ASPRX1"},
788 {"DSP RX1 Source", "ASPRX2", "ASPRX2"},
789 {"DSP RX2 Source", "ASPRX1", "ASPRX1"},
790 {"DSP RX2 Source", "ASPRX2", "ASPRX2"},
792 {"DSP1", NULL, "DSP RX1 Source"},
793 {"DSP1", NULL, "DSP RX2 Source"},
795 {"ASP TX1 Source", "VMON", "VMON ADC"},
796 {"ASP TX1 Source", "IMON", "IMON ADC"},
797 {"ASP TX1 Source", "VPMON", "VPMON ADC"},
798 {"ASP TX1 Source", "VBSTMON", "VBSTMON ADC"},
799 {"ASP TX1 Source", "DSPTX1", "DSP1"},
800 {"ASP TX1 Source", "DSPTX2", "DSP1"},
801 {"ASP TX1 Source", "ASPRX1", "ASPRX1" },
802 {"ASP TX1 Source", "ASPRX2", "ASPRX2" },
803 {"ASP TX2 Source", "VMON", "VMON ADC"},
804 {"ASP TX2 Source", "IMON", "IMON ADC"},
805 {"ASP TX2 Source", "VPMON", "VPMON ADC"},
806 {"ASP TX2 Source", "VBSTMON", "VBSTMON ADC"},
807 {"ASP TX2 Source", "DSPTX1", "DSP1"},
808 {"ASP TX2 Source", "DSPTX2", "DSP1"},
809 {"ASP TX2 Source", "ASPRX1", "ASPRX1" },
810 {"ASP TX2 Source", "ASPRX2", "ASPRX2" },
811 {"ASP TX3 Source", "VMON", "VMON ADC"},
812 {"ASP TX3 Source", "IMON", "IMON ADC"},
813 {"ASP TX3 Source", "VPMON", "VPMON ADC"},
814 {"ASP TX3 Source", "VBSTMON", "VBSTMON ADC"},
815 {"ASP TX3 Source", "DSPTX1", "DSP1"},
816 {"ASP TX3 Source", "DSPTX2", "DSP1"},
817 {"ASP TX3 Source", "ASPRX1", "ASPRX1" },
818 {"ASP TX3 Source", "ASPRX2", "ASPRX2" },
819 {"ASP TX4 Source", "VMON", "VMON ADC"},
820 {"ASP TX4 Source", "IMON", "IMON ADC"},
821 {"ASP TX4 Source", "VPMON", "VPMON ADC"},
822 {"ASP TX4 Source", "VBSTMON", "VBSTMON ADC"},
823 {"ASP TX4 Source", "DSPTX1", "DSP1"},
824 {"ASP TX4 Source", "DSPTX2", "DSP1"},
825 {"ASP TX4 Source", "ASPRX1", "ASPRX1" },
826 {"ASP TX4 Source", "ASPRX2", "ASPRX2" },
827 {"ASPTX1", NULL, "ASP TX1 Source"},
828 {"ASPTX2", NULL, "ASP TX2 Source"},
829 {"ASPTX3", NULL, "ASP TX3 Source"},
830 {"ASPTX4", NULL, "ASP TX4 Source"},
831 {"AMP Capture", NULL, "ASPTX1"},
832 {"AMP Capture", NULL, "ASPTX2"},
833 {"AMP Capture", NULL, "ASPTX3"},
834 {"AMP Capture", NULL, "ASPTX4"},
836 {"DSP1", NULL, "VMON"},
837 {"DSP1", NULL, "IMON"},
838 {"DSP1", NULL, "VPMON"},
839 {"DSP1", NULL, "VBSTMON"},
840 {"DSP1", NULL, "TEMPMON"},
842 {"VMON ADC", NULL, "VMON"},
843 {"IMON ADC", NULL, "IMON"},
844 {"VPMON ADC", NULL, "VPMON"},
845 {"VBSTMON ADC", NULL, "VBSTMON"},
846 {"TEMPMON ADC", NULL, "TEMPMON"},
848 {"VMON ADC", NULL, "VSENSE"},
849 {"IMON ADC", NULL, "ISENSE"},
850 {"VPMON ADC", NULL, "VP"},
851 {"VBSTMON ADC", NULL, "VBST"},
852 {"TEMPMON ADC", NULL, "TEMP"},
854 {"DSP1 Preload", NULL, "DSP1 Preloader"},
855 {"DSP1", NULL, "DSP1 Preloader"},
857 {"ASPRX1", NULL, "AMP Playback"},
858 {"ASPRX2", NULL, "AMP Playback"},
859 {"DRE", "Switch", "CLASS H"},
860 {"Main AMP", NULL, "CLASS H"},
861 {"Main AMP", NULL, "DRE"},
862 {"SPK", NULL, "Main AMP"},
864 {"PCM Source", "ASP", "ASPRX1"},
865 {"PCM Source", "DSP", "DSP1"},
866 {"CLASS H", NULL, "PCM Source"},
869 static const struct cs_dsp_region cs35l41_dsp1_regions[] = {
870 { .type = WMFW_HALO_PM_PACKED, .base = CS35L41_DSP1_PMEM_0 },
871 { .type = WMFW_HALO_XM_PACKED, .base = CS35L41_DSP1_XMEM_PACK_0 },
872 { .type = WMFW_HALO_YM_PACKED, .base = CS35L41_DSP1_YMEM_PACK_0 },
873 {. type = WMFW_ADSP2_XM, .base = CS35L41_DSP1_XMEM_UNPACK24_0},
874 {. type = WMFW_ADSP2_YM, .base = CS35L41_DSP1_YMEM_UNPACK24_0},
877 static int cs35l41_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num,
878 unsigned int *tx_slot, unsigned int rx_num,
879 unsigned int *rx_slot)
881 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
882 unsigned int val, mask;
885 if (tx_num > 4 || rx_num > 2)
890 for (i = 0; i < rx_num; i++) {
891 dev_dbg(cs35l41->dev, "rx slot %d position = %d\n", i, rx_slot[i]);
892 val |= rx_slot[i] << (i * 8);
893 mask |= 0x3F << (i * 8);
895 regmap_update_bits(cs35l41->regmap, CS35L41_SP_FRAME_RX_SLOT, mask, val);
899 for (i = 0; i < tx_num; i++) {
900 dev_dbg(cs35l41->dev, "tx slot %d position = %d\n", i, tx_slot[i]);
901 val |= tx_slot[i] << (i * 8);
902 mask |= 0x3F << (i * 8);
904 regmap_update_bits(cs35l41->regmap, CS35L41_SP_FRAME_TX_SLOT, mask, val);
909 static int cs35l41_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
911 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
912 unsigned int daifmt = 0;
914 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
915 case SND_SOC_DAIFMT_CBP_CFP:
916 daifmt |= CS35L41_SCLK_MSTR_MASK | CS35L41_LRCLK_MSTR_MASK;
918 case SND_SOC_DAIFMT_CBC_CFC:
921 dev_warn(cs35l41->dev, "Mixed provider/consumer mode unsupported\n");
925 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
926 case SND_SOC_DAIFMT_DSP_A:
928 case SND_SOC_DAIFMT_I2S:
929 daifmt |= 2 << CS35L41_ASP_FMT_SHIFT;
932 dev_warn(cs35l41->dev, "Invalid or unsupported DAI format\n");
936 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
937 case SND_SOC_DAIFMT_NB_IF:
938 daifmt |= CS35L41_LRCLK_INV_MASK;
940 case SND_SOC_DAIFMT_IB_NF:
941 daifmt |= CS35L41_SCLK_INV_MASK;
943 case SND_SOC_DAIFMT_IB_IF:
944 daifmt |= CS35L41_LRCLK_INV_MASK | CS35L41_SCLK_INV_MASK;
946 case SND_SOC_DAIFMT_NB_NF:
949 dev_warn(cs35l41->dev, "Invalid DAI clock INV\n");
953 return regmap_update_bits(cs35l41->regmap, CS35L41_SP_FORMAT,
954 CS35L41_SCLK_MSTR_MASK | CS35L41_LRCLK_MSTR_MASK |
955 CS35L41_ASP_FMT_MASK | CS35L41_LRCLK_INV_MASK |
956 CS35L41_SCLK_INV_MASK, daifmt);
959 struct cs35l41_global_fs_config {
964 static const struct cs35l41_global_fs_config cs35l41_fs_rates[] = {
980 static int cs35l41_pcm_hw_params(struct snd_pcm_substream *substream,
981 struct snd_pcm_hw_params *params,
982 struct snd_soc_dai *dai)
984 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
985 unsigned int rate = params_rate(params);
989 for (i = 0; i < ARRAY_SIZE(cs35l41_fs_rates); i++) {
990 if (rate == cs35l41_fs_rates[i].rate)
994 if (i >= ARRAY_SIZE(cs35l41_fs_rates)) {
995 dev_err(cs35l41->dev, "Unsupported rate: %u\n", rate);
999 asp_wl = params_width(params);
1001 if (i < ARRAY_SIZE(cs35l41_fs_rates))
1002 regmap_update_bits(cs35l41->regmap, CS35L41_GLOBAL_CLK_CTRL,
1003 CS35L41_GLOBAL_FS_MASK,
1004 cs35l41_fs_rates[i].fs_cfg << CS35L41_GLOBAL_FS_SHIFT);
1006 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1007 regmap_update_bits(cs35l41->regmap, CS35L41_SP_FORMAT,
1008 CS35L41_ASP_WIDTH_RX_MASK,
1009 asp_wl << CS35L41_ASP_WIDTH_RX_SHIFT);
1010 regmap_update_bits(cs35l41->regmap, CS35L41_SP_RX_WL,
1011 CS35L41_ASP_RX_WL_MASK,
1012 asp_wl << CS35L41_ASP_RX_WL_SHIFT);
1014 regmap_update_bits(cs35l41->regmap, CS35L41_SP_FORMAT,
1015 CS35L41_ASP_WIDTH_TX_MASK,
1016 asp_wl << CS35L41_ASP_WIDTH_TX_SHIFT);
1017 regmap_update_bits(cs35l41->regmap, CS35L41_SP_TX_WL,
1018 CS35L41_ASP_TX_WL_MASK,
1019 asp_wl << CS35L41_ASP_TX_WL_SHIFT);
1025 static int cs35l41_get_clk_config(int freq)
1029 for (i = 0; i < ARRAY_SIZE(cs35l41_pll_sysclk); i++) {
1030 if (cs35l41_pll_sysclk[i].freq == freq)
1031 return cs35l41_pll_sysclk[i].clk_cfg;
1037 static const unsigned int cs35l41_src_rates[] = {
1038 8000, 12000, 11025, 16000, 22050, 24000, 32000,
1039 44100, 48000, 88200, 96000, 176400, 192000
1042 static const struct snd_pcm_hw_constraint_list cs35l41_constraints = {
1043 .count = ARRAY_SIZE(cs35l41_src_rates),
1044 .list = cs35l41_src_rates,
1047 static int cs35l41_pcm_startup(struct snd_pcm_substream *substream,
1048 struct snd_soc_dai *dai)
1050 if (substream->runtime)
1051 return snd_pcm_hw_constraint_list(substream->runtime, 0,
1052 SNDRV_PCM_HW_PARAM_RATE,
1053 &cs35l41_constraints);
1057 static int cs35l41_component_set_sysclk(struct snd_soc_component *component,
1058 int clk_id, int source,
1059 unsigned int freq, int dir)
1061 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
1062 int extclk_cfg, clksrc;
1065 case CS35L41_CLKID_SCLK:
1066 clksrc = CS35L41_PLLSRC_SCLK;
1068 case CS35L41_CLKID_LRCLK:
1069 clksrc = CS35L41_PLLSRC_LRCLK;
1071 case CS35L41_CLKID_MCLK:
1072 clksrc = CS35L41_PLLSRC_MCLK;
1075 dev_err(cs35l41->dev, "Invalid CLK Config\n");
1079 extclk_cfg = cs35l41_get_clk_config(freq);
1081 if (extclk_cfg < 0) {
1082 dev_err(cs35l41->dev, "Invalid CLK Config: %d, freq: %u\n",
1087 regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
1088 CS35L41_PLL_OPENLOOP_MASK,
1089 1 << CS35L41_PLL_OPENLOOP_SHIFT);
1090 regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
1091 CS35L41_REFCLK_FREQ_MASK,
1092 extclk_cfg << CS35L41_REFCLK_FREQ_SHIFT);
1093 regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
1094 CS35L41_PLL_CLK_EN_MASK,
1095 0 << CS35L41_PLL_CLK_EN_SHIFT);
1096 regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
1097 CS35L41_PLL_CLK_SEL_MASK, clksrc);
1098 regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
1099 CS35L41_PLL_OPENLOOP_MASK,
1100 0 << CS35L41_PLL_OPENLOOP_SHIFT);
1101 regmap_update_bits(cs35l41->regmap, CS35L41_PLL_CLK_CTRL,
1102 CS35L41_PLL_CLK_EN_MASK,
1103 1 << CS35L41_PLL_CLK_EN_SHIFT);
1108 static int cs35l41_dai_set_sysclk(struct snd_soc_dai *dai,
1109 int clk_id, unsigned int freq, int dir)
1111 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(dai->component);
1112 unsigned int fs1_val;
1113 unsigned int fs2_val;
1117 fsindex = cs35l41_get_fs_mon_config_index(freq);
1119 dev_err(cs35l41->dev, "Invalid CLK Config freq: %u\n", freq);
1123 dev_dbg(cs35l41->dev, "Set DAI sysclk %d\n", freq);
1125 if (freq <= 6144000) {
1126 /* Use the lookup table */
1127 fs1_val = cs35l41_fs_mon[fsindex].fs1;
1128 fs2_val = cs35l41_fs_mon[fsindex].fs2;
1130 /* Use hard-coded values */
1136 val |= (fs2_val << CS35L41_FS2_WINDOW_SHIFT) & CS35L41_FS2_WINDOW_MASK;
1137 regmap_write(cs35l41->regmap, CS35L41_TST_FS_MON0, val);
1142 static int cs35l41_boost_config(struct cs35l41_private *cs35l41,
1143 int boost_ind, int boost_cap, int boost_ipk)
1145 unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled;
1146 struct regmap *regmap = cs35l41->regmap;
1147 struct device *dev = cs35l41->dev;
1150 switch (boost_ind) {
1151 case 1000: /* 1.0 uH */
1154 case 1200: /* 1.2 uH */
1157 case 1500: /* 1.5 uH */
1160 case 2200: /* 2.2 uH */
1164 dev_err(dev, "Invalid boost inductor value: %d nH\n", boost_ind);
1168 switch (boost_cap) {
1181 default: /* 201 uF and greater */
1185 ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_COEFF,
1186 CS35L41_BST_K1_MASK | CS35L41_BST_K2_MASK,
1187 cs35l41_bst_k1_table[bst_lbst_val][bst_cbst_range]
1188 << CS35L41_BST_K1_SHIFT |
1189 cs35l41_bst_k2_table[bst_lbst_val][bst_cbst_range]
1190 << CS35L41_BST_K2_SHIFT);
1192 dev_err(dev, "Failed to write boost coefficients: %d\n", ret);
1196 ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_SLOPE_LBST,
1197 CS35L41_BST_SLOPE_MASK | CS35L41_BST_LBST_VAL_MASK,
1198 cs35l41_bst_slope_table[bst_lbst_val]
1199 << CS35L41_BST_SLOPE_SHIFT |
1200 bst_lbst_val << CS35L41_BST_LBST_VAL_SHIFT);
1202 dev_err(dev, "Failed to write boost slope/inductor value: %d\n", ret);
1206 if (boost_ipk < 1600 || boost_ipk > 4500) {
1207 dev_err(dev, "Invalid boost inductor peak current: %d mA\n",
1211 bst_ipk_scaled = ((boost_ipk - 1600) / 50) + 0x10;
1213 ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_PEAK_CUR,
1214 CS35L41_BST_IPK_MASK,
1215 bst_ipk_scaled << CS35L41_BST_IPK_SHIFT);
1217 dev_err(dev, "Failed to write boost inductor peak current: %d\n", ret);
1224 static int cs35l41_set_pdata(struct cs35l41_private *cs35l41)
1228 /* Set Platform Data */
1230 if (cs35l41->pdata.bst_ipk &&
1231 cs35l41->pdata.bst_ind && cs35l41->pdata.bst_cap) {
1232 ret = cs35l41_boost_config(cs35l41, cs35l41->pdata.bst_ind,
1233 cs35l41->pdata.bst_cap,
1234 cs35l41->pdata.bst_ipk);
1236 dev_err(cs35l41->dev, "Error in Boost DT config: %d\n", ret);
1240 dev_err(cs35l41->dev, "Incomplete Boost component DT config\n");
1245 if (cs35l41->pdata.dout_hiz <= CS35L41_ASP_DOUT_HIZ_MASK &&
1246 cs35l41->pdata.dout_hiz >= 0)
1247 regmap_update_bits(cs35l41->regmap, CS35L41_SP_HIZ_CTRL,
1248 CS35L41_ASP_DOUT_HIZ_MASK,
1249 cs35l41->pdata.dout_hiz);
1254 static int cs35l41_irq_gpio_config(struct cs35l41_private *cs35l41)
1256 struct cs35l41_irq_cfg *irq_gpio_cfg1 = &cs35l41->pdata.irq_config1;
1257 struct cs35l41_irq_cfg *irq_gpio_cfg2 = &cs35l41->pdata.irq_config2;
1258 int irq_pol = IRQF_TRIGGER_NONE;
1260 regmap_update_bits(cs35l41->regmap, CS35L41_GPIO1_CTRL1,
1261 CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
1262 irq_gpio_cfg1->irq_pol_inv << CS35L41_GPIO_POL_SHIFT |
1263 !irq_gpio_cfg1->irq_out_en << CS35L41_GPIO_DIR_SHIFT);
1265 regmap_update_bits(cs35l41->regmap, CS35L41_GPIO2_CTRL1,
1266 CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
1267 irq_gpio_cfg1->irq_pol_inv << CS35L41_GPIO_POL_SHIFT |
1268 !irq_gpio_cfg1->irq_out_en << CS35L41_GPIO_DIR_SHIFT);
1270 regmap_update_bits(cs35l41->regmap, CS35L41_GPIO_PAD_CONTROL,
1271 CS35L41_GPIO1_CTRL_MASK | CS35L41_GPIO2_CTRL_MASK,
1272 irq_gpio_cfg1->irq_src_sel << CS35L41_GPIO1_CTRL_SHIFT |
1273 irq_gpio_cfg2->irq_src_sel << CS35L41_GPIO2_CTRL_SHIFT);
1275 if ((irq_gpio_cfg2->irq_src_sel ==
1276 (CS35L41_GPIO_CTRL_ACTV_LO | CS35L41_VALID_PDATA)) ||
1277 (irq_gpio_cfg2->irq_src_sel ==
1278 (CS35L41_GPIO_CTRL_OPEN_INT | CS35L41_VALID_PDATA)))
1279 irq_pol = IRQF_TRIGGER_LOW;
1280 else if (irq_gpio_cfg2->irq_src_sel ==
1281 (CS35L41_GPIO_CTRL_ACTV_HI | CS35L41_VALID_PDATA))
1282 irq_pol = IRQF_TRIGGER_HIGH;
1287 static int cs35l41_component_probe(struct snd_soc_component *component)
1289 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
1291 return wm_adsp2_component_probe(&cs35l41->dsp, component);
1294 static void cs35l41_component_remove(struct snd_soc_component *component)
1296 struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component);
1298 wm_adsp2_component_remove(&cs35l41->dsp, component);
1301 static const struct snd_soc_dai_ops cs35l41_ops = {
1302 .startup = cs35l41_pcm_startup,
1303 .set_fmt = cs35l41_set_dai_fmt,
1304 .hw_params = cs35l41_pcm_hw_params,
1305 .set_sysclk = cs35l41_dai_set_sysclk,
1306 .set_channel_map = cs35l41_set_channel_map,
1309 static struct snd_soc_dai_driver cs35l41_dai[] = {
1311 .name = "cs35l41-pcm",
1314 .stream_name = "AMP Playback",
1317 .rates = SNDRV_PCM_RATE_KNOT,
1318 .formats = CS35L41_RX_FORMATS,
1321 .stream_name = "AMP Capture",
1324 .rates = SNDRV_PCM_RATE_KNOT,
1325 .formats = CS35L41_TX_FORMATS,
1327 .ops = &cs35l41_ops,
1328 .symmetric_rate = 1,
1332 static const struct snd_soc_component_driver soc_component_dev_cs35l41 = {
1333 .name = "cs35l41-codec",
1334 .probe = cs35l41_component_probe,
1335 .remove = cs35l41_component_remove,
1337 .dapm_widgets = cs35l41_dapm_widgets,
1338 .num_dapm_widgets = ARRAY_SIZE(cs35l41_dapm_widgets),
1339 .dapm_routes = cs35l41_audio_map,
1340 .num_dapm_routes = ARRAY_SIZE(cs35l41_audio_map),
1342 .controls = cs35l41_aud_controls,
1343 .num_controls = ARRAY_SIZE(cs35l41_aud_controls),
1344 .set_sysclk = cs35l41_component_set_sysclk,
1347 static int cs35l41_handle_pdata(struct device *dev,
1348 struct cs35l41_platform_data *pdata,
1349 struct cs35l41_private *cs35l41)
1351 struct cs35l41_irq_cfg *irq_gpio1_config = &pdata->irq_config1;
1352 struct cs35l41_irq_cfg *irq_gpio2_config = &pdata->irq_config2;
1356 ret = device_property_read_u32(dev, "cirrus,boost-peak-milliamp", &val);
1358 pdata->bst_ipk = val;
1360 ret = device_property_read_u32(dev, "cirrus,boost-ind-nanohenry", &val);
1362 pdata->bst_ind = val;
1364 ret = device_property_read_u32(dev, "cirrus,boost-cap-microfarad", &val);
1366 pdata->bst_cap = val;
1368 ret = device_property_read_u32(dev, "cirrus,asp-sdout-hiz", &val);
1370 pdata->dout_hiz = val;
1372 pdata->dout_hiz = -1;
1374 /* GPIO1 Pin Config */
1375 irq_gpio1_config->irq_pol_inv = device_property_read_bool(dev,
1376 "cirrus,gpio1-polarity-invert");
1377 irq_gpio1_config->irq_out_en = device_property_read_bool(dev,
1378 "cirrus,gpio1-output-enable");
1379 ret = device_property_read_u32(dev, "cirrus,gpio1-src-select",
1382 irq_gpio1_config->irq_src_sel = val | CS35L41_VALID_PDATA;
1384 /* GPIO2 Pin Config */
1385 irq_gpio2_config->irq_pol_inv = device_property_read_bool(dev,
1386 "cirrus,gpio2-polarity-invert");
1387 irq_gpio2_config->irq_out_en = device_property_read_bool(dev,
1388 "cirrus,gpio2-output-enable");
1389 ret = device_property_read_u32(dev, "cirrus,gpio2-src-select",
1392 irq_gpio2_config->irq_src_sel = val | CS35L41_VALID_PDATA;
1397 static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
1398 { 0x00000040, 0x00005555 },
1399 { 0x00000040, 0x0000AAAA },
1400 { 0x00003854, 0x05180240 },
1401 { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
1402 { 0x00004310, 0x00000000 },
1403 { CS35L41_VPVBST_FS_SEL, 0x00000000 },
1404 { CS35L41_OTP_TRIM_30, 0x9091A1C8 },
1405 { 0x00003014, 0x0200EE0E },
1406 { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
1407 { 0x00000054, 0x00000004 },
1408 { CS35L41_IRQ1_DB3, 0x00000000 },
1409 { CS35L41_IRQ2_DB3, 0x00000000 },
1410 { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
1411 { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
1412 { 0x00000040, 0x0000CCCC },
1413 { 0x00000040, 0x00003333 },
1416 static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
1417 { 0x00000040, 0x00005555 },
1418 { 0x00000040, 0x0000AAAA },
1419 { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
1420 { 0x00004310, 0x00000000 },
1421 { CS35L41_VPVBST_FS_SEL, 0x00000000 },
1422 { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
1423 { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
1424 { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
1425 { 0x00000040, 0x0000CCCC },
1426 { 0x00000040, 0x00003333 },
1429 static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
1430 { 0x00000040, 0x00005555 },
1431 { 0x00000040, 0x0000AAAA },
1432 { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
1433 { 0x00004310, 0x00000000 },
1434 { CS35L41_VPVBST_FS_SEL, 0x00000000 },
1435 { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
1436 { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
1437 { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
1438 { 0x00000040, 0x0000CCCC },
1439 { 0x00000040, 0x00003333 },
1442 static const struct reg_sequence cs35l41_fs_errata_patch[] = {
1443 { CS35L41_DSP1_RX1_RATE, 0x00000001 },
1444 { CS35L41_DSP1_RX2_RATE, 0x00000001 },
1445 { CS35L41_DSP1_RX3_RATE, 0x00000001 },
1446 { CS35L41_DSP1_RX4_RATE, 0x00000001 },
1447 { CS35L41_DSP1_RX5_RATE, 0x00000001 },
1448 { CS35L41_DSP1_RX6_RATE, 0x00000001 },
1449 { CS35L41_DSP1_RX7_RATE, 0x00000001 },
1450 { CS35L41_DSP1_RX8_RATE, 0x00000001 },
1451 { CS35L41_DSP1_TX1_RATE, 0x00000001 },
1452 { CS35L41_DSP1_TX2_RATE, 0x00000001 },
1453 { CS35L41_DSP1_TX3_RATE, 0x00000001 },
1454 { CS35L41_DSP1_TX4_RATE, 0x00000001 },
1455 { CS35L41_DSP1_TX5_RATE, 0x00000001 },
1456 { CS35L41_DSP1_TX6_RATE, 0x00000001 },
1457 { CS35L41_DSP1_TX7_RATE, 0x00000001 },
1458 { CS35L41_DSP1_TX8_RATE, 0x00000001 },
1461 static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
1463 struct wm_adsp *dsp;
1466 dsp = &cs35l41->dsp;
1467 dsp->part = "cs35l41";
1468 dsp->cs_dsp.num = 1;
1469 dsp->cs_dsp.type = WMFW_HALO;
1470 dsp->cs_dsp.rev = 0;
1471 dsp->fw = 9; /* 9 is WM_ADSP_FW_SPK_PROT in wm_adsp.c */
1472 dsp->cs_dsp.dev = cs35l41->dev;
1473 dsp->cs_dsp.regmap = cs35l41->regmap;
1474 dsp->cs_dsp.base = CS35L41_DSP1_CTRL_BASE;
1475 dsp->cs_dsp.base_sysinfo = CS35L41_DSP1_SYS_ID;
1476 dsp->cs_dsp.mem = cs35l41_dsp1_regions;
1477 dsp->cs_dsp.num_mems = ARRAY_SIZE(cs35l41_dsp1_regions);
1478 dsp->cs_dsp.lock_regions = 0xFFFFFFFF;
1480 ret = regmap_multi_reg_write(cs35l41->regmap, cs35l41_fs_errata_patch,
1481 ARRAY_SIZE(cs35l41_fs_errata_patch));
1483 dev_err(cs35l41->dev, "Failed to write fs errata: %d\n", ret);
1487 ret = wm_halo_init(dsp);
1489 dev_err(cs35l41->dev, "wm_halo_init failed: %d\n", ret);
1493 ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC,
1494 CS35L41_INPUT_SRC_VPMON);
1496 dev_err(cs35l41->dev, "Write INPUT_SRC_VPMON failed: %d\n", ret);
1499 ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC,
1500 CS35L41_INPUT_SRC_CLASSH);
1502 dev_err(cs35l41->dev, "Write INPUT_SRC_CLASSH failed: %d\n", ret);
1505 ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX7_SRC,
1506 CS35L41_INPUT_SRC_TEMPMON);
1508 dev_err(cs35l41->dev, "Write INPUT_SRC_TEMPMON failed: %d\n", ret);
1511 ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX8_SRC,
1512 CS35L41_INPUT_SRC_RSVD);
1514 dev_err(cs35l41->dev, "Write INPUT_SRC_RSVD failed: %d\n", ret);
1521 wm_adsp2_remove(dsp);
1526 int cs35l41_probe(struct cs35l41_private *cs35l41,
1527 struct cs35l41_platform_data *pdata)
1529 u32 regid, reg_revid, i, mtl_revid, int_status, chipid_match;
1534 cs35l41->pdata = *pdata;
1536 ret = cs35l41_handle_pdata(cs35l41->dev, &cs35l41->pdata, cs35l41);
1541 for (i = 0; i < CS35L41_NUM_SUPPLIES; i++)
1542 cs35l41->supplies[i].supply = cs35l41_supplies[i];
1544 ret = devm_regulator_bulk_get(cs35l41->dev, CS35L41_NUM_SUPPLIES,
1547 dev_err(cs35l41->dev, "Failed to request core supplies: %d\n", ret);
1551 ret = regulator_bulk_enable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
1553 dev_err(cs35l41->dev, "Failed to enable core supplies: %d\n", ret);
1557 /* returning NULL can be an option if in stereo mode */
1558 cs35l41->reset_gpio = devm_gpiod_get_optional(cs35l41->dev, "reset",
1560 if (IS_ERR(cs35l41->reset_gpio)) {
1561 ret = PTR_ERR(cs35l41->reset_gpio);
1562 cs35l41->reset_gpio = NULL;
1563 if (ret == -EBUSY) {
1564 dev_info(cs35l41->dev,
1565 "Reset line busy, assuming shared reset\n");
1567 dev_err(cs35l41->dev,
1568 "Failed to get reset GPIO: %d\n", ret);
1572 if (cs35l41->reset_gpio) {
1573 /* satisfy minimum reset pulse width spec */
1574 usleep_range(2000, 2100);
1575 gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);
1578 usleep_range(2000, 2100);
1580 ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4,
1581 int_status, int_status & CS35L41_OTP_BOOT_DONE,
1584 dev_err(cs35l41->dev,
1585 "Failed waiting for OTP_BOOT_DONE: %d\n", ret);
1589 regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_status);
1590 if (int_status & CS35L41_OTP_BOOT_ERR) {
1591 dev_err(cs35l41->dev, "OTP Boot error\n");
1596 ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, ®id);
1598 dev_err(cs35l41->dev, "Get Device ID failed: %d\n", ret);
1602 ret = regmap_read(cs35l41->regmap, CS35L41_REVID, ®_revid);
1604 dev_err(cs35l41->dev, "Get Revision ID failed: %d\n", ret);
1608 mtl_revid = reg_revid & CS35L41_MTLREVID_MASK;
1610 /* CS35L41 will have even MTLREVID
1611 * CS35L41R will have odd MTLREVID
1613 chipid_match = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;
1614 if (regid != chipid_match) {
1615 dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n",
1616 regid, chipid_match);
1621 switch (reg_revid) {
1622 case CS35L41_REVID_A0:
1623 ret = regmap_register_patch(cs35l41->regmap,
1624 cs35l41_reva0_errata_patch,
1625 ARRAY_SIZE(cs35l41_reva0_errata_patch));
1627 dev_err(cs35l41->dev,
1628 "Failed to apply A0 errata patch: %d\n", ret);
1632 case CS35L41_REVID_B0:
1633 ret = regmap_register_patch(cs35l41->regmap,
1634 cs35l41_revb0_errata_patch,
1635 ARRAY_SIZE(cs35l41_revb0_errata_patch));
1637 dev_err(cs35l41->dev,
1638 "Failed to apply B0 errata patch: %d\n", ret);
1642 case CS35L41_REVID_B2:
1643 ret = regmap_register_patch(cs35l41->regmap,
1644 cs35l41_revb2_errata_patch,
1645 ARRAY_SIZE(cs35l41_revb2_errata_patch));
1647 dev_err(cs35l41->dev,
1648 "Failed to apply B2 errata patch: %d\n", ret);
1654 irq_pol = cs35l41_irq_gpio_config(cs35l41);
1656 /* Set interrupt masks for critical errors */
1657 regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1,
1658 CS35L41_INT1_MASK_DEFAULT);
1660 ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq,
1661 IRQF_ONESHOT | IRQF_SHARED | irq_pol,
1662 "cs35l41", cs35l41);
1664 /* CS35L41 needs INT for PDN_DONE */
1666 dev_err(cs35l41->dev, "Failed to request IRQ: %d\n", ret);
1670 ret = cs35l41_otp_unpack(cs35l41);
1672 dev_err(cs35l41->dev, "OTP Unpack failed: %d\n", ret);
1676 ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_CCM_CORE_CTRL, 0);
1678 dev_err(cs35l41->dev, "Write CCM_CORE_CTRL failed: %d\n", ret);
1682 ret = regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2,
1683 CS35L41_AMP_EN_MASK, 0);
1685 dev_err(cs35l41->dev, "Write CS35L41_PWR_CTRL2 failed: %d\n", ret);
1689 ret = regmap_update_bits(cs35l41->regmap, CS35L41_AMP_GAIN_CTRL,
1690 CS35L41_AMP_GAIN_PCM_MASK, 0);
1692 dev_err(cs35l41->dev, "Write CS35L41_AMP_GAIN_CTRL failed: %d\n", ret);
1696 ret = cs35l41_set_pdata(cs35l41);
1698 dev_err(cs35l41->dev, "Set pdata failed: %d\n", ret);
1702 ret = cs35l41_dsp_init(cs35l41);
1706 ret = devm_snd_soc_register_component(cs35l41->dev,
1707 &soc_component_dev_cs35l41,
1708 cs35l41_dai, ARRAY_SIZE(cs35l41_dai));
1710 dev_err(cs35l41->dev, "Register codec failed: %d\n", ret);
1714 dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n",
1720 wm_adsp2_remove(&cs35l41->dsp);
1722 regulator_bulk_disable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
1723 gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
1727 EXPORT_SYMBOL_GPL(cs35l41_probe);
1729 void cs35l41_remove(struct cs35l41_private *cs35l41)
1731 regmap_write(cs35l41->regmap, CS35L41_IRQ1_MASK1, 0xFFFFFFFF);
1732 wm_adsp2_remove(&cs35l41->dsp);
1733 regulator_bulk_disable(CS35L41_NUM_SUPPLIES, cs35l41->supplies);
1734 gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
1736 EXPORT_SYMBOL_GPL(cs35l41_remove);
1738 MODULE_DESCRIPTION("ASoC CS35L41 driver");
1739 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
1740 MODULE_LICENSE("GPL");