root/sound/soc/codecs/madera.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. madera_spin_sysclk
  2. madera_sysclk_ev
  3. madera_check_speaker_overheat
  4. madera_spk_ev
  5. madera_thermal_warn
  6. madera_init_overheat
  7. madera_free_overheat
  8. madera_get_variable_u32_array
  9. madera_prop_get_inmode
  10. madera_prop_get_pdata
  11. madera_core_init
  12. madera_core_free
  13. madera_debug_dump_domain_groups
  14. madera_domain_clk_ev
  15. madera_out1_demux_put
  16. madera_out1_demux_get
  17. madera_inmux_put
  18. madera_can_change_grp_rate
  19. madera_adsp_rate_get
  20. madera_adsp_rate_put
  21. madera_write_adsp_clk_setting
  22. madera_set_adsp_clk
  23. madera_rate_put
  24. madera_configure_input_mode
  25. madera_init_inputs
  26. madera_init_outputs
  27. madera_init_bus_error_irq
  28. madera_free_bus_error_irq
  29. madera_dfc_put
  30. madera_lp_mode_put
  31. madera_in_set_vu
  32. madera_in_ev
  33. madera_out_ev
  34. madera_hp_ev
  35. madera_anc_ev
  36. madera_set_opclk
  37. madera_get_sysclk_setting
  38. madera_get_legacy_dspclk_setting
  39. madera_get_dspclk_setting
  40. madera_set_outclk
  41. madera_set_sysclk
  42. madera_set_fmt
  43. madera_startup
  44. madera_hw_params_rate
  45. madera_aif_cfg_changed
  46. madera_hw_params
  47. madera_is_syncclk
  48. madera_dai_set_sysclk
  49. madera_set_tristate
  50. madera_set_channels_to_mask
  51. madera_set_tdm_slot
  52. madera_init_dai
  53. madera_find_sync_fratio
  54. madera_find_main_fratio
  55. madera_find_fratio
  56. madera_calc_fratio
  57. madera_find_fll_gain
  58. madera_calc_fll
  59. madera_write_fll
  60. madera_is_enabled_fll
  61. madera_wait_for_fll
  62. madera_set_fll_phase_integrator
  63. madera_disable_fll
  64. madera_enable_fll
  65. madera_apply_fll
  66. madera_set_fll_syncclk
  67. madera_set_fll_refclk
  68. madera_init_fll
  69. madera_enable_fll_ao
  70. madera_disable_fll_ao
  71. madera_set_fll_ao_refclk
  72. madera_fllhj_disable
  73. madera_fllhj_apply
  74. madera_fllhj_enable
  75. madera_fllhj_validate
  76. madera_fllhj_set_refclk
  77. madera_set_output_mode
  78. madera_eq_filter_unstable
  79. madera_eq_coeff_put
  80. madera_lhpf_coeff_put

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 //
   3 // Cirrus Logic Madera class codecs common support
   4 //
   5 // Copyright (C) 2015-2019 Cirrus Logic, Inc. and
   6 //                         Cirrus Logic International Semiconductor Ltd.
   7 //
   8 
   9 #include <linux/delay.h>
  10 #include <linux/gcd.h>
  11 #include <linux/module.h>
  12 #include <linux/pm_runtime.h>
  13 #include <linux/slab.h>
  14 #include <sound/pcm.h>
  15 #include <sound/pcm_params.h>
  16 #include <sound/tlv.h>
  17 
  18 #include <linux/irqchip/irq-madera.h>
  19 #include <linux/mfd/madera/core.h>
  20 #include <linux/mfd/madera/registers.h>
  21 #include <linux/mfd/madera/pdata.h>
  22 #include <sound/madera-pdata.h>
  23 
  24 #include <dt-bindings/sound/madera.h>
  25 
  26 #include "madera.h"
  27 
  28 #define MADERA_AIF_BCLK_CTRL                    0x00
  29 #define MADERA_AIF_TX_PIN_CTRL                  0x01
  30 #define MADERA_AIF_RX_PIN_CTRL                  0x02
  31 #define MADERA_AIF_RATE_CTRL                    0x03
  32 #define MADERA_AIF_FORMAT                       0x04
  33 #define MADERA_AIF_RX_BCLK_RATE                 0x06
  34 #define MADERA_AIF_FRAME_CTRL_1                 0x07
  35 #define MADERA_AIF_FRAME_CTRL_2                 0x08
  36 #define MADERA_AIF_FRAME_CTRL_3                 0x09
  37 #define MADERA_AIF_FRAME_CTRL_4                 0x0A
  38 #define MADERA_AIF_FRAME_CTRL_5                 0x0B
  39 #define MADERA_AIF_FRAME_CTRL_6                 0x0C
  40 #define MADERA_AIF_FRAME_CTRL_7                 0x0D
  41 #define MADERA_AIF_FRAME_CTRL_8                 0x0E
  42 #define MADERA_AIF_FRAME_CTRL_9                 0x0F
  43 #define MADERA_AIF_FRAME_CTRL_10                0x10
  44 #define MADERA_AIF_FRAME_CTRL_11                0x11
  45 #define MADERA_AIF_FRAME_CTRL_12                0x12
  46 #define MADERA_AIF_FRAME_CTRL_13                0x13
  47 #define MADERA_AIF_FRAME_CTRL_14                0x14
  48 #define MADERA_AIF_FRAME_CTRL_15                0x15
  49 #define MADERA_AIF_FRAME_CTRL_16                0x16
  50 #define MADERA_AIF_FRAME_CTRL_17                0x17
  51 #define MADERA_AIF_FRAME_CTRL_18                0x18
  52 #define MADERA_AIF_TX_ENABLES                   0x19
  53 #define MADERA_AIF_RX_ENABLES                   0x1A
  54 #define MADERA_AIF_FORCE_WRITE                  0x1B
  55 
  56 #define MADERA_DSP_CONFIG_1_OFFS                0x00
  57 #define MADERA_DSP_CONFIG_2_OFFS                0x02
  58 
  59 #define MADERA_DSP_CLK_SEL_MASK                 0x70000
  60 #define MADERA_DSP_CLK_SEL_SHIFT                16
  61 
  62 #define MADERA_DSP_RATE_MASK                    0x7800
  63 #define MADERA_DSP_RATE_SHIFT                   11
  64 
  65 #define MADERA_SYSCLK_6MHZ                      0
  66 #define MADERA_SYSCLK_12MHZ                     1
  67 #define MADERA_SYSCLK_24MHZ                     2
  68 #define MADERA_SYSCLK_49MHZ                     3
  69 #define MADERA_SYSCLK_98MHZ                     4
  70 
  71 #define MADERA_DSPCLK_9MHZ                      0
  72 #define MADERA_DSPCLK_18MHZ                     1
  73 #define MADERA_DSPCLK_36MHZ                     2
  74 #define MADERA_DSPCLK_73MHZ                     3
  75 #define MADERA_DSPCLK_147MHZ                    4
  76 
  77 #define MADERA_FLL_VCO_CORNER                   141900000
  78 #define MADERA_FLL_MAX_FREF                     13500000
  79 #define MADERA_FLL_MAX_N                        1023
  80 #define MADERA_FLL_MIN_FOUT                     90000000
  81 #define MADERA_FLL_MAX_FOUT                     100000000
  82 #define MADERA_FLL_MAX_FRATIO                   16
  83 #define MADERA_FLL_MAX_REFDIV                   8
  84 #define MADERA_FLL_OUTDIV                       3
  85 #define MADERA_FLL_VCO_MULT                     3
  86 #define MADERA_FLLAO_MAX_FREF                   12288000
  87 #define MADERA_FLLAO_MIN_N                      4
  88 #define MADERA_FLLAO_MAX_N                      1023
  89 #define MADERA_FLLAO_MAX_FBDIV                  254
  90 #define MADERA_FLLHJ_INT_MAX_N                  1023
  91 #define MADERA_FLLHJ_INT_MIN_N                  1
  92 #define MADERA_FLLHJ_FRAC_MAX_N                 255
  93 #define MADERA_FLLHJ_FRAC_MIN_N                 4
  94 #define MADERA_FLLHJ_LOW_THRESH                 192000
  95 #define MADERA_FLLHJ_MID_THRESH                 1152000
  96 #define MADERA_FLLHJ_MAX_THRESH                 13000000
  97 #define MADERA_FLLHJ_LOW_GAINS                  0x23f0
  98 #define MADERA_FLLHJ_MID_GAINS                  0x22f2
  99 #define MADERA_FLLHJ_HIGH_GAINS                 0x21f0
 100 
 101 #define MADERA_FLL_SYNCHRONISER_OFFS            0x10
 102 #define CS47L35_FLL_SYNCHRONISER_OFFS           0xE
 103 #define MADERA_FLL_CONTROL_1_OFFS               0x1
 104 #define MADERA_FLL_CONTROL_2_OFFS               0x2
 105 #define MADERA_FLL_CONTROL_3_OFFS               0x3
 106 #define MADERA_FLL_CONTROL_4_OFFS               0x4
 107 #define MADERA_FLL_CONTROL_5_OFFS               0x5
 108 #define MADERA_FLL_CONTROL_6_OFFS               0x6
 109 #define MADERA_FLL_GAIN_OFFS                    0x8
 110 #define MADERA_FLL_CONTROL_7_OFFS               0x9
 111 #define MADERA_FLL_EFS_2_OFFS                   0xA
 112 #define MADERA_FLL_SYNCHRONISER_1_OFFS          0x1
 113 #define MADERA_FLL_SYNCHRONISER_2_OFFS          0x2
 114 #define MADERA_FLL_SYNCHRONISER_3_OFFS          0x3
 115 #define MADERA_FLL_SYNCHRONISER_4_OFFS          0x4
 116 #define MADERA_FLL_SYNCHRONISER_5_OFFS          0x5
 117 #define MADERA_FLL_SYNCHRONISER_6_OFFS          0x6
 118 #define MADERA_FLL_SYNCHRONISER_7_OFFS          0x7
 119 #define MADERA_FLL_SPREAD_SPECTRUM_OFFS         0x9
 120 #define MADERA_FLL_GPIO_CLOCK_OFFS              0xA
 121 #define MADERA_FLL_CONTROL_10_OFFS              0xA
 122 #define MADERA_FLL_CONTROL_11_OFFS              0xB
 123 #define MADERA_FLL1_DIGITAL_TEST_1_OFFS         0xD
 124 
 125 #define MADERA_FLLAO_CONTROL_1_OFFS             0x1
 126 #define MADERA_FLLAO_CONTROL_2_OFFS             0x2
 127 #define MADERA_FLLAO_CONTROL_3_OFFS             0x3
 128 #define MADERA_FLLAO_CONTROL_4_OFFS             0x4
 129 #define MADERA_FLLAO_CONTROL_5_OFFS             0x5
 130 #define MADERA_FLLAO_CONTROL_6_OFFS             0x6
 131 #define MADERA_FLLAO_CONTROL_7_OFFS             0x8
 132 #define MADERA_FLLAO_CONTROL_8_OFFS             0xA
 133 #define MADERA_FLLAO_CONTROL_9_OFFS             0xB
 134 #define MADERA_FLLAO_CONTROL_10_OFFS            0xC
 135 #define MADERA_FLLAO_CONTROL_11_OFFS            0xD
 136 
 137 #define MADERA_FMT_DSP_MODE_A                   0
 138 #define MADERA_FMT_DSP_MODE_B                   1
 139 #define MADERA_FMT_I2S_MODE                     2
 140 #define MADERA_FMT_LEFT_JUSTIFIED_MODE          3
 141 
 142 #define madera_fll_err(_fll, fmt, ...) \
 143         dev_err(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
 144 #define madera_fll_warn(_fll, fmt, ...) \
 145         dev_warn(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
 146 #define madera_fll_dbg(_fll, fmt, ...) \
 147         dev_dbg(_fll->madera->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
 148 
 149 #define madera_aif_err(_dai, fmt, ...) \
 150         dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
 151 #define madera_aif_warn(_dai, fmt, ...) \
 152         dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
 153 #define madera_aif_dbg(_dai, fmt, ...) \
 154         dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
 155 
 156 static const int madera_dsp_bus_error_irqs[MADERA_MAX_ADSP] = {
 157         MADERA_IRQ_DSP1_BUS_ERR,
 158         MADERA_IRQ_DSP2_BUS_ERR,
 159         MADERA_IRQ_DSP3_BUS_ERR,
 160         MADERA_IRQ_DSP4_BUS_ERR,
 161         MADERA_IRQ_DSP5_BUS_ERR,
 162         MADERA_IRQ_DSP6_BUS_ERR,
 163         MADERA_IRQ_DSP7_BUS_ERR,
 164 };
 165 
 166 static void madera_spin_sysclk(struct madera_priv *priv)
 167 {
 168         struct madera *madera = priv->madera;
 169         unsigned int val;
 170         int ret, i;
 171 
 172         /* Skip this if the chip is down */
 173         if (pm_runtime_suspended(madera->dev))
 174                 return;
 175 
 176         /*
 177          * Just read a register a few times to ensure the internal
 178          * oscillator sends out a few clocks.
 179          */
 180         for (i = 0; i < 4; i++) {
 181                 ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &val);
 182                 if (ret)
 183                         dev_err(madera->dev,
 184                                 "Failed to read sysclk spin %d: %d\n", i, ret);
 185         }
 186 
 187         udelay(300);
 188 }
 189 
 190 int madera_sysclk_ev(struct snd_soc_dapm_widget *w,
 191                      struct snd_kcontrol *kcontrol, int event)
 192 {
 193         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 194         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 195 
 196         madera_spin_sysclk(priv);
 197 
 198         return 0;
 199 }
 200 EXPORT_SYMBOL_GPL(madera_sysclk_ev);
 201 
 202 static int madera_check_speaker_overheat(struct madera *madera,
 203                                          bool *warn, bool *shutdown)
 204 {
 205         unsigned int val;
 206         int ret;
 207 
 208         ret = regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_15, &val);
 209         if (ret) {
 210                 dev_err(madera->dev, "Failed to read thermal status: %d\n",
 211                         ret);
 212                 return ret;
 213         }
 214 
 215         *warn = val & MADERA_SPK_OVERHEAT_WARN_STS1;
 216         *shutdown = val & MADERA_SPK_OVERHEAT_STS1;
 217 
 218         return 0;
 219 }
 220 
 221 int madera_spk_ev(struct snd_soc_dapm_widget *w,
 222                   struct snd_kcontrol *kcontrol, int event)
 223 {
 224         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 225         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 226         struct madera *madera = priv->madera;
 227         bool warn, shutdown;
 228         int ret;
 229 
 230         switch (event) {
 231         case SND_SOC_DAPM_POST_PMU:
 232                 ret = madera_check_speaker_overheat(madera, &warn, &shutdown);
 233                 if (ret)
 234                         return ret;
 235 
 236                 if (shutdown) {
 237                         dev_crit(madera->dev,
 238                                  "Speaker not enabled due to temperature\n");
 239                         return -EBUSY;
 240                 }
 241 
 242                 regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
 243                                    1 << w->shift, 1 << w->shift);
 244                 break;
 245         case SND_SOC_DAPM_PRE_PMD:
 246                 regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
 247                                    1 << w->shift, 0);
 248                 break;
 249         default:
 250                 break;
 251         }
 252 
 253         return 0;
 254 }
 255 EXPORT_SYMBOL_GPL(madera_spk_ev);
 256 
 257 static irqreturn_t madera_thermal_warn(int irq, void *data)
 258 {
 259         struct madera *madera = data;
 260         bool warn, shutdown;
 261         int ret;
 262 
 263         ret = madera_check_speaker_overheat(madera, &warn, &shutdown);
 264         if (ret || shutdown) { /* for safety attempt to shutdown on error */
 265                 dev_crit(madera->dev, "Thermal shutdown\n");
 266                 ret = regmap_update_bits(madera->regmap,
 267                                          MADERA_OUTPUT_ENABLES_1,
 268                                          MADERA_OUT4L_ENA |
 269                                          MADERA_OUT4R_ENA, 0);
 270                 if (ret != 0)
 271                         dev_crit(madera->dev,
 272                                  "Failed to disable speaker outputs: %d\n",
 273                                  ret);
 274         } else if (warn) {
 275                 dev_alert(madera->dev, "Thermal warning\n");
 276         } else {
 277                 dev_info(madera->dev, "Spurious thermal warning\n");
 278                 return IRQ_NONE;
 279         }
 280 
 281         return IRQ_HANDLED;
 282 }
 283 
 284 int madera_init_overheat(struct madera_priv *priv)
 285 {
 286         struct madera *madera = priv->madera;
 287         struct device *dev = madera->dev;
 288         int ret;
 289 
 290         ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN,
 291                                  "Thermal warning", madera_thermal_warn,
 292                                  madera);
 293         if (ret)
 294                 dev_err(dev, "Failed to get thermal warning IRQ: %d\n", ret);
 295 
 296         ret = madera_request_irq(madera, MADERA_IRQ_SPK_OVERHEAT,
 297                                  "Thermal shutdown", madera_thermal_warn,
 298                                  madera);
 299         if (ret)
 300                 dev_err(dev, "Failed to get thermal shutdown IRQ: %d\n", ret);
 301 
 302         return 0;
 303 }
 304 EXPORT_SYMBOL_GPL(madera_init_overheat);
 305 
 306 int madera_free_overheat(struct madera_priv *priv)
 307 {
 308         struct madera *madera = priv->madera;
 309 
 310         madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT_WARN, madera);
 311         madera_free_irq(madera, MADERA_IRQ_SPK_OVERHEAT, madera);
 312 
 313         return 0;
 314 }
 315 EXPORT_SYMBOL_GPL(madera_free_overheat);
 316 
 317 static int madera_get_variable_u32_array(struct device *dev,
 318                                          const char *propname,
 319                                          u32 *dest, int n_max,
 320                                          int multiple)
 321 {
 322         int n, ret;
 323 
 324         n = device_property_count_u32(dev, propname);
 325         if (n < 0) {
 326                 if (n == -EINVAL)
 327                         return 0;       /* missing, ignore */
 328 
 329                 dev_warn(dev, "%s malformed (%d)\n", propname, n);
 330 
 331                 return n;
 332         } else if ((n % multiple) != 0) {
 333                 dev_warn(dev, "%s not a multiple of %d entries\n",
 334                          propname, multiple);
 335 
 336                 return -EINVAL;
 337         }
 338 
 339         if (n > n_max)
 340                 n = n_max;
 341 
 342         ret = device_property_read_u32_array(dev, propname, dest, n);
 343         if (ret < 0)
 344                 return ret;
 345 
 346         return n;
 347 }
 348 
 349 static void madera_prop_get_inmode(struct madera_priv *priv)
 350 {
 351         struct madera *madera = priv->madera;
 352         struct madera_codec_pdata *pdata = &madera->pdata.codec;
 353         u32 tmp[MADERA_MAX_INPUT * MADERA_MAX_MUXED_CHANNELS];
 354         int n, i, in_idx, ch_idx;
 355 
 356         BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode) != MADERA_MAX_INPUT);
 357         BUILD_BUG_ON(ARRAY_SIZE(pdata->inmode[0]) != MADERA_MAX_MUXED_CHANNELS);
 358 
 359         n = madera_get_variable_u32_array(madera->dev, "cirrus,inmode",
 360                                           tmp, ARRAY_SIZE(tmp),
 361                                           MADERA_MAX_MUXED_CHANNELS);
 362         if (n < 0)
 363                 return;
 364 
 365         in_idx = 0;
 366         ch_idx = 0;
 367         for (i = 0; i < n; ++i) {
 368                 pdata->inmode[in_idx][ch_idx] = tmp[i];
 369 
 370                 if (++ch_idx == MADERA_MAX_MUXED_CHANNELS) {
 371                         ch_idx = 0;
 372                         ++in_idx;
 373                 }
 374         }
 375 }
 376 
 377 static void madera_prop_get_pdata(struct madera_priv *priv)
 378 {
 379         struct madera *madera = priv->madera;
 380         struct madera_codec_pdata *pdata = &madera->pdata.codec;
 381         u32 out_mono[ARRAY_SIZE(pdata->out_mono)];
 382         int i, n;
 383 
 384         madera_prop_get_inmode(priv);
 385 
 386         n = madera_get_variable_u32_array(madera->dev, "cirrus,out-mono",
 387                                           out_mono, ARRAY_SIZE(out_mono), 1);
 388         if (n > 0)
 389                 for (i = 0; i < n; ++i)
 390                         pdata->out_mono[i] = !!out_mono[i];
 391 
 392         madera_get_variable_u32_array(madera->dev,
 393                                       "cirrus,max-channels-clocked",
 394                                       pdata->max_channels_clocked,
 395                                       ARRAY_SIZE(pdata->max_channels_clocked),
 396                                       1);
 397 
 398         madera_get_variable_u32_array(madera->dev, "cirrus,pdm-fmt",
 399                                       pdata->pdm_fmt,
 400                                       ARRAY_SIZE(pdata->pdm_fmt), 1);
 401 
 402         madera_get_variable_u32_array(madera->dev, "cirrus,pdm-mute",
 403                                       pdata->pdm_mute,
 404                                       ARRAY_SIZE(pdata->pdm_mute), 1);
 405 
 406         madera_get_variable_u32_array(madera->dev, "cirrus,dmic-ref",
 407                                       pdata->dmic_ref,
 408                                       ARRAY_SIZE(pdata->dmic_ref), 1);
 409 }
 410 
 411 int madera_core_init(struct madera_priv *priv)
 412 {
 413         int i;
 414 
 415         /* trap undersized array initializers */
 416         BUILD_BUG_ON(!madera_mixer_texts[MADERA_NUM_MIXER_INPUTS - 1]);
 417         BUILD_BUG_ON(!madera_mixer_values[MADERA_NUM_MIXER_INPUTS - 1]);
 418 
 419         if (!dev_get_platdata(priv->madera->dev))
 420                 madera_prop_get_pdata(priv);
 421 
 422         mutex_init(&priv->rate_lock);
 423 
 424         for (i = 0; i < MADERA_MAX_HP_OUTPUT; i++)
 425                 priv->madera->out_clamp[i] = true;
 426 
 427         return 0;
 428 }
 429 EXPORT_SYMBOL_GPL(madera_core_init);
 430 
 431 int madera_core_free(struct madera_priv *priv)
 432 {
 433         mutex_destroy(&priv->rate_lock);
 434 
 435         return 0;
 436 }
 437 EXPORT_SYMBOL_GPL(madera_core_free);
 438 
 439 static void madera_debug_dump_domain_groups(const struct madera_priv *priv)
 440 {
 441         struct madera *madera = priv->madera;
 442         int i;
 443 
 444         for (i = 0; i < ARRAY_SIZE(priv->domain_group_ref); ++i)
 445                 dev_dbg(madera->dev, "domain_grp_ref[%d]=%d\n", i,
 446                         priv->domain_group_ref[i]);
 447 }
 448 
 449 int madera_domain_clk_ev(struct snd_soc_dapm_widget *w,
 450                          struct snd_kcontrol *kcontrol,
 451                          int event)
 452 {
 453         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 454         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 455         int dom_grp = w->shift;
 456 
 457         if (dom_grp >= ARRAY_SIZE(priv->domain_group_ref)) {
 458                 WARN(true, "%s dom_grp exceeds array size\n", __func__);
 459                 return -EINVAL;
 460         }
 461 
 462         /*
 463          * We can't rely on the DAPM mutex for locking because we need a lock
 464          * that can safely be called in hw_params
 465          */
 466         mutex_lock(&priv->rate_lock);
 467 
 468         switch (event) {
 469         case SND_SOC_DAPM_PRE_PMU:
 470                 dev_dbg(priv->madera->dev, "Inc ref on domain group %d\n",
 471                         dom_grp);
 472                 ++priv->domain_group_ref[dom_grp];
 473                 break;
 474         case SND_SOC_DAPM_POST_PMD:
 475                 dev_dbg(priv->madera->dev, "Dec ref on domain group %d\n",
 476                         dom_grp);
 477                 --priv->domain_group_ref[dom_grp];
 478                 break;
 479         default:
 480                 break;
 481         }
 482 
 483         madera_debug_dump_domain_groups(priv);
 484 
 485         mutex_unlock(&priv->rate_lock);
 486 
 487         return 0;
 488 }
 489 EXPORT_SYMBOL_GPL(madera_domain_clk_ev);
 490 
 491 int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
 492                           struct snd_ctl_elem_value *ucontrol)
 493 {
 494         struct snd_soc_component *component =
 495                 snd_soc_dapm_kcontrol_component(kcontrol);
 496         struct snd_soc_dapm_context *dapm =
 497                 snd_soc_dapm_kcontrol_dapm(kcontrol);
 498         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 499         struct madera *madera = priv->madera;
 500         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 501         unsigned int ep_sel, mux, change;
 502         bool out_mono;
 503         int ret;
 504 
 505         if (ucontrol->value.enumerated.item[0] > e->items - 1)
 506                 return -EINVAL;
 507 
 508         mux = ucontrol->value.enumerated.item[0];
 509 
 510         snd_soc_dapm_mutex_lock(dapm);
 511 
 512         ep_sel = mux << MADERA_EP_SEL_SHIFT;
 513 
 514         change = snd_soc_component_test_bits(component, MADERA_OUTPUT_ENABLES_1,
 515                                              MADERA_EP_SEL_MASK,
 516                                              ep_sel);
 517         if (!change)
 518                 goto end;
 519 
 520         /* EP_SEL should not be modified while HP or EP driver is enabled */
 521         ret = regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1,
 522                                  MADERA_OUT1L_ENA | MADERA_OUT1R_ENA, 0);
 523         if (ret)
 524                 dev_warn(madera->dev, "Failed to disable outputs: %d\n", ret);
 525 
 526         usleep_range(2000, 3000); /* wait for wseq to complete */
 527 
 528         /* change demux setting */
 529         if (madera->out_clamp[0])
 530                 ret = regmap_update_bits(madera->regmap,
 531                                          MADERA_OUTPUT_ENABLES_1,
 532                                          MADERA_EP_SEL_MASK, ep_sel);
 533         if (ret) {
 534                 dev_err(madera->dev, "Failed to set OUT1 demux: %d\n", ret);
 535         } else {
 536                 /* apply correct setting for mono mode */
 537                 if (!ep_sel && !madera->pdata.codec.out_mono[0])
 538                         out_mono = false; /* stereo HP */
 539                 else
 540                         out_mono = true; /* EP or mono HP */
 541 
 542                 ret = madera_set_output_mode(component, 1, out_mono);
 543                 if (ret)
 544                         dev_warn(madera->dev,
 545                                  "Failed to set output mode: %d\n", ret);
 546         }
 547 
 548         /*
 549          * if HPDET has disabled the clamp while switching to HPOUT
 550          * OUT1 should remain disabled
 551          */
 552         if (ep_sel ||
 553             (madera->out_clamp[0] && !madera->out_shorted[0])) {
 554                 ret = regmap_update_bits(madera->regmap,
 555                                          MADERA_OUTPUT_ENABLES_1,
 556                                          MADERA_OUT1L_ENA | MADERA_OUT1R_ENA,
 557                                          madera->hp_ena);
 558                 if (ret)
 559                         dev_warn(madera->dev,
 560                                  "Failed to restore earpiece outputs: %d\n",
 561                                  ret);
 562                 else if (madera->hp_ena)
 563                         msleep(34); /* wait for enable wseq */
 564                 else
 565                         usleep_range(2000, 3000); /* wait for disable wseq */
 566         }
 567 
 568 end:
 569         snd_soc_dapm_mutex_unlock(dapm);
 570 
 571         return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
 572 }
 573 EXPORT_SYMBOL_GPL(madera_out1_demux_put);
 574 
 575 int madera_out1_demux_get(struct snd_kcontrol *kcontrol,
 576                           struct snd_ctl_elem_value *ucontrol)
 577 {
 578         struct snd_soc_component *component =
 579                 snd_soc_dapm_kcontrol_component(kcontrol);
 580         unsigned int val;
 581         int ret;
 582 
 583         ret = snd_soc_component_read(component, MADERA_OUTPUT_ENABLES_1, &val);
 584         if (ret)
 585                 return ret;
 586 
 587         val &= MADERA_EP_SEL_MASK;
 588         val >>= MADERA_EP_SEL_SHIFT;
 589         ucontrol->value.enumerated.item[0] = val;
 590 
 591         return 0;
 592 }
 593 EXPORT_SYMBOL_GPL(madera_out1_demux_get);
 594 
 595 static int madera_inmux_put(struct snd_kcontrol *kcontrol,
 596                             struct snd_ctl_elem_value *ucontrol)
 597 {
 598         struct snd_soc_component *component =
 599                 snd_soc_dapm_kcontrol_component(kcontrol);
 600         struct snd_soc_dapm_context *dapm =
 601                 snd_soc_dapm_kcontrol_dapm(kcontrol);
 602         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 603         struct madera *madera = priv->madera;
 604         struct regmap *regmap = madera->regmap;
 605         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 606         unsigned int mux, val, mask;
 607         unsigned int inmode;
 608         bool changed;
 609         int ret;
 610 
 611         mux = ucontrol->value.enumerated.item[0];
 612         if (mux > 1)
 613                 return -EINVAL;
 614 
 615         val = mux << e->shift_l;
 616         mask = (e->mask << e->shift_l) | MADERA_IN1L_SRC_SE_MASK;
 617 
 618         switch (e->reg) {
 619         case MADERA_ADC_DIGITAL_VOLUME_1L:
 620                 inmode = madera->pdata.codec.inmode[0][2 * mux];
 621                 break;
 622         case MADERA_ADC_DIGITAL_VOLUME_1R:
 623                 inmode = madera->pdata.codec.inmode[0][1 + (2 * mux)];
 624                 break;
 625         case MADERA_ADC_DIGITAL_VOLUME_2L:
 626                 inmode = madera->pdata.codec.inmode[1][2 * mux];
 627                 break;
 628         case MADERA_ADC_DIGITAL_VOLUME_2R:
 629                 inmode = madera->pdata.codec.inmode[1][1 + (2 * mux)];
 630                 break;
 631         default:
 632                 return -EINVAL;
 633         }
 634 
 635         if (inmode & MADERA_INMODE_SE)
 636                 val |= 1 << MADERA_IN1L_SRC_SE_SHIFT;
 637 
 638         dev_dbg(madera->dev, "mux=%u reg=0x%x inmode=0x%x mask=0x%x val=0x%x\n",
 639                 mux, e->reg, inmode, mask, val);
 640 
 641         ret = regmap_update_bits_check(regmap, e->reg, mask, val, &changed);
 642         if (ret < 0)
 643                 return ret;
 644 
 645         if (changed)
 646                 return snd_soc_dapm_mux_update_power(dapm, kcontrol,
 647                                                      mux, e, NULL);
 648         else
 649                 return 0;
 650 }
 651 
 652 static const char * const madera_inmux_texts[] = {
 653         "A",
 654         "B",
 655 };
 656 
 657 static SOC_ENUM_SINGLE_DECL(madera_in1muxl_enum,
 658                             MADERA_ADC_DIGITAL_VOLUME_1L,
 659                             MADERA_IN1L_SRC_SHIFT,
 660                             madera_inmux_texts);
 661 
 662 static SOC_ENUM_SINGLE_DECL(madera_in1muxr_enum,
 663                             MADERA_ADC_DIGITAL_VOLUME_1R,
 664                             MADERA_IN1R_SRC_SHIFT,
 665                             madera_inmux_texts);
 666 
 667 static SOC_ENUM_SINGLE_DECL(madera_in2muxl_enum,
 668                             MADERA_ADC_DIGITAL_VOLUME_2L,
 669                             MADERA_IN2L_SRC_SHIFT,
 670                             madera_inmux_texts);
 671 
 672 static SOC_ENUM_SINGLE_DECL(madera_in2muxr_enum,
 673                             MADERA_ADC_DIGITAL_VOLUME_2R,
 674                             MADERA_IN2R_SRC_SHIFT,
 675                             madera_inmux_texts);
 676 
 677 const struct snd_kcontrol_new madera_inmux[] = {
 678         SOC_DAPM_ENUM_EXT("IN1L Mux", madera_in1muxl_enum,
 679                           snd_soc_dapm_get_enum_double, madera_inmux_put),
 680         SOC_DAPM_ENUM_EXT("IN1R Mux", madera_in1muxr_enum,
 681                           snd_soc_dapm_get_enum_double, madera_inmux_put),
 682         SOC_DAPM_ENUM_EXT("IN2L Mux", madera_in2muxl_enum,
 683                           snd_soc_dapm_get_enum_double, madera_inmux_put),
 684         SOC_DAPM_ENUM_EXT("IN2R Mux", madera_in2muxr_enum,
 685                           snd_soc_dapm_get_enum_double, madera_inmux_put),
 686 };
 687 EXPORT_SYMBOL_GPL(madera_inmux);
 688 
 689 static const char * const madera_dmode_texts[] = {
 690         "Analog",
 691         "Digital",
 692 };
 693 
 694 static SOC_ENUM_SINGLE_DECL(madera_in1dmode_enum,
 695                             MADERA_IN1L_CONTROL,
 696                             MADERA_IN1_MODE_SHIFT,
 697                             madera_dmode_texts);
 698 
 699 static SOC_ENUM_SINGLE_DECL(madera_in2dmode_enum,
 700                             MADERA_IN2L_CONTROL,
 701                             MADERA_IN2_MODE_SHIFT,
 702                             madera_dmode_texts);
 703 
 704 static SOC_ENUM_SINGLE_DECL(madera_in3dmode_enum,
 705                             MADERA_IN3L_CONTROL,
 706                             MADERA_IN3_MODE_SHIFT,
 707                             madera_dmode_texts);
 708 
 709 const struct snd_kcontrol_new madera_inmode[] = {
 710         SOC_DAPM_ENUM("IN1 Mode", madera_in1dmode_enum),
 711         SOC_DAPM_ENUM("IN2 Mode", madera_in2dmode_enum),
 712         SOC_DAPM_ENUM("IN3 Mode", madera_in3dmode_enum),
 713 };
 714 EXPORT_SYMBOL_GPL(madera_inmode);
 715 
 716 static bool madera_can_change_grp_rate(const struct madera_priv *priv,
 717                                        unsigned int reg)
 718 {
 719         int count;
 720 
 721         switch (reg) {
 722         case MADERA_FX_CTRL1:
 723                 count = priv->domain_group_ref[MADERA_DOM_GRP_FX];
 724                 break;
 725         case MADERA_ASRC1_RATE1:
 726         case MADERA_ASRC1_RATE2:
 727                 count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC1];
 728                 break;
 729         case MADERA_ASRC2_RATE1:
 730         case MADERA_ASRC2_RATE2:
 731                 count = priv->domain_group_ref[MADERA_DOM_GRP_ASRC2];
 732                 break;
 733         case MADERA_ISRC_1_CTRL_1:
 734         case MADERA_ISRC_1_CTRL_2:
 735                 count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC1];
 736                 break;
 737         case MADERA_ISRC_2_CTRL_1:
 738         case MADERA_ISRC_2_CTRL_2:
 739                 count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC2];
 740                 break;
 741         case MADERA_ISRC_3_CTRL_1:
 742         case MADERA_ISRC_3_CTRL_2:
 743                 count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC3];
 744                 break;
 745         case MADERA_ISRC_4_CTRL_1:
 746         case MADERA_ISRC_4_CTRL_2:
 747                 count = priv->domain_group_ref[MADERA_DOM_GRP_ISRC4];
 748                 break;
 749         case MADERA_OUTPUT_RATE_1:
 750                 count = priv->domain_group_ref[MADERA_DOM_GRP_OUT];
 751                 break;
 752         case MADERA_SPD1_TX_CONTROL:
 753                 count = priv->domain_group_ref[MADERA_DOM_GRP_SPD];
 754                 break;
 755         case MADERA_DSP1_CONFIG_1:
 756         case MADERA_DSP1_CONFIG_2:
 757                 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP1];
 758                 break;
 759         case MADERA_DSP2_CONFIG_1:
 760         case MADERA_DSP2_CONFIG_2:
 761                 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP2];
 762                 break;
 763         case MADERA_DSP3_CONFIG_1:
 764         case MADERA_DSP3_CONFIG_2:
 765                 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP3];
 766                 break;
 767         case MADERA_DSP4_CONFIG_1:
 768         case MADERA_DSP4_CONFIG_2:
 769                 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP4];
 770                 break;
 771         case MADERA_DSP5_CONFIG_1:
 772         case MADERA_DSP5_CONFIG_2:
 773                 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP5];
 774                 break;
 775         case MADERA_DSP6_CONFIG_1:
 776         case MADERA_DSP6_CONFIG_2:
 777                 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP6];
 778                 break;
 779         case MADERA_DSP7_CONFIG_1:
 780         case MADERA_DSP7_CONFIG_2:
 781                 count = priv->domain_group_ref[MADERA_DOM_GRP_DSP7];
 782                 break;
 783         case MADERA_AIF1_RATE_CTRL:
 784                 count = priv->domain_group_ref[MADERA_DOM_GRP_AIF1];
 785                 break;
 786         case MADERA_AIF2_RATE_CTRL:
 787                 count = priv->domain_group_ref[MADERA_DOM_GRP_AIF2];
 788                 break;
 789         case MADERA_AIF3_RATE_CTRL:
 790                 count = priv->domain_group_ref[MADERA_DOM_GRP_AIF3];
 791                 break;
 792         case MADERA_AIF4_RATE_CTRL:
 793                 count = priv->domain_group_ref[MADERA_DOM_GRP_AIF4];
 794                 break;
 795         case MADERA_SLIMBUS_RATES_1:
 796         case MADERA_SLIMBUS_RATES_2:
 797         case MADERA_SLIMBUS_RATES_3:
 798         case MADERA_SLIMBUS_RATES_4:
 799         case MADERA_SLIMBUS_RATES_5:
 800         case MADERA_SLIMBUS_RATES_6:
 801         case MADERA_SLIMBUS_RATES_7:
 802         case MADERA_SLIMBUS_RATES_8:
 803                 count = priv->domain_group_ref[MADERA_DOM_GRP_SLIMBUS];
 804                 break;
 805         case MADERA_PWM_DRIVE_1:
 806                 count = priv->domain_group_ref[MADERA_DOM_GRP_PWM];
 807                 break;
 808         default:
 809                 return false;
 810         }
 811 
 812         dev_dbg(priv->madera->dev, "Rate reg 0x%x group ref %d\n", reg, count);
 813 
 814         if (count)
 815                 return false;
 816         else
 817                 return true;
 818 }
 819 
 820 static int madera_adsp_rate_get(struct snd_kcontrol *kcontrol,
 821                                 struct snd_ctl_elem_value *ucontrol)
 822 {
 823         struct snd_soc_component *component =
 824                 snd_soc_kcontrol_component(kcontrol);
 825         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 826         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 827         unsigned int cached_rate;
 828         const int adsp_num = e->shift_l;
 829         int item;
 830 
 831         mutex_lock(&priv->rate_lock);
 832         cached_rate = priv->adsp_rate_cache[adsp_num];
 833         mutex_unlock(&priv->rate_lock);
 834 
 835         item = snd_soc_enum_val_to_item(e, cached_rate);
 836         ucontrol->value.enumerated.item[0] = item;
 837 
 838         return 0;
 839 }
 840 
 841 static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
 842                                 struct snd_ctl_elem_value *ucontrol)
 843 {
 844         struct snd_soc_component *component =
 845                 snd_soc_kcontrol_component(kcontrol);
 846         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
 847         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 848         const int adsp_num = e->shift_l;
 849         const unsigned int item = ucontrol->value.enumerated.item[0];
 850         int ret;
 851 
 852         if (item >= e->items)
 853                 return -EINVAL;
 854 
 855         /*
 856          * We don't directly write the rate register here but we want to
 857          * maintain consistent behaviour that rate domains cannot be changed
 858          * while in use since this is a hardware requirement
 859          */
 860         mutex_lock(&priv->rate_lock);
 861 
 862         if (!madera_can_change_grp_rate(priv, priv->adsp[adsp_num].base)) {
 863                 dev_warn(priv->madera->dev,
 864                          "Cannot change '%s' while in use by active audio paths\n",
 865                          kcontrol->id.name);
 866                 ret = -EBUSY;
 867         } else {
 868                 /* Volatile register so defer until the codec is powered up */
 869                 priv->adsp_rate_cache[adsp_num] = e->values[item];
 870                 ret = 0;
 871         }
 872 
 873         mutex_unlock(&priv->rate_lock);
 874 
 875         return ret;
 876 }
 877 
 878 static const struct soc_enum madera_adsp_rate_enum[] = {
 879         SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0, 0xf, MADERA_RATE_ENUM_SIZE,
 880                               madera_rate_text, madera_rate_val),
 881         SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 1, 0xf, MADERA_RATE_ENUM_SIZE,
 882                               madera_rate_text, madera_rate_val),
 883         SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 2, 0xf, MADERA_RATE_ENUM_SIZE,
 884                               madera_rate_text, madera_rate_val),
 885         SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 3, 0xf, MADERA_RATE_ENUM_SIZE,
 886                               madera_rate_text, madera_rate_val),
 887         SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 4, 0xf, MADERA_RATE_ENUM_SIZE,
 888                               madera_rate_text, madera_rate_val),
 889         SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 5, 0xf, MADERA_RATE_ENUM_SIZE,
 890                               madera_rate_text, madera_rate_val),
 891         SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 6, 0xf, MADERA_RATE_ENUM_SIZE,
 892                               madera_rate_text, madera_rate_val),
 893 };
 894 
 895 const struct snd_kcontrol_new madera_adsp_rate_controls[] = {
 896         SOC_ENUM_EXT("DSP1 Rate", madera_adsp_rate_enum[0],
 897                      madera_adsp_rate_get, madera_adsp_rate_put),
 898         SOC_ENUM_EXT("DSP2 Rate", madera_adsp_rate_enum[1],
 899                      madera_adsp_rate_get, madera_adsp_rate_put),
 900         SOC_ENUM_EXT("DSP3 Rate", madera_adsp_rate_enum[2],
 901                      madera_adsp_rate_get, madera_adsp_rate_put),
 902         SOC_ENUM_EXT("DSP4 Rate", madera_adsp_rate_enum[3],
 903                      madera_adsp_rate_get, madera_adsp_rate_put),
 904         SOC_ENUM_EXT("DSP5 Rate", madera_adsp_rate_enum[4],
 905                      madera_adsp_rate_get, madera_adsp_rate_put),
 906         SOC_ENUM_EXT("DSP6 Rate", madera_adsp_rate_enum[5],
 907                      madera_adsp_rate_get, madera_adsp_rate_put),
 908         SOC_ENUM_EXT("DSP7 Rate", madera_adsp_rate_enum[6],
 909                      madera_adsp_rate_get, madera_adsp_rate_put),
 910 };
 911 EXPORT_SYMBOL_GPL(madera_adsp_rate_controls);
 912 
 913 static int madera_write_adsp_clk_setting(struct madera_priv *priv,
 914                                          struct wm_adsp *dsp,
 915                                          unsigned int freq)
 916 {
 917         unsigned int val;
 918         unsigned int mask = MADERA_DSP_RATE_MASK;
 919         int ret;
 920 
 921         val = priv->adsp_rate_cache[dsp->num - 1] << MADERA_DSP_RATE_SHIFT;
 922 
 923         switch (priv->madera->type) {
 924         case CS47L35:
 925         case CS47L85:
 926         case WM1840:
 927                 /* use legacy frequency registers */
 928                 mask |= MADERA_DSP_CLK_SEL_MASK;
 929                 val |= (freq << MADERA_DSP_CLK_SEL_SHIFT);
 930                 break;
 931         default:
 932                 /* Configure exact dsp frequency */
 933                 dev_dbg(priv->madera->dev, "Set DSP frequency to 0x%x\n", freq);
 934 
 935                 ret = regmap_write(dsp->regmap,
 936                                    dsp->base + MADERA_DSP_CONFIG_2_OFFS, freq);
 937                 if (ret)
 938                         goto err;
 939                 break;
 940         }
 941 
 942         ret = regmap_update_bits(dsp->regmap,
 943                                  dsp->base + MADERA_DSP_CONFIG_1_OFFS,
 944                                  mask, val);
 945         if (ret)
 946                 goto err;
 947 
 948         dev_dbg(priv->madera->dev, "Set DSP clocking to 0x%x\n", val);
 949 
 950         return 0;
 951 
 952 err:
 953         dev_err(dsp->dev, "Failed to set DSP%d clock: %d\n", dsp->num, ret);
 954 
 955         return ret;
 956 }
 957 
 958 int madera_set_adsp_clk(struct madera_priv *priv, int dsp_num,
 959                         unsigned int freq)
 960 {
 961         struct wm_adsp *dsp = &priv->adsp[dsp_num];
 962         struct madera *madera = priv->madera;
 963         unsigned int cur, new;
 964         int ret;
 965 
 966         /*
 967          * This is called at a higher DAPM priority than the mux widgets so
 968          * the muxes are still off at this point and it's safe to change
 969          * the rate domain control.
 970          * Also called at a lower DAPM priority than the domain group widgets
 971          * so locking the reads of adsp_rate_cache is not necessary as we know
 972          * changes are locked out by the domain_group_ref reference count.
 973          */
 974 
 975         ret = regmap_read(dsp->regmap,  dsp->base, &cur);
 976         if (ret) {
 977                 dev_err(madera->dev,
 978                         "Failed to read current DSP rate: %d\n", ret);
 979                 return ret;
 980         }
 981 
 982         cur &= MADERA_DSP_RATE_MASK;
 983 
 984         new = priv->adsp_rate_cache[dsp->num - 1] << MADERA_DSP_RATE_SHIFT;
 985 
 986         if (new == cur) {
 987                 dev_dbg(madera->dev, "DSP rate not changed\n");
 988                 return madera_write_adsp_clk_setting(priv, dsp, freq);
 989         } else {
 990                 dev_dbg(madera->dev, "DSP rate changed\n");
 991 
 992                 /* The write must be guarded by a number of SYSCLK cycles */
 993                 madera_spin_sysclk(priv);
 994                 ret = madera_write_adsp_clk_setting(priv, dsp, freq);
 995                 madera_spin_sysclk(priv);
 996                 return ret;
 997         }
 998 }
 999 EXPORT_SYMBOL_GPL(madera_set_adsp_clk);
1000 
1001 int madera_rate_put(struct snd_kcontrol *kcontrol,
1002                     struct snd_ctl_elem_value *ucontrol)
1003 {
1004         struct snd_soc_component *component =
1005                 snd_soc_kcontrol_component(kcontrol);
1006         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1007         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1008         unsigned int item = ucontrol->value.enumerated.item[0];
1009         unsigned int val;
1010         int ret;
1011 
1012         if (item >= e->items)
1013                 return -EINVAL;
1014 
1015         /*
1016          * Prevent the domain powering up while we're checking whether it's
1017          * safe to change rate domain
1018          */
1019         mutex_lock(&priv->rate_lock);
1020 
1021         ret = snd_soc_component_read(component, e->reg, &val);
1022         if (ret < 0) {
1023                 dev_warn(priv->madera->dev, "Failed to read 0x%x (%d)\n",
1024                          e->reg, ret);
1025                 goto out;
1026         }
1027         val >>= e->shift_l;
1028         val &= e->mask;
1029         if (snd_soc_enum_item_to_val(e, item) == val) {
1030                 ret = 0;
1031                 goto out;
1032         }
1033 
1034         if (!madera_can_change_grp_rate(priv, e->reg)) {
1035                 dev_warn(priv->madera->dev,
1036                          "Cannot change '%s' while in use by active audio paths\n",
1037                          kcontrol->id.name);
1038                 ret = -EBUSY;
1039         } else {
1040                 /* The write must be guarded by a number of SYSCLK cycles */
1041                 madera_spin_sysclk(priv);
1042                 ret = snd_soc_put_enum_double(kcontrol, ucontrol);
1043                 madera_spin_sysclk(priv);
1044         }
1045 out:
1046         mutex_unlock(&priv->rate_lock);
1047 
1048         return ret;
1049 }
1050 EXPORT_SYMBOL_GPL(madera_rate_put);
1051 
1052 static void madera_configure_input_mode(struct madera *madera)
1053 {
1054         unsigned int dig_mode, ana_mode_l, ana_mode_r;
1055         int max_analogue_inputs, max_dmic_sup, i;
1056 
1057         switch (madera->type) {
1058         case CS47L15:
1059                 max_analogue_inputs = 1;
1060                 max_dmic_sup = 2;
1061                 break;
1062         case CS47L35:
1063                 max_analogue_inputs = 2;
1064                 max_dmic_sup = 2;
1065                 break;
1066         case CS47L85:
1067         case WM1840:
1068                 max_analogue_inputs = 3;
1069                 max_dmic_sup = 3;
1070                 break;
1071         case CS47L90:
1072         case CS47L91:
1073                 max_analogue_inputs = 2;
1074                 max_dmic_sup = 2;
1075                 break;
1076         default:
1077                 max_analogue_inputs = 2;
1078                 max_dmic_sup = 4;
1079                 break;
1080         }
1081 
1082         /*
1083          * Initialize input modes from the A settings. For muxed inputs the
1084          * B settings will be applied if the mux is changed
1085          */
1086         for (i = 0; i < max_dmic_sup; i++) {
1087                 dev_dbg(madera->dev, "IN%d mode %u:%u:%u:%u\n", i + 1,
1088                         madera->pdata.codec.inmode[i][0],
1089                         madera->pdata.codec.inmode[i][1],
1090                         madera->pdata.codec.inmode[i][2],
1091                         madera->pdata.codec.inmode[i][3]);
1092 
1093                 dig_mode = madera->pdata.codec.dmic_ref[i] <<
1094                            MADERA_IN1_DMIC_SUP_SHIFT;
1095 
1096                 switch (madera->pdata.codec.inmode[i][0]) {
1097                 case MADERA_INMODE_DIFF:
1098                         ana_mode_l = 0;
1099                         break;
1100                 case MADERA_INMODE_SE:
1101                         ana_mode_l = 1 << MADERA_IN1L_SRC_SE_SHIFT;
1102                         break;
1103                 default:
1104                         dev_warn(madera->dev,
1105                                  "IN%dAL Illegal inmode %u ignored\n",
1106                                  i + 1, madera->pdata.codec.inmode[i][0]);
1107                         continue;
1108                 }
1109 
1110                 switch (madera->pdata.codec.inmode[i][1]) {
1111                 case MADERA_INMODE_DIFF:
1112                         ana_mode_r = 0;
1113                         break;
1114                 case MADERA_INMODE_SE:
1115                         ana_mode_r = 1 << MADERA_IN1R_SRC_SE_SHIFT;
1116                         break;
1117                 default:
1118                         dev_warn(madera->dev,
1119                                  "IN%dAR Illegal inmode %u ignored\n",
1120                                  i + 1, madera->pdata.codec.inmode[i][1]);
1121                         continue;
1122                 }
1123 
1124                 dev_dbg(madera->dev,
1125                         "IN%dA DMIC mode=0x%x Analogue mode=0x%x,0x%x\n",
1126                         i + 1, dig_mode, ana_mode_l, ana_mode_r);
1127 
1128                 regmap_update_bits(madera->regmap,
1129                                    MADERA_IN1L_CONTROL + (i * 8),
1130                                    MADERA_IN1_DMIC_SUP_MASK, dig_mode);
1131 
1132                 if (i >= max_analogue_inputs)
1133                         continue;
1134 
1135                 regmap_update_bits(madera->regmap,
1136                                    MADERA_ADC_DIGITAL_VOLUME_1L + (i * 8),
1137                                    MADERA_IN1L_SRC_SE_MASK, ana_mode_l);
1138 
1139                 regmap_update_bits(madera->regmap,
1140                                    MADERA_ADC_DIGITAL_VOLUME_1R + (i * 8),
1141                                    MADERA_IN1R_SRC_SE_MASK, ana_mode_r);
1142         }
1143 }
1144 
1145 int madera_init_inputs(struct snd_soc_component *component)
1146 {
1147         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1148         struct madera *madera = priv->madera;
1149 
1150         madera_configure_input_mode(madera);
1151 
1152         return 0;
1153 }
1154 EXPORT_SYMBOL_GPL(madera_init_inputs);
1155 
1156 static const struct snd_soc_dapm_route madera_mono_routes[] = {
1157         { "OUT1R", NULL, "OUT1L" },
1158         { "OUT2R", NULL, "OUT2L" },
1159         { "OUT3R", NULL, "OUT3L" },
1160         { "OUT4R", NULL, "OUT4L" },
1161         { "OUT5R", NULL, "OUT5L" },
1162         { "OUT6R", NULL, "OUT6L" },
1163 };
1164 
1165 int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes)
1166 {
1167         struct snd_soc_dapm_context *dapm =
1168                 snd_soc_component_get_dapm(component);
1169         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
1170         struct madera *madera = priv->madera;
1171         const struct madera_codec_pdata *pdata = &madera->pdata.codec;
1172         unsigned int val;
1173         int i;
1174 
1175         if (n_mono_routes > MADERA_MAX_OUTPUT) {
1176                 dev_warn(madera->dev,
1177                          "Requested %d mono outputs, using maximum allowed %d\n",
1178                          n_mono_routes, MADERA_MAX_OUTPUT);
1179                 n_mono_routes = MADERA_MAX_OUTPUT;
1180         }
1181 
1182         for (i = 0; i < n_mono_routes; i++) {
1183                 /* Default is 0 so noop with defaults */
1184                 if (pdata->out_mono[i]) {
1185                         val = MADERA_OUT1_MONO;
1186                         snd_soc_dapm_add_routes(dapm,
1187                                                 &madera_mono_routes[i], 1);
1188                 } else {
1189                         val = 0;
1190                 }
1191 
1192                 regmap_update_bits(madera->regmap,
1193                                    MADERA_OUTPUT_PATH_CONFIG_1L + (i * 8),
1194                                    MADERA_OUT1_MONO, val);
1195 
1196                 dev_dbg(madera->dev, "OUT%d mono=0x%x\n", i + 1, val);
1197         }
1198 
1199         for (i = 0; i < MADERA_MAX_PDM_SPK; i++) {
1200                 dev_dbg(madera->dev, "PDM%d fmt=0x%x mute=0x%x\n", i + 1,
1201                         pdata->pdm_fmt[i], pdata->pdm_mute[i]);
1202 
1203                 if (pdata->pdm_mute[i])
1204                         regmap_update_bits(madera->regmap,
1205                                            MADERA_PDM_SPK1_CTRL_1 + (i * 2),
1206                                            MADERA_SPK1_MUTE_ENDIAN_MASK |
1207                                            MADERA_SPK1_MUTE_SEQ1_MASK,
1208                                            pdata->pdm_mute[i]);
1209 
1210                 if (pdata->pdm_fmt[i])
1211                         regmap_update_bits(madera->regmap,
1212                                            MADERA_PDM_SPK1_CTRL_2 + (i * 2),
1213                                            MADERA_SPK1_FMT_MASK,
1214                                            pdata->pdm_fmt[i]);
1215         }
1216 
1217         return 0;
1218 }
1219 EXPORT_SYMBOL_GPL(madera_init_outputs);
1220 
1221 int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num,
1222                               irq_handler_t handler)
1223 {
1224         struct madera *madera = priv->madera;
1225         int ret;
1226 
1227         ret = madera_request_irq(madera,
1228                                  madera_dsp_bus_error_irqs[dsp_num],
1229                                  "ADSP2 bus error",
1230                                  handler,
1231                                  &priv->adsp[dsp_num]);
1232         if (ret)
1233                 dev_err(madera->dev,
1234                         "Failed to request DSP Lock region IRQ: %d\n", ret);
1235 
1236         return ret;
1237 }
1238 EXPORT_SYMBOL_GPL(madera_init_bus_error_irq);
1239 
1240 void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num)
1241 {
1242         struct madera *madera = priv->madera;
1243 
1244         madera_free_irq(madera,
1245                         madera_dsp_bus_error_irqs[dsp_num],
1246                         &priv->adsp[dsp_num]);
1247 }
1248 EXPORT_SYMBOL_GPL(madera_free_bus_error_irq);
1249 
1250 const char * const madera_mixer_texts[] = {
1251         "None",
1252         "Tone Generator 1",
1253         "Tone Generator 2",
1254         "Haptics",
1255         "AEC1",
1256         "AEC2",
1257         "Mic Mute Mixer",
1258         "Noise Generator",
1259         "IN1L",
1260         "IN1R",
1261         "IN2L",
1262         "IN2R",
1263         "IN3L",
1264         "IN3R",
1265         "IN4L",
1266         "IN4R",
1267         "IN5L",
1268         "IN5R",
1269         "IN6L",
1270         "IN6R",
1271         "AIF1RX1",
1272         "AIF1RX2",
1273         "AIF1RX3",
1274         "AIF1RX4",
1275         "AIF1RX5",
1276         "AIF1RX6",
1277         "AIF1RX7",
1278         "AIF1RX8",
1279         "AIF2RX1",
1280         "AIF2RX2",
1281         "AIF2RX3",
1282         "AIF2RX4",
1283         "AIF2RX5",
1284         "AIF2RX6",
1285         "AIF2RX7",
1286         "AIF2RX8",
1287         "AIF3RX1",
1288         "AIF3RX2",
1289         "AIF3RX3",
1290         "AIF3RX4",
1291         "AIF4RX1",
1292         "AIF4RX2",
1293         "SLIMRX1",
1294         "SLIMRX2",
1295         "SLIMRX3",
1296         "SLIMRX4",
1297         "SLIMRX5",
1298         "SLIMRX6",
1299         "SLIMRX7",
1300         "SLIMRX8",
1301         "EQ1",
1302         "EQ2",
1303         "EQ3",
1304         "EQ4",
1305         "DRC1L",
1306         "DRC1R",
1307         "DRC2L",
1308         "DRC2R",
1309         "LHPF1",
1310         "LHPF2",
1311         "LHPF3",
1312         "LHPF4",
1313         "DSP1.1",
1314         "DSP1.2",
1315         "DSP1.3",
1316         "DSP1.4",
1317         "DSP1.5",
1318         "DSP1.6",
1319         "DSP2.1",
1320         "DSP2.2",
1321         "DSP2.3",
1322         "DSP2.4",
1323         "DSP2.5",
1324         "DSP2.6",
1325         "DSP3.1",
1326         "DSP3.2",
1327         "DSP3.3",
1328         "DSP3.4",
1329         "DSP3.5",
1330         "DSP3.6",
1331         "DSP4.1",
1332         "DSP4.2",
1333         "DSP4.3",
1334         "DSP4.4",
1335         "DSP4.5",
1336         "DSP4.6",
1337         "DSP5.1",
1338         "DSP5.2",
1339         "DSP5.3",
1340         "DSP5.4",
1341         "DSP5.5",
1342         "DSP5.6",
1343         "DSP6.1",
1344         "DSP6.2",
1345         "DSP6.3",
1346         "DSP6.4",
1347         "DSP6.5",
1348         "DSP6.6",
1349         "DSP7.1",
1350         "DSP7.2",
1351         "DSP7.3",
1352         "DSP7.4",
1353         "DSP7.5",
1354         "DSP7.6",
1355         "ASRC1IN1L",
1356         "ASRC1IN1R",
1357         "ASRC1IN2L",
1358         "ASRC1IN2R",
1359         "ASRC2IN1L",
1360         "ASRC2IN1R",
1361         "ASRC2IN2L",
1362         "ASRC2IN2R",
1363         "ISRC1INT1",
1364         "ISRC1INT2",
1365         "ISRC1INT3",
1366         "ISRC1INT4",
1367         "ISRC1DEC1",
1368         "ISRC1DEC2",
1369         "ISRC1DEC3",
1370         "ISRC1DEC4",
1371         "ISRC2INT1",
1372         "ISRC2INT2",
1373         "ISRC2INT3",
1374         "ISRC2INT4",
1375         "ISRC2DEC1",
1376         "ISRC2DEC2",
1377         "ISRC2DEC3",
1378         "ISRC2DEC4",
1379         "ISRC3INT1",
1380         "ISRC3INT2",
1381         "ISRC3INT3",
1382         "ISRC3INT4",
1383         "ISRC3DEC1",
1384         "ISRC3DEC2",
1385         "ISRC3DEC3",
1386         "ISRC3DEC4",
1387         "ISRC4INT1",
1388         "ISRC4INT2",
1389         "ISRC4DEC1",
1390         "ISRC4DEC2",
1391         "DFC1",
1392         "DFC2",
1393         "DFC3",
1394         "DFC4",
1395         "DFC5",
1396         "DFC6",
1397         "DFC7",
1398         "DFC8",
1399 };
1400 EXPORT_SYMBOL_GPL(madera_mixer_texts);
1401 
1402 const unsigned int madera_mixer_values[] = {
1403         0x00,   /* None */
1404         0x04,   /* Tone Generator 1 */
1405         0x05,   /* Tone Generator 2 */
1406         0x06,   /* Haptics */
1407         0x08,   /* AEC */
1408         0x09,   /* AEC2 */
1409         0x0c,   /* Noise mixer */
1410         0x0d,   /* Comfort noise */
1411         0x10,   /* IN1L */
1412         0x11,
1413         0x12,
1414         0x13,
1415         0x14,
1416         0x15,
1417         0x16,
1418         0x17,
1419         0x18,
1420         0x19,
1421         0x1A,
1422         0x1B,
1423         0x20,   /* AIF1RX1 */
1424         0x21,
1425         0x22,
1426         0x23,
1427         0x24,
1428         0x25,
1429         0x26,
1430         0x27,
1431         0x28,   /* AIF2RX1 */
1432         0x29,
1433         0x2a,
1434         0x2b,
1435         0x2c,
1436         0x2d,
1437         0x2e,
1438         0x2f,
1439         0x30,   /* AIF3RX1 */
1440         0x31,
1441         0x32,
1442         0x33,
1443         0x34,   /* AIF4RX1 */
1444         0x35,
1445         0x38,   /* SLIMRX1 */
1446         0x39,
1447         0x3a,
1448         0x3b,
1449         0x3c,
1450         0x3d,
1451         0x3e,
1452         0x3f,
1453         0x50,   /* EQ1 */
1454         0x51,
1455         0x52,
1456         0x53,
1457         0x58,   /* DRC1L */
1458         0x59,
1459         0x5a,
1460         0x5b,
1461         0x60,   /* LHPF1 */
1462         0x61,
1463         0x62,
1464         0x63,
1465         0x68,   /* DSP1.1 */
1466         0x69,
1467         0x6a,
1468         0x6b,
1469         0x6c,
1470         0x6d,
1471         0x70,   /* DSP2.1 */
1472         0x71,
1473         0x72,
1474         0x73,
1475         0x74,
1476         0x75,
1477         0x78,   /* DSP3.1 */
1478         0x79,
1479         0x7a,
1480         0x7b,
1481         0x7c,
1482         0x7d,
1483         0x80,   /* DSP4.1 */
1484         0x81,
1485         0x82,
1486         0x83,
1487         0x84,
1488         0x85,
1489         0x88,   /* DSP5.1 */
1490         0x89,
1491         0x8a,
1492         0x8b,
1493         0x8c,
1494         0x8d,
1495         0xc0,   /* DSP6.1 */
1496         0xc1,
1497         0xc2,
1498         0xc3,
1499         0xc4,
1500         0xc5,
1501         0xc8,   /* DSP7.1 */
1502         0xc9,
1503         0xca,
1504         0xcb,
1505         0xcc,
1506         0xcd,
1507         0x90,   /* ASRC1IN1L */
1508         0x91,
1509         0x92,
1510         0x93,
1511         0x94,   /* ASRC2IN1L */
1512         0x95,
1513         0x96,
1514         0x97,
1515         0xa0,   /* ISRC1INT1 */
1516         0xa1,
1517         0xa2,
1518         0xa3,
1519         0xa4,   /* ISRC1DEC1 */
1520         0xa5,
1521         0xa6,
1522         0xa7,
1523         0xa8,   /* ISRC2DEC1 */
1524         0xa9,
1525         0xaa,
1526         0xab,
1527         0xac,   /* ISRC2INT1 */
1528         0xad,
1529         0xae,
1530         0xaf,
1531         0xb0,   /* ISRC3DEC1 */
1532         0xb1,
1533         0xb2,
1534         0xb3,
1535         0xb4,   /* ISRC3INT1 */
1536         0xb5,
1537         0xb6,
1538         0xb7,
1539         0xb8,   /* ISRC4INT1 */
1540         0xb9,
1541         0xbc,   /* ISRC4DEC1 */
1542         0xbd,
1543         0xf8,   /* DFC1 */
1544         0xf9,
1545         0xfa,
1546         0xfb,
1547         0xfc,
1548         0xfd,
1549         0xfe,
1550         0xff,   /* DFC8 */
1551 };
1552 EXPORT_SYMBOL_GPL(madera_mixer_values);
1553 
1554 const DECLARE_TLV_DB_SCALE(madera_ana_tlv, 0, 100, 0);
1555 EXPORT_SYMBOL_GPL(madera_ana_tlv);
1556 
1557 const DECLARE_TLV_DB_SCALE(madera_eq_tlv, -1200, 100, 0);
1558 EXPORT_SYMBOL_GPL(madera_eq_tlv);
1559 
1560 const DECLARE_TLV_DB_SCALE(madera_digital_tlv, -6400, 50, 0);
1561 EXPORT_SYMBOL_GPL(madera_digital_tlv);
1562 
1563 const DECLARE_TLV_DB_SCALE(madera_noise_tlv, -13200, 600, 0);
1564 EXPORT_SYMBOL_GPL(madera_noise_tlv);
1565 
1566 const DECLARE_TLV_DB_SCALE(madera_ng_tlv, -12000, 600, 0);
1567 EXPORT_SYMBOL_GPL(madera_ng_tlv);
1568 
1569 const DECLARE_TLV_DB_SCALE(madera_mixer_tlv, -3200, 100, 0);
1570 EXPORT_SYMBOL_GPL(madera_mixer_tlv);
1571 
1572 const char * const madera_rate_text[MADERA_RATE_ENUM_SIZE] = {
1573         "SYNCCLK rate 1", "SYNCCLK rate 2", "SYNCCLK rate 3",
1574         "ASYNCCLK rate 1", "ASYNCCLK rate 2",
1575 };
1576 EXPORT_SYMBOL_GPL(madera_rate_text);
1577 
1578 const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE] = {
1579         0x0, 0x1, 0x2, 0x8, 0x9,
1580 };
1581 EXPORT_SYMBOL_GPL(madera_rate_val);
1582 
1583 static const char * const madera_dfc_width_text[MADERA_DFC_WIDTH_ENUM_SIZE] = {
1584         "8 bit", "16 bit", "20 bit", "24 bit", "32 bit",
1585 };
1586 
1587 static const unsigned int madera_dfc_width_val[MADERA_DFC_WIDTH_ENUM_SIZE] = {
1588         7, 15, 19, 23, 31,
1589 };
1590 
1591 static const char * const madera_dfc_type_text[MADERA_DFC_TYPE_ENUM_SIZE] = {
1592         "Fixed", "Unsigned Fixed", "Single Precision Floating",
1593         "Half Precision Floating", "Arm Alternative Floating",
1594 };
1595 
1596 static const unsigned int madera_dfc_type_val[MADERA_DFC_TYPE_ENUM_SIZE] = {
1597         0, 1, 2, 4, 5,
1598 };
1599 
1600 const struct soc_enum madera_dfc_width[] = {
1601         SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_RX,
1602                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1603                               MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1604                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1605                               ARRAY_SIZE(madera_dfc_width_text),
1606                               madera_dfc_width_text,
1607                               madera_dfc_width_val),
1608         SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_TX,
1609                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1610                               MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1611                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1612                               ARRAY_SIZE(madera_dfc_width_text),
1613                               madera_dfc_width_text,
1614                               madera_dfc_width_val),
1615         SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_RX,
1616                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1617                               MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1618                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1619                               ARRAY_SIZE(madera_dfc_width_text),
1620                               madera_dfc_width_text,
1621                               madera_dfc_width_val),
1622         SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_TX,
1623                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1624                               MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1625                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1626                               ARRAY_SIZE(madera_dfc_width_text),
1627                               madera_dfc_width_text,
1628                               madera_dfc_width_val),
1629         SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_RX,
1630                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1631                               MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1632                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1633                               ARRAY_SIZE(madera_dfc_width_text),
1634                               madera_dfc_width_text,
1635                               madera_dfc_width_val),
1636         SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_TX,
1637                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1638                               MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1639                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1640                               ARRAY_SIZE(madera_dfc_width_text),
1641                               madera_dfc_width_text,
1642                               madera_dfc_width_val),
1643         SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_RX,
1644                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1645                               MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1646                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1647                               ARRAY_SIZE(madera_dfc_width_text),
1648                               madera_dfc_width_text,
1649                               madera_dfc_width_val),
1650         SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_TX,
1651                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1652                               MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1653                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1654                               ARRAY_SIZE(madera_dfc_width_text),
1655                               madera_dfc_width_text,
1656                               madera_dfc_width_val),
1657         SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_RX,
1658                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1659                               MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1660                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1661                               ARRAY_SIZE(madera_dfc_width_text),
1662                               madera_dfc_width_text,
1663                               madera_dfc_width_val),
1664         SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_TX,
1665                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1666                               MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1667                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1668                               ARRAY_SIZE(madera_dfc_width_text),
1669                               madera_dfc_width_text,
1670                               madera_dfc_width_val),
1671         SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_RX,
1672                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1673                               MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1674                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1675                               ARRAY_SIZE(madera_dfc_width_text),
1676                               madera_dfc_width_text,
1677                               madera_dfc_width_val),
1678         SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_TX,
1679                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1680                               MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1681                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1682                               ARRAY_SIZE(madera_dfc_width_text),
1683                               madera_dfc_width_text,
1684                               madera_dfc_width_val),
1685         SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_RX,
1686                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1687                               MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1688                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1689                               ARRAY_SIZE(madera_dfc_width_text),
1690                               madera_dfc_width_text,
1691                               madera_dfc_width_val),
1692         SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_TX,
1693                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1694                               MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1695                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1696                               ARRAY_SIZE(madera_dfc_width_text),
1697                               madera_dfc_width_text,
1698                               madera_dfc_width_val),
1699         SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_RX,
1700                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1701                               MADERA_DFC1_RX_DATA_WIDTH_MASK >>
1702                               MADERA_DFC1_RX_DATA_WIDTH_SHIFT,
1703                               ARRAY_SIZE(madera_dfc_width_text),
1704                               madera_dfc_width_text,
1705                               madera_dfc_width_val),
1706         SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_TX,
1707                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1708                               MADERA_DFC1_TX_DATA_WIDTH_MASK >>
1709                               MADERA_DFC1_TX_DATA_WIDTH_SHIFT,
1710                               ARRAY_SIZE(madera_dfc_width_text),
1711                               madera_dfc_width_text,
1712                               madera_dfc_width_val),
1713 };
1714 EXPORT_SYMBOL_GPL(madera_dfc_width);
1715 
1716 const struct soc_enum madera_dfc_type[] = {
1717         SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_RX,
1718                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1719                               MADERA_DFC1_RX_DATA_TYPE_MASK >>
1720                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1721                               ARRAY_SIZE(madera_dfc_type_text),
1722                               madera_dfc_type_text,
1723                               madera_dfc_type_val),
1724         SOC_VALUE_ENUM_SINGLE(MADERA_DFC1_TX,
1725                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1726                               MADERA_DFC1_TX_DATA_TYPE_MASK >>
1727                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1728                               ARRAY_SIZE(madera_dfc_type_text),
1729                               madera_dfc_type_text,
1730                               madera_dfc_type_val),
1731         SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_RX,
1732                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1733                               MADERA_DFC1_RX_DATA_TYPE_MASK >>
1734                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1735                               ARRAY_SIZE(madera_dfc_type_text),
1736                               madera_dfc_type_text,
1737                               madera_dfc_type_val),
1738         SOC_VALUE_ENUM_SINGLE(MADERA_DFC2_TX,
1739                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1740                               MADERA_DFC1_TX_DATA_TYPE_MASK >>
1741                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1742                               ARRAY_SIZE(madera_dfc_type_text),
1743                               madera_dfc_type_text,
1744                               madera_dfc_type_val),
1745         SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_RX,
1746                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1747                               MADERA_DFC1_RX_DATA_TYPE_MASK >>
1748                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1749                               ARRAY_SIZE(madera_dfc_type_text),
1750                               madera_dfc_type_text,
1751                               madera_dfc_type_val),
1752         SOC_VALUE_ENUM_SINGLE(MADERA_DFC3_TX,
1753                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1754                               MADERA_DFC1_TX_DATA_TYPE_MASK >>
1755                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1756                               ARRAY_SIZE(madera_dfc_type_text),
1757                               madera_dfc_type_text,
1758                               madera_dfc_type_val),
1759         SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_RX,
1760                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1761                               MADERA_DFC1_RX_DATA_TYPE_MASK >>
1762                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1763                               ARRAY_SIZE(madera_dfc_type_text),
1764                               madera_dfc_type_text,
1765                               madera_dfc_type_val),
1766         SOC_VALUE_ENUM_SINGLE(MADERA_DFC4_TX,
1767                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1768                               MADERA_DFC1_TX_DATA_TYPE_MASK >>
1769                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1770                               ARRAY_SIZE(madera_dfc_type_text),
1771                               madera_dfc_type_text,
1772                               madera_dfc_type_val),
1773         SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_RX,
1774                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1775                               MADERA_DFC1_RX_DATA_TYPE_MASK >>
1776                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1777                               ARRAY_SIZE(madera_dfc_type_text),
1778                               madera_dfc_type_text,
1779                               madera_dfc_type_val),
1780         SOC_VALUE_ENUM_SINGLE(MADERA_DFC5_TX,
1781                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1782                               MADERA_DFC1_TX_DATA_TYPE_MASK >>
1783                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1784                               ARRAY_SIZE(madera_dfc_type_text),
1785                               madera_dfc_type_text,
1786                               madera_dfc_type_val),
1787         SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_RX,
1788                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1789                               MADERA_DFC1_RX_DATA_TYPE_MASK >>
1790                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1791                               ARRAY_SIZE(madera_dfc_type_text),
1792                               madera_dfc_type_text,
1793                               madera_dfc_type_val),
1794         SOC_VALUE_ENUM_SINGLE(MADERA_DFC6_TX,
1795                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1796                               MADERA_DFC1_TX_DATA_TYPE_MASK >>
1797                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1798                               ARRAY_SIZE(madera_dfc_type_text),
1799                               madera_dfc_type_text,
1800                               madera_dfc_type_val),
1801         SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_RX,
1802                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1803                               MADERA_DFC1_RX_DATA_TYPE_MASK >>
1804                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1805                               ARRAY_SIZE(madera_dfc_type_text),
1806                               madera_dfc_type_text,
1807                               madera_dfc_type_val),
1808         SOC_VALUE_ENUM_SINGLE(MADERA_DFC7_TX,
1809                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1810                               MADERA_DFC1_TX_DATA_TYPE_MASK >>
1811                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1812                               ARRAY_SIZE(madera_dfc_type_text),
1813                               madera_dfc_type_text,
1814                               madera_dfc_type_val),
1815         SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_RX,
1816                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1817                               MADERA_DFC1_RX_DATA_TYPE_MASK >>
1818                               MADERA_DFC1_RX_DATA_TYPE_SHIFT,
1819                               ARRAY_SIZE(madera_dfc_type_text),
1820                               madera_dfc_type_text,
1821                               madera_dfc_type_val),
1822         SOC_VALUE_ENUM_SINGLE(MADERA_DFC8_TX,
1823                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1824                               MADERA_DFC1_TX_DATA_TYPE_MASK >>
1825                               MADERA_DFC1_TX_DATA_TYPE_SHIFT,
1826                               ARRAY_SIZE(madera_dfc_type_text),
1827                               madera_dfc_type_text,
1828                               madera_dfc_type_val),
1829 };
1830 EXPORT_SYMBOL_GPL(madera_dfc_type);
1831 
1832 const struct soc_enum madera_isrc_fsh[] = {
1833         SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_1_CTRL_1,
1834                               MADERA_ISRC1_FSH_SHIFT, 0xf,
1835                               MADERA_RATE_ENUM_SIZE,
1836                               madera_rate_text, madera_rate_val),
1837         SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_2_CTRL_1,
1838                               MADERA_ISRC2_FSH_SHIFT, 0xf,
1839                               MADERA_RATE_ENUM_SIZE,
1840                               madera_rate_text, madera_rate_val),
1841         SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_3_CTRL_1,
1842                               MADERA_ISRC3_FSH_SHIFT, 0xf,
1843                               MADERA_RATE_ENUM_SIZE,
1844                               madera_rate_text, madera_rate_val),
1845         SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_4_CTRL_1,
1846                               MADERA_ISRC4_FSH_SHIFT, 0xf,
1847                               MADERA_RATE_ENUM_SIZE,
1848                               madera_rate_text, madera_rate_val),
1849 
1850 };
1851 EXPORT_SYMBOL_GPL(madera_isrc_fsh);
1852 
1853 const struct soc_enum madera_isrc_fsl[] = {
1854         SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_1_CTRL_2,
1855                               MADERA_ISRC1_FSL_SHIFT, 0xf,
1856                               MADERA_RATE_ENUM_SIZE,
1857                               madera_rate_text, madera_rate_val),
1858         SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_2_CTRL_2,
1859                               MADERA_ISRC2_FSL_SHIFT, 0xf,
1860                               MADERA_RATE_ENUM_SIZE,
1861                               madera_rate_text, madera_rate_val),
1862         SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_3_CTRL_2,
1863                               MADERA_ISRC3_FSL_SHIFT, 0xf,
1864                               MADERA_RATE_ENUM_SIZE,
1865                               madera_rate_text, madera_rate_val),
1866         SOC_VALUE_ENUM_SINGLE(MADERA_ISRC_4_CTRL_2,
1867                               MADERA_ISRC4_FSL_SHIFT, 0xf,
1868                               MADERA_RATE_ENUM_SIZE,
1869                               madera_rate_text, madera_rate_val),
1870 
1871 };
1872 EXPORT_SYMBOL_GPL(madera_isrc_fsl);
1873 
1874 const struct soc_enum madera_asrc1_rate[] = {
1875         SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1,
1876                               MADERA_ASRC1_RATE1_SHIFT, 0xf,
1877                               MADERA_SYNC_RATE_ENUM_SIZE,
1878                               madera_rate_text, madera_rate_val),
1879         SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2,
1880                               MADERA_ASRC1_RATE1_SHIFT, 0xf,
1881                               MADERA_ASYNC_RATE_ENUM_SIZE,
1882                               madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
1883                               madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
1884 
1885 };
1886 EXPORT_SYMBOL_GPL(madera_asrc1_rate);
1887 
1888 const struct soc_enum madera_asrc1_bidir_rate[] = {
1889         SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE1,
1890                               MADERA_ASRC1_RATE1_SHIFT, 0xf,
1891                               MADERA_RATE_ENUM_SIZE,
1892                               madera_rate_text, madera_rate_val),
1893         SOC_VALUE_ENUM_SINGLE(MADERA_ASRC1_RATE2,
1894                               MADERA_ASRC1_RATE2_SHIFT, 0xf,
1895                               MADERA_RATE_ENUM_SIZE,
1896                               madera_rate_text, madera_rate_val),
1897 };
1898 EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate);
1899 
1900 const struct soc_enum madera_asrc2_rate[] = {
1901         SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE1,
1902                               MADERA_ASRC2_RATE1_SHIFT, 0xf,
1903                               MADERA_SYNC_RATE_ENUM_SIZE,
1904                               madera_rate_text, madera_rate_val),
1905         SOC_VALUE_ENUM_SINGLE(MADERA_ASRC2_RATE2,
1906                               MADERA_ASRC2_RATE2_SHIFT, 0xf,
1907                               MADERA_ASYNC_RATE_ENUM_SIZE,
1908                               madera_rate_text + MADERA_SYNC_RATE_ENUM_SIZE,
1909                               madera_rate_val + MADERA_SYNC_RATE_ENUM_SIZE),
1910 
1911 };
1912 EXPORT_SYMBOL_GPL(madera_asrc2_rate);
1913 
1914 static const char * const madera_vol_ramp_text[] = {
1915         "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
1916         "15ms/6dB", "30ms/6dB",
1917 };
1918 
1919 SOC_ENUM_SINGLE_DECL(madera_in_vd_ramp,
1920                      MADERA_INPUT_VOLUME_RAMP,
1921                      MADERA_IN_VD_RAMP_SHIFT,
1922                      madera_vol_ramp_text);
1923 EXPORT_SYMBOL_GPL(madera_in_vd_ramp);
1924 
1925 SOC_ENUM_SINGLE_DECL(madera_in_vi_ramp,
1926                      MADERA_INPUT_VOLUME_RAMP,
1927                      MADERA_IN_VI_RAMP_SHIFT,
1928                      madera_vol_ramp_text);
1929 EXPORT_SYMBOL_GPL(madera_in_vi_ramp);
1930 
1931 SOC_ENUM_SINGLE_DECL(madera_out_vd_ramp,
1932                      MADERA_OUTPUT_VOLUME_RAMP,
1933                      MADERA_OUT_VD_RAMP_SHIFT,
1934                      madera_vol_ramp_text);
1935 EXPORT_SYMBOL_GPL(madera_out_vd_ramp);
1936 
1937 SOC_ENUM_SINGLE_DECL(madera_out_vi_ramp,
1938                      MADERA_OUTPUT_VOLUME_RAMP,
1939                      MADERA_OUT_VI_RAMP_SHIFT,
1940                      madera_vol_ramp_text);
1941 EXPORT_SYMBOL_GPL(madera_out_vi_ramp);
1942 
1943 static const char * const madera_lhpf_mode_text[] = {
1944         "Low-pass", "High-pass"
1945 };
1946 
1947 SOC_ENUM_SINGLE_DECL(madera_lhpf1_mode,
1948                      MADERA_HPLPF1_1,
1949                      MADERA_LHPF1_MODE_SHIFT,
1950                      madera_lhpf_mode_text);
1951 EXPORT_SYMBOL_GPL(madera_lhpf1_mode);
1952 
1953 SOC_ENUM_SINGLE_DECL(madera_lhpf2_mode,
1954                      MADERA_HPLPF2_1,
1955                      MADERA_LHPF2_MODE_SHIFT,
1956                      madera_lhpf_mode_text);
1957 EXPORT_SYMBOL_GPL(madera_lhpf2_mode);
1958 
1959 SOC_ENUM_SINGLE_DECL(madera_lhpf3_mode,
1960                      MADERA_HPLPF3_1,
1961                      MADERA_LHPF3_MODE_SHIFT,
1962                      madera_lhpf_mode_text);
1963 EXPORT_SYMBOL_GPL(madera_lhpf3_mode);
1964 
1965 SOC_ENUM_SINGLE_DECL(madera_lhpf4_mode,
1966                      MADERA_HPLPF4_1,
1967                      MADERA_LHPF4_MODE_SHIFT,
1968                      madera_lhpf_mode_text);
1969 EXPORT_SYMBOL_GPL(madera_lhpf4_mode);
1970 
1971 static const char * const madera_ng_hold_text[] = {
1972         "30ms", "120ms", "250ms", "500ms",
1973 };
1974 
1975 SOC_ENUM_SINGLE_DECL(madera_ng_hold,
1976                      MADERA_NOISE_GATE_CONTROL,
1977                      MADERA_NGATE_HOLD_SHIFT,
1978                      madera_ng_hold_text);
1979 EXPORT_SYMBOL_GPL(madera_ng_hold);
1980 
1981 static const char * const madera_in_hpf_cut_text[] = {
1982         "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
1983 };
1984 
1985 SOC_ENUM_SINGLE_DECL(madera_in_hpf_cut_enum,
1986                      MADERA_HPF_CONTROL,
1987                      MADERA_IN_HPF_CUT_SHIFT,
1988                      madera_in_hpf_cut_text);
1989 EXPORT_SYMBOL_GPL(madera_in_hpf_cut_enum);
1990 
1991 static const char * const madera_in_dmic_osr_text[MADERA_OSR_ENUM_SIZE] = {
1992         "384kHz", "768kHz", "1.536MHz", "3.072MHz", "6.144MHz",
1993 };
1994 
1995 static const unsigned int madera_in_dmic_osr_val[MADERA_OSR_ENUM_SIZE] = {
1996         2, 3, 4, 5, 6,
1997 };
1998 
1999 const struct soc_enum madera_in_dmic_osr[] = {
2000         SOC_VALUE_ENUM_SINGLE(MADERA_DMIC1L_CONTROL, MADERA_IN1_OSR_SHIFT,
2001                               0x7, MADERA_OSR_ENUM_SIZE,
2002                               madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2003         SOC_VALUE_ENUM_SINGLE(MADERA_DMIC2L_CONTROL, MADERA_IN2_OSR_SHIFT,
2004                               0x7, MADERA_OSR_ENUM_SIZE,
2005                               madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2006         SOC_VALUE_ENUM_SINGLE(MADERA_DMIC3L_CONTROL, MADERA_IN3_OSR_SHIFT,
2007                               0x7, MADERA_OSR_ENUM_SIZE,
2008                               madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2009         SOC_VALUE_ENUM_SINGLE(MADERA_DMIC4L_CONTROL, MADERA_IN4_OSR_SHIFT,
2010                               0x7, MADERA_OSR_ENUM_SIZE,
2011                               madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2012         SOC_VALUE_ENUM_SINGLE(MADERA_DMIC5L_CONTROL, MADERA_IN5_OSR_SHIFT,
2013                               0x7, MADERA_OSR_ENUM_SIZE,
2014                               madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2015         SOC_VALUE_ENUM_SINGLE(MADERA_DMIC6L_CONTROL, MADERA_IN6_OSR_SHIFT,
2016                               0x7, MADERA_OSR_ENUM_SIZE,
2017                               madera_in_dmic_osr_text, madera_in_dmic_osr_val),
2018 };
2019 EXPORT_SYMBOL_GPL(madera_in_dmic_osr);
2020 
2021 static const char * const madera_anc_input_src_text[] = {
2022         "None", "IN1", "IN2", "IN3", "IN4", "IN5", "IN6",
2023 };
2024 
2025 static const char * const madera_anc_channel_src_text[] = {
2026         "None", "Left", "Right", "Combine",
2027 };
2028 
2029 const struct soc_enum madera_anc_input_src[] = {
2030         SOC_ENUM_SINGLE(MADERA_ANC_SRC,
2031                         MADERA_IN_RXANCL_SEL_SHIFT,
2032                         ARRAY_SIZE(madera_anc_input_src_text),
2033                         madera_anc_input_src_text),
2034         SOC_ENUM_SINGLE(MADERA_FCL_ADC_REFORMATTER_CONTROL,
2035                         MADERA_FCL_MIC_MODE_SEL_SHIFT,
2036                         ARRAY_SIZE(madera_anc_channel_src_text),
2037                         madera_anc_channel_src_text),
2038         SOC_ENUM_SINGLE(MADERA_ANC_SRC,
2039                         MADERA_IN_RXANCR_SEL_SHIFT,
2040                         ARRAY_SIZE(madera_anc_input_src_text),
2041                         madera_anc_input_src_text),
2042         SOC_ENUM_SINGLE(MADERA_FCR_ADC_REFORMATTER_CONTROL,
2043                         MADERA_FCR_MIC_MODE_SEL_SHIFT,
2044                         ARRAY_SIZE(madera_anc_channel_src_text),
2045                         madera_anc_channel_src_text),
2046 };
2047 EXPORT_SYMBOL_GPL(madera_anc_input_src);
2048 
2049 static const char * const madera_anc_ng_texts[] = {
2050         "None", "Internal", "External",
2051 };
2052 
2053 SOC_ENUM_SINGLE_DECL(madera_anc_ng_enum, SND_SOC_NOPM, 0, madera_anc_ng_texts);
2054 EXPORT_SYMBOL_GPL(madera_anc_ng_enum);
2055 
2056 static const char * const madera_out_anc_src_text[] = {
2057         "None", "RXANCL", "RXANCR",
2058 };
2059 
2060 const struct soc_enum madera_output_anc_src[] = {
2061         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_1L,
2062                         MADERA_OUT1L_ANC_SRC_SHIFT,
2063                         ARRAY_SIZE(madera_out_anc_src_text),
2064                         madera_out_anc_src_text),
2065         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_1R,
2066                         MADERA_OUT1R_ANC_SRC_SHIFT,
2067                         ARRAY_SIZE(madera_out_anc_src_text),
2068                         madera_out_anc_src_text),
2069         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_2L,
2070                         MADERA_OUT2L_ANC_SRC_SHIFT,
2071                         ARRAY_SIZE(madera_out_anc_src_text),
2072                         madera_out_anc_src_text),
2073         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_2R,
2074                         MADERA_OUT2R_ANC_SRC_SHIFT,
2075                         ARRAY_SIZE(madera_out_anc_src_text),
2076                         madera_out_anc_src_text),
2077         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_3L,
2078                         MADERA_OUT3L_ANC_SRC_SHIFT,
2079                         ARRAY_SIZE(madera_out_anc_src_text),
2080                         madera_out_anc_src_text),
2081         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_3R,
2082                         MADERA_OUT3R_ANC_SRC_SHIFT,
2083                         ARRAY_SIZE(madera_out_anc_src_text),
2084                         madera_out_anc_src_text),
2085         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_4L,
2086                         MADERA_OUT4L_ANC_SRC_SHIFT,
2087                         ARRAY_SIZE(madera_out_anc_src_text),
2088                         madera_out_anc_src_text),
2089         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_4R,
2090                         MADERA_OUT4R_ANC_SRC_SHIFT,
2091                         ARRAY_SIZE(madera_out_anc_src_text),
2092                         madera_out_anc_src_text),
2093         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_5L,
2094                         MADERA_OUT5L_ANC_SRC_SHIFT,
2095                         ARRAY_SIZE(madera_out_anc_src_text),
2096                         madera_out_anc_src_text),
2097         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_5R,
2098                         MADERA_OUT5R_ANC_SRC_SHIFT,
2099                         ARRAY_SIZE(madera_out_anc_src_text),
2100                         madera_out_anc_src_text),
2101         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_6L,
2102                         MADERA_OUT6L_ANC_SRC_SHIFT,
2103                         ARRAY_SIZE(madera_out_anc_src_text),
2104                         madera_out_anc_src_text),
2105         SOC_ENUM_SINGLE(MADERA_OUTPUT_PATH_CONFIG_6R,
2106                         MADERA_OUT6R_ANC_SRC_SHIFT,
2107                         ARRAY_SIZE(madera_out_anc_src_text),
2108                         madera_out_anc_src_text),
2109 };
2110 EXPORT_SYMBOL_GPL(madera_output_anc_src);
2111 
2112 int madera_dfc_put(struct snd_kcontrol *kcontrol,
2113                    struct snd_ctl_elem_value *ucontrol)
2114 {
2115         struct snd_soc_component *component =
2116                 snd_soc_kcontrol_component(kcontrol);
2117         struct snd_soc_dapm_context *dapm =
2118                 snd_soc_component_get_dapm(component);
2119         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
2120         unsigned int reg = e->reg;
2121         unsigned int val;
2122         int ret = 0;
2123 
2124         reg = ((reg / 6) * 6) - 2;
2125 
2126         snd_soc_dapm_mutex_lock(dapm);
2127 
2128         ret = snd_soc_component_read(component, reg, &val);
2129         if (ret)
2130                 goto exit;
2131 
2132         if (val & MADERA_DFC1_ENA) {
2133                 ret = -EBUSY;
2134                 dev_err(component->dev, "Can't change mode on an active DFC\n");
2135                 goto exit;
2136         }
2137 
2138         ret = snd_soc_put_enum_double(kcontrol, ucontrol);
2139 exit:
2140         snd_soc_dapm_mutex_unlock(dapm);
2141 
2142         return ret;
2143 }
2144 EXPORT_SYMBOL_GPL(madera_dfc_put);
2145 
2146 int madera_lp_mode_put(struct snd_kcontrol *kcontrol,
2147                        struct snd_ctl_elem_value *ucontrol)
2148 {
2149         struct soc_mixer_control *mc =
2150                 (struct soc_mixer_control *)kcontrol->private_value;
2151         struct snd_soc_component *component =
2152                 snd_soc_kcontrol_component(kcontrol);
2153         struct snd_soc_dapm_context *dapm =
2154                 snd_soc_component_get_dapm(component);
2155         unsigned int val, mask;
2156         int ret;
2157 
2158         snd_soc_dapm_mutex_lock(dapm);
2159 
2160         /* Cannot change lp mode on an active input */
2161         ret = snd_soc_component_read(component, MADERA_INPUT_ENABLES, &val);
2162         if (ret)
2163                 goto exit;
2164         mask = (mc->reg - MADERA_ADC_DIGITAL_VOLUME_1L) / 4;
2165         mask ^= 0x1; /* Flip bottom bit for channel order */
2166 
2167         if (val & (1 << mask)) {
2168                 ret = -EBUSY;
2169                 dev_err(component->dev,
2170                         "Can't change lp mode on an active input\n");
2171                 goto exit;
2172         }
2173 
2174         ret = snd_soc_put_volsw(kcontrol, ucontrol);
2175 
2176 exit:
2177         snd_soc_dapm_mutex_unlock(dapm);
2178 
2179         return ret;
2180 }
2181 EXPORT_SYMBOL_GPL(madera_lp_mode_put);
2182 
2183 const struct snd_kcontrol_new madera_dsp_trigger_output_mux[] = {
2184         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2185         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2186         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2187         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2188         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2189         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2190         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2191 };
2192 EXPORT_SYMBOL_GPL(madera_dsp_trigger_output_mux);
2193 
2194 const struct snd_kcontrol_new madera_drc_activity_output_mux[] = {
2195         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2196         SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0),
2197 };
2198 EXPORT_SYMBOL_GPL(madera_drc_activity_output_mux);
2199 
2200 static void madera_in_set_vu(struct madera_priv *priv, bool enable)
2201 {
2202         unsigned int val;
2203         int i, ret;
2204 
2205         if (enable)
2206                 val = MADERA_IN_VU;
2207         else
2208                 val = 0;
2209 
2210         for (i = 0; i < priv->num_inputs; i++) {
2211                 ret = regmap_update_bits(priv->madera->regmap,
2212                                          MADERA_ADC_DIGITAL_VOLUME_1L + (i * 4),
2213                                          MADERA_IN_VU, val);
2214                 if (ret)
2215                         dev_warn(priv->madera->dev,
2216                                  "Failed to modify VU bits: %d\n", ret);
2217         }
2218 }
2219 
2220 int madera_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
2221                  int event)
2222 {
2223         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2224         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2225         unsigned int reg, val;
2226         int ret;
2227 
2228         if (w->shift % 2)
2229                 reg = MADERA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
2230         else
2231                 reg = MADERA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
2232 
2233         switch (event) {
2234         case SND_SOC_DAPM_PRE_PMU:
2235                 priv->in_pending++;
2236                 break;
2237         case SND_SOC_DAPM_POST_PMU:
2238                 priv->in_pending--;
2239                 snd_soc_component_update_bits(component, reg,
2240                                               MADERA_IN1L_MUTE, 0);
2241 
2242                 /* If this is the last input pending then allow VU */
2243                 if (priv->in_pending == 0) {
2244                         usleep_range(1000, 3000);
2245                         madera_in_set_vu(priv, true);
2246                 }
2247                 break;
2248         case SND_SOC_DAPM_PRE_PMD:
2249                 snd_soc_component_update_bits(component, reg,
2250                                               MADERA_IN1L_MUTE | MADERA_IN_VU,
2251                                               MADERA_IN1L_MUTE | MADERA_IN_VU);
2252                 break;
2253         case SND_SOC_DAPM_POST_PMD:
2254                 /* Disable volume updates if no inputs are enabled */
2255                 ret = snd_soc_component_read(component, MADERA_INPUT_ENABLES,
2256                                              &val);
2257                 if (!ret && !val)
2258                         madera_in_set_vu(priv, false);
2259                 break;
2260         default:
2261                 break;
2262         }
2263 
2264         return 0;
2265 }
2266 EXPORT_SYMBOL_GPL(madera_in_ev);
2267 
2268 int madera_out_ev(struct snd_soc_dapm_widget *w,
2269                   struct snd_kcontrol *kcontrol, int event)
2270 {
2271         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2272         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2273         struct madera *madera = priv->madera;
2274         int out_up_delay;
2275 
2276         switch (madera->type) {
2277         case CS47L90:
2278         case CS47L91:
2279         case CS42L92:
2280         case CS47L92:
2281         case CS47L93:
2282                 out_up_delay = 6;
2283                 break;
2284         default:
2285                 out_up_delay = 17;
2286                 break;
2287         }
2288 
2289         switch (event) {
2290         case SND_SOC_DAPM_PRE_PMU:
2291                 switch (w->shift) {
2292                 case MADERA_OUT1L_ENA_SHIFT:
2293                 case MADERA_OUT1R_ENA_SHIFT:
2294                 case MADERA_OUT2L_ENA_SHIFT:
2295                 case MADERA_OUT2R_ENA_SHIFT:
2296                 case MADERA_OUT3L_ENA_SHIFT:
2297                 case MADERA_OUT3R_ENA_SHIFT:
2298                         priv->out_up_pending++;
2299                         priv->out_up_delay += out_up_delay;
2300                         break;
2301                 default:
2302                         break;
2303                 }
2304                 break;
2305 
2306         case SND_SOC_DAPM_POST_PMU:
2307                 switch (w->shift) {
2308                 case MADERA_OUT1L_ENA_SHIFT:
2309                 case MADERA_OUT1R_ENA_SHIFT:
2310                 case MADERA_OUT2L_ENA_SHIFT:
2311                 case MADERA_OUT2R_ENA_SHIFT:
2312                 case MADERA_OUT3L_ENA_SHIFT:
2313                 case MADERA_OUT3R_ENA_SHIFT:
2314                         priv->out_up_pending--;
2315                         if (!priv->out_up_pending) {
2316                                 msleep(priv->out_up_delay);
2317                                 priv->out_up_delay = 0;
2318                         }
2319                         break;
2320 
2321                 default:
2322                         break;
2323                 }
2324                 break;
2325 
2326         case SND_SOC_DAPM_PRE_PMD:
2327                 switch (w->shift) {
2328                 case MADERA_OUT1L_ENA_SHIFT:
2329                 case MADERA_OUT1R_ENA_SHIFT:
2330                 case MADERA_OUT2L_ENA_SHIFT:
2331                 case MADERA_OUT2R_ENA_SHIFT:
2332                 case MADERA_OUT3L_ENA_SHIFT:
2333                 case MADERA_OUT3R_ENA_SHIFT:
2334                         priv->out_down_pending++;
2335                         priv->out_down_delay++;
2336                         break;
2337                 default:
2338                         break;
2339                 }
2340                 break;
2341 
2342         case SND_SOC_DAPM_POST_PMD:
2343                 switch (w->shift) {
2344                 case MADERA_OUT1L_ENA_SHIFT:
2345                 case MADERA_OUT1R_ENA_SHIFT:
2346                 case MADERA_OUT2L_ENA_SHIFT:
2347                 case MADERA_OUT2R_ENA_SHIFT:
2348                 case MADERA_OUT3L_ENA_SHIFT:
2349                 case MADERA_OUT3R_ENA_SHIFT:
2350                         priv->out_down_pending--;
2351                         if (!priv->out_down_pending) {
2352                                 msleep(priv->out_down_delay);
2353                                 priv->out_down_delay = 0;
2354                         }
2355                         break;
2356                 default:
2357                         break;
2358                 }
2359                 break;
2360         default:
2361                 break;
2362         }
2363 
2364         return 0;
2365 }
2366 EXPORT_SYMBOL_GPL(madera_out_ev);
2367 
2368 int madera_hp_ev(struct snd_soc_dapm_widget *w,
2369                  struct snd_kcontrol *kcontrol, int event)
2370 {
2371         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2372         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2373         struct madera *madera = priv->madera;
2374         unsigned int mask = 1 << w->shift;
2375         unsigned int out_num = w->shift / 2;
2376         unsigned int val;
2377         unsigned int ep_sel = 0;
2378 
2379         switch (event) {
2380         case SND_SOC_DAPM_POST_PMU:
2381                 val = mask;
2382                 break;
2383         case SND_SOC_DAPM_PRE_PMD:
2384                 val = 0;
2385                 break;
2386         case SND_SOC_DAPM_PRE_PMU:
2387         case SND_SOC_DAPM_POST_PMD:
2388                 return madera_out_ev(w, kcontrol, event);
2389         default:
2390                 return 0;
2391         }
2392 
2393         /* Store the desired state for the HP outputs */
2394         madera->hp_ena &= ~mask;
2395         madera->hp_ena |= val;
2396 
2397         switch (madera->type) {
2398         case CS42L92:
2399         case CS47L92:
2400         case CS47L93:
2401                 break;
2402         default:
2403                 /* if OUT1 is routed to EPOUT, ignore HP clamp and impedance */
2404                 regmap_read(madera->regmap, MADERA_OUTPUT_ENABLES_1, &ep_sel);
2405                 ep_sel &= MADERA_EP_SEL_MASK;
2406                 break;
2407         }
2408 
2409         /* Force off if HPDET has disabled the clamp for this output */
2410         if (!ep_sel &&
2411             (!madera->out_clamp[out_num] || madera->out_shorted[out_num]))
2412                 val = 0;
2413 
2414         regmap_update_bits(madera->regmap, MADERA_OUTPUT_ENABLES_1, mask, val);
2415 
2416         return madera_out_ev(w, kcontrol, event);
2417 }
2418 EXPORT_SYMBOL_GPL(madera_hp_ev);
2419 
2420 int madera_anc_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
2421                   int event)
2422 {
2423         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2424         unsigned int val;
2425 
2426         switch (event) {
2427         case SND_SOC_DAPM_POST_PMU:
2428                 val = 1 << w->shift;
2429                 break;
2430         case SND_SOC_DAPM_PRE_PMD:
2431                 val = 1 << (w->shift + 1);
2432                 break;
2433         default:
2434                 return 0;
2435         }
2436 
2437         snd_soc_component_write(component, MADERA_CLOCK_CONTROL, val);
2438 
2439         return 0;
2440 }
2441 EXPORT_SYMBOL_GPL(madera_anc_ev);
2442 
2443 static const unsigned int madera_opclk_ref_48k_rates[] = {
2444         6144000,
2445         12288000,
2446         24576000,
2447         49152000,
2448 };
2449 
2450 static const unsigned int madera_opclk_ref_44k1_rates[] = {
2451         5644800,
2452         11289600,
2453         22579200,
2454         45158400,
2455 };
2456 
2457 static int madera_set_opclk(struct snd_soc_component *component,
2458                             unsigned int clk, unsigned int freq)
2459 {
2460         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2461         unsigned int mask = MADERA_OPCLK_DIV_MASK | MADERA_OPCLK_SEL_MASK;
2462         unsigned int reg, val;
2463         const unsigned int *rates;
2464         int ref, div, refclk;
2465 
2466         BUILD_BUG_ON(ARRAY_SIZE(madera_opclk_ref_48k_rates) !=
2467                      ARRAY_SIZE(madera_opclk_ref_44k1_rates));
2468 
2469         switch (clk) {
2470         case MADERA_CLK_OPCLK:
2471                 reg = MADERA_OUTPUT_SYSTEM_CLOCK;
2472                 refclk = priv->sysclk;
2473                 break;
2474         case MADERA_CLK_ASYNC_OPCLK:
2475                 reg = MADERA_OUTPUT_ASYNC_CLOCK;
2476                 refclk = priv->asyncclk;
2477                 break;
2478         default:
2479                 return -EINVAL;
2480         }
2481 
2482         if (refclk % 4000)
2483                 rates = madera_opclk_ref_44k1_rates;
2484         else
2485                 rates = madera_opclk_ref_48k_rates;
2486 
2487         for (ref = 0; ref < ARRAY_SIZE(madera_opclk_ref_48k_rates); ++ref) {
2488                 if (rates[ref] > refclk)
2489                         continue;
2490 
2491                 div = 2;
2492                 while ((rates[ref] / div >= freq) && (div <= 30)) {
2493                         if (rates[ref] / div == freq) {
2494                                 dev_dbg(component->dev, "Configured %dHz OPCLK\n",
2495                                         freq);
2496 
2497                                 val = (div << MADERA_OPCLK_DIV_SHIFT) | ref;
2498 
2499                                 snd_soc_component_update_bits(component, reg,
2500                                                               mask, val);
2501                                 return 0;
2502                         }
2503                         div += 2;
2504                 }
2505         }
2506 
2507         dev_err(component->dev, "Unable to generate %dHz OPCLK\n", freq);
2508 
2509         return -EINVAL;
2510 }
2511 
2512 static int madera_get_sysclk_setting(unsigned int freq)
2513 {
2514         switch (freq) {
2515         case 0:
2516         case 5644800:
2517         case 6144000:
2518                 return 0;
2519         case 11289600:
2520         case 12288000:
2521                 return MADERA_SYSCLK_12MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2522         case 22579200:
2523         case 24576000:
2524                 return MADERA_SYSCLK_24MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2525         case 45158400:
2526         case 49152000:
2527                 return MADERA_SYSCLK_49MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2528         case 90316800:
2529         case 98304000:
2530                 return MADERA_SYSCLK_98MHZ << MADERA_SYSCLK_FREQ_SHIFT;
2531         default:
2532                 return -EINVAL;
2533         }
2534 }
2535 
2536 static int madera_get_legacy_dspclk_setting(struct madera *madera,
2537                                             unsigned int freq)
2538 {
2539         switch (freq) {
2540         case 0:
2541                 return 0;
2542         case 45158400:
2543         case 49152000:
2544                 switch (madera->type) {
2545                 case CS47L85:
2546                 case WM1840:
2547                         if (madera->rev < 3)
2548                                 return -EINVAL;
2549                         else
2550                                 return MADERA_SYSCLK_49MHZ <<
2551                                        MADERA_SYSCLK_FREQ_SHIFT;
2552                 default:
2553                         return -EINVAL;
2554                 }
2555         case 135475200:
2556         case 147456000:
2557                 return MADERA_DSPCLK_147MHZ << MADERA_DSP_CLK_FREQ_LEGACY_SHIFT;
2558         default:
2559                 return -EINVAL;
2560         }
2561 }
2562 
2563 static int madera_get_dspclk_setting(struct madera *madera,
2564                                      unsigned int freq,
2565                                      unsigned int *clock_2_val)
2566 {
2567         switch (madera->type) {
2568         case CS47L35:
2569         case CS47L85:
2570         case WM1840:
2571                 *clock_2_val = 0; /* don't use MADERA_DSP_CLOCK_2 */
2572                 return madera_get_legacy_dspclk_setting(madera, freq);
2573         default:
2574                 if (freq > 150000000)
2575                         return -EINVAL;
2576 
2577                 /* Use new exact frequency control */
2578                 *clock_2_val = freq / 15625; /* freq * (2^6) / (10^6) */
2579                 return 0;
2580         }
2581 }
2582 
2583 static int madera_set_outclk(struct snd_soc_component *component,
2584                              unsigned int source, unsigned int freq)
2585 {
2586         int div, div_inc, rate;
2587 
2588         switch (source) {
2589         case MADERA_OUTCLK_SYSCLK:
2590                 dev_dbg(component->dev, "Configured OUTCLK to SYSCLK\n");
2591                 snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
2592                                               MADERA_OUT_CLK_SRC_MASK, source);
2593                 return 0;
2594         case MADERA_OUTCLK_ASYNCCLK:
2595                 dev_dbg(component->dev, "Configured OUTCLK to ASYNCCLK\n");
2596                 snd_soc_component_update_bits(component, MADERA_OUTPUT_RATE_1,
2597                                               MADERA_OUT_CLK_SRC_MASK, source);
2598                 return 0;
2599         case MADERA_OUTCLK_MCLK1:
2600         case MADERA_OUTCLK_MCLK2:
2601         case MADERA_OUTCLK_MCLK3:
2602                 break;
2603         default:
2604                 return -EINVAL;
2605         }
2606 
2607         if (freq % 4000)
2608                 rate = 5644800;
2609         else
2610                 rate = 6144000;
2611 
2612         div = 1;
2613         div_inc = 0;
2614         while (div <= 8) {
2615                 if (freq / div == rate && !(freq % div)) {
2616                         dev_dbg(component->dev, "Configured %dHz OUTCLK\n", rate);
2617                         snd_soc_component_update_bits(component,
2618                                 MADERA_OUTPUT_RATE_1,
2619                                 MADERA_OUT_EXT_CLK_DIV_MASK |
2620                                 MADERA_OUT_CLK_SRC_MASK,
2621                                 (div_inc << MADERA_OUT_EXT_CLK_DIV_SHIFT) |
2622                                 source);
2623                         return 0;
2624                 }
2625                 div_inc++;
2626                 div *= 2;
2627         }
2628 
2629         dev_err(component->dev,
2630                 "Unable to generate %dHz OUTCLK from %dHz MCLK\n",
2631                 rate, freq);
2632         return -EINVAL;
2633 }
2634 
2635 int madera_set_sysclk(struct snd_soc_component *component, int clk_id,
2636                       int source, unsigned int freq, int dir)
2637 {
2638         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2639         struct madera *madera = priv->madera;
2640         char *name;
2641         unsigned int reg, clock_2_val = 0;
2642         unsigned int mask = MADERA_SYSCLK_FREQ_MASK | MADERA_SYSCLK_SRC_MASK;
2643         unsigned int val = source << MADERA_SYSCLK_SRC_SHIFT;
2644         int clk_freq_sel, *clk;
2645         int ret = 0;
2646 
2647         switch (clk_id) {
2648         case MADERA_CLK_SYSCLK_1:
2649                 name = "SYSCLK";
2650                 reg = MADERA_SYSTEM_CLOCK_1;
2651                 clk = &priv->sysclk;
2652                 clk_freq_sel = madera_get_sysclk_setting(freq);
2653                 mask |= MADERA_SYSCLK_FRAC;
2654                 break;
2655         case MADERA_CLK_ASYNCCLK_1:
2656                 name = "ASYNCCLK";
2657                 reg = MADERA_ASYNC_CLOCK_1;
2658                 clk = &priv->asyncclk;
2659                 clk_freq_sel = madera_get_sysclk_setting(freq);
2660                 break;
2661         case MADERA_CLK_DSPCLK:
2662                 name = "DSPCLK";
2663                 reg = MADERA_DSP_CLOCK_1;
2664                 clk = &priv->dspclk;
2665                 clk_freq_sel = madera_get_dspclk_setting(madera, freq,
2666                                                          &clock_2_val);
2667                 break;
2668         case MADERA_CLK_OPCLK:
2669         case MADERA_CLK_ASYNC_OPCLK:
2670                 return madera_set_opclk(component, clk_id, freq);
2671         case MADERA_CLK_OUTCLK:
2672                 return madera_set_outclk(component, source, freq);
2673         default:
2674                 return -EINVAL;
2675         }
2676 
2677         if (clk_freq_sel < 0) {
2678                 dev_err(madera->dev,
2679                         "Failed to get clk setting for %dHZ\n", freq);
2680                 return clk_freq_sel;
2681         }
2682 
2683         *clk = freq;
2684 
2685         if (freq == 0) {
2686                 dev_dbg(madera->dev, "%s cleared\n", name);
2687                 return 0;
2688         }
2689 
2690         val |= clk_freq_sel;
2691 
2692         if (clock_2_val) {
2693                 ret = regmap_write(madera->regmap, MADERA_DSP_CLOCK_2,
2694                                    clock_2_val);
2695                 if (ret) {
2696                         dev_err(madera->dev,
2697                                 "Failed to write DSP_CONFIG2: %d\n", ret);
2698                         return ret;
2699                 }
2700 
2701                 /*
2702                  * We're using the frequency setting in MADERA_DSP_CLOCK_2 so
2703                  * don't change the frequency select bits in MADERA_DSP_CLOCK_1
2704                  */
2705                 mask = MADERA_SYSCLK_SRC_MASK;
2706         }
2707 
2708         if (freq % 6144000)
2709                 val |= MADERA_SYSCLK_FRAC;
2710 
2711         dev_dbg(madera->dev, "%s set to %uHz\n", name, freq);
2712 
2713         return regmap_update_bits(madera->regmap, reg, mask, val);
2714 }
2715 EXPORT_SYMBOL_GPL(madera_set_sysclk);
2716 
2717 static int madera_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2718 {
2719         struct snd_soc_component *component = dai->component;
2720         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2721         struct madera *madera = priv->madera;
2722         int lrclk, bclk, mode, base;
2723 
2724         base = dai->driver->base;
2725 
2726         lrclk = 0;
2727         bclk = 0;
2728 
2729         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2730         case SND_SOC_DAIFMT_DSP_A:
2731                 mode = MADERA_FMT_DSP_MODE_A;
2732                 break;
2733         case SND_SOC_DAIFMT_DSP_B:
2734                 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) !=
2735                     SND_SOC_DAIFMT_CBM_CFM) {
2736                         madera_aif_err(dai, "DSP_B not valid in slave mode\n");
2737                         return -EINVAL;
2738                 }
2739                 mode = MADERA_FMT_DSP_MODE_B;
2740                 break;
2741         case SND_SOC_DAIFMT_I2S:
2742                 mode = MADERA_FMT_I2S_MODE;
2743                 break;
2744         case SND_SOC_DAIFMT_LEFT_J:
2745                 if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) !=
2746                     SND_SOC_DAIFMT_CBM_CFM) {
2747                         madera_aif_err(dai, "LEFT_J not valid in slave mode\n");
2748                         return -EINVAL;
2749                 }
2750                 mode = MADERA_FMT_LEFT_JUSTIFIED_MODE;
2751                 break;
2752         default:
2753                 madera_aif_err(dai, "Unsupported DAI format %d\n",
2754                                fmt & SND_SOC_DAIFMT_FORMAT_MASK);
2755                 return -EINVAL;
2756         }
2757 
2758         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
2759         case SND_SOC_DAIFMT_CBS_CFS:
2760                 break;
2761         case SND_SOC_DAIFMT_CBS_CFM:
2762                 lrclk |= MADERA_AIF1TX_LRCLK_MSTR;
2763                 break;
2764         case SND_SOC_DAIFMT_CBM_CFS:
2765                 bclk |= MADERA_AIF1_BCLK_MSTR;
2766                 break;
2767         case SND_SOC_DAIFMT_CBM_CFM:
2768                 bclk |= MADERA_AIF1_BCLK_MSTR;
2769                 lrclk |= MADERA_AIF1TX_LRCLK_MSTR;
2770                 break;
2771         default:
2772                 madera_aif_err(dai, "Unsupported master mode %d\n",
2773                                fmt & SND_SOC_DAIFMT_MASTER_MASK);
2774                 return -EINVAL;
2775         }
2776 
2777         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
2778         case SND_SOC_DAIFMT_NB_NF:
2779                 break;
2780         case SND_SOC_DAIFMT_IB_IF:
2781                 bclk |= MADERA_AIF1_BCLK_INV;
2782                 lrclk |= MADERA_AIF1TX_LRCLK_INV;
2783                 break;
2784         case SND_SOC_DAIFMT_IB_NF:
2785                 bclk |= MADERA_AIF1_BCLK_INV;
2786                 break;
2787         case SND_SOC_DAIFMT_NB_IF:
2788                 lrclk |= MADERA_AIF1TX_LRCLK_INV;
2789                 break;
2790         default:
2791                 madera_aif_err(dai, "Unsupported invert mode %d\n",
2792                                fmt & SND_SOC_DAIFMT_INV_MASK);
2793                 return -EINVAL;
2794         }
2795 
2796         regmap_update_bits(madera->regmap, base + MADERA_AIF_BCLK_CTRL,
2797                            MADERA_AIF1_BCLK_INV | MADERA_AIF1_BCLK_MSTR,
2798                            bclk);
2799         regmap_update_bits(madera->regmap, base + MADERA_AIF_TX_PIN_CTRL,
2800                            MADERA_AIF1TX_LRCLK_INV | MADERA_AIF1TX_LRCLK_MSTR,
2801                            lrclk);
2802         regmap_update_bits(madera->regmap, base + MADERA_AIF_RX_PIN_CTRL,
2803                            MADERA_AIF1RX_LRCLK_INV | MADERA_AIF1RX_LRCLK_MSTR,
2804                            lrclk);
2805         regmap_update_bits(madera->regmap, base + MADERA_AIF_FORMAT,
2806                            MADERA_AIF1_FMT_MASK, mode);
2807 
2808         return 0;
2809 }
2810 
2811 static const int madera_48k_bclk_rates[] = {
2812         -1,
2813         48000,
2814         64000,
2815         96000,
2816         128000,
2817         192000,
2818         256000,
2819         384000,
2820         512000,
2821         768000,
2822         1024000,
2823         1536000,
2824         2048000,
2825         3072000,
2826         4096000,
2827         6144000,
2828         8192000,
2829         12288000,
2830         24576000,
2831 };
2832 
2833 static const int madera_44k1_bclk_rates[] = {
2834         -1,
2835         44100,
2836         58800,
2837         88200,
2838         117600,
2839         177640,
2840         235200,
2841         352800,
2842         470400,
2843         705600,
2844         940800,
2845         1411200,
2846         1881600,
2847         2822400,
2848         3763200,
2849         5644800,
2850         7526400,
2851         11289600,
2852         22579200,
2853 };
2854 
2855 static const unsigned int madera_sr_vals[] = {
2856         0,
2857         12000,
2858         24000,
2859         48000,
2860         96000,
2861         192000,
2862         384000,
2863         768000,
2864         0,
2865         11025,
2866         22050,
2867         44100,
2868         88200,
2869         176400,
2870         352800,
2871         705600,
2872         4000,
2873         8000,
2874         16000,
2875         32000,
2876         64000,
2877         128000,
2878         256000,
2879         512000,
2880 };
2881 
2882 #define MADERA_192K_48K_RATE_MASK       0x0F003E
2883 #define MADERA_192K_44K1_RATE_MASK      0x003E00
2884 #define MADERA_192K_RATE_MASK           (MADERA_192K_48K_RATE_MASK | \
2885                                          MADERA_192K_44K1_RATE_MASK)
2886 #define MADERA_384K_48K_RATE_MASK       0x0F007E
2887 #define MADERA_384K_44K1_RATE_MASK      0x007E00
2888 #define MADERA_384K_RATE_MASK           (MADERA_384K_48K_RATE_MASK | \
2889                                          MADERA_384K_44K1_RATE_MASK)
2890 
2891 static const struct snd_pcm_hw_constraint_list madera_constraint = {
2892         .count  = ARRAY_SIZE(madera_sr_vals),
2893         .list   = madera_sr_vals,
2894 };
2895 
2896 static int madera_startup(struct snd_pcm_substream *substream,
2897                           struct snd_soc_dai *dai)
2898 {
2899         struct snd_soc_component *component = dai->component;
2900         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2901         struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
2902         struct madera *madera = priv->madera;
2903         unsigned int base_rate;
2904 
2905         if (!substream->runtime)
2906                 return 0;
2907 
2908         switch (dai_priv->clk) {
2909         case MADERA_CLK_SYSCLK_1:
2910         case MADERA_CLK_SYSCLK_2:
2911         case MADERA_CLK_SYSCLK_3:
2912                 base_rate = priv->sysclk;
2913                 break;
2914         case MADERA_CLK_ASYNCCLK_1:
2915         case MADERA_CLK_ASYNCCLK_2:
2916                 base_rate = priv->asyncclk;
2917                 break;
2918         default:
2919                 return 0;
2920         }
2921 
2922         switch (madera->type) {
2923         case CS42L92:
2924         case CS47L92:
2925         case CS47L93:
2926                 if (base_rate == 0)
2927                         dai_priv->constraint.mask = MADERA_384K_RATE_MASK;
2928                 else if (base_rate % 4000)
2929                         dai_priv->constraint.mask = MADERA_384K_44K1_RATE_MASK;
2930                 else
2931                         dai_priv->constraint.mask = MADERA_384K_48K_RATE_MASK;
2932                 break;
2933         default:
2934                 if (base_rate == 0)
2935                         dai_priv->constraint.mask = MADERA_192K_RATE_MASK;
2936                 else if (base_rate % 4000)
2937                         dai_priv->constraint.mask = MADERA_192K_44K1_RATE_MASK;
2938                 else
2939                         dai_priv->constraint.mask = MADERA_192K_48K_RATE_MASK;
2940                 break;
2941         }
2942 
2943         return snd_pcm_hw_constraint_list(substream->runtime, 0,
2944                                           SNDRV_PCM_HW_PARAM_RATE,
2945                                           &dai_priv->constraint);
2946 }
2947 
2948 static int madera_hw_params_rate(struct snd_pcm_substream *substream,
2949                                  struct snd_pcm_hw_params *params,
2950                                  struct snd_soc_dai *dai)
2951 {
2952         struct snd_soc_component *component = dai->component;
2953         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
2954         struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
2955         int base = dai->driver->base;
2956         int i, sr_val;
2957         unsigned int reg, cur, tar;
2958         int ret;
2959 
2960         for (i = 0; i < ARRAY_SIZE(madera_sr_vals); i++)
2961                 if (madera_sr_vals[i] == params_rate(params))
2962                         break;
2963 
2964         if (i == ARRAY_SIZE(madera_sr_vals)) {
2965                 madera_aif_err(dai, "Unsupported sample rate %dHz\n",
2966                                params_rate(params));
2967                 return -EINVAL;
2968         }
2969         sr_val = i;
2970 
2971         switch (dai_priv->clk) {
2972         case MADERA_CLK_SYSCLK_1:
2973                 reg = MADERA_SAMPLE_RATE_1;
2974                 tar = 0 << MADERA_AIF1_RATE_SHIFT;
2975                 break;
2976         case MADERA_CLK_SYSCLK_2:
2977                 reg = MADERA_SAMPLE_RATE_2;
2978                 tar = 1 << MADERA_AIF1_RATE_SHIFT;
2979                 break;
2980         case MADERA_CLK_SYSCLK_3:
2981                 reg = MADERA_SAMPLE_RATE_3;
2982                 tar = 2 << MADERA_AIF1_RATE_SHIFT;
2983                 break;
2984         case MADERA_CLK_ASYNCCLK_1:
2985                 reg = MADERA_ASYNC_SAMPLE_RATE_1,
2986                 tar = 8 << MADERA_AIF1_RATE_SHIFT;
2987                 break;
2988         case MADERA_CLK_ASYNCCLK_2:
2989                 reg = MADERA_ASYNC_SAMPLE_RATE_2,
2990                 tar = 9 << MADERA_AIF1_RATE_SHIFT;
2991                 break;
2992         default:
2993                 madera_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
2994                 return -EINVAL;
2995         }
2996 
2997         snd_soc_component_update_bits(component, reg, MADERA_SAMPLE_RATE_1_MASK,
2998                                       sr_val);
2999 
3000         if (!base)
3001                 return 0;
3002 
3003         ret = regmap_read(priv->madera->regmap,
3004                           base + MADERA_AIF_RATE_CTRL, &cur);
3005         if (ret != 0) {
3006                 madera_aif_err(dai, "Failed to check rate: %d\n", ret);
3007                 return ret;
3008         }
3009 
3010         if ((cur & MADERA_AIF1_RATE_MASK) == (tar & MADERA_AIF1_RATE_MASK))
3011                 return 0;
3012 
3013         mutex_lock(&priv->rate_lock);
3014 
3015         if (!madera_can_change_grp_rate(priv, base + MADERA_AIF_RATE_CTRL)) {
3016                 madera_aif_warn(dai, "Cannot change rate while active\n");
3017                 ret = -EBUSY;
3018                 goto out;
3019         }
3020 
3021         /* Guard the rate change with SYSCLK cycles */
3022         madera_spin_sysclk(priv);
3023         snd_soc_component_update_bits(component, base + MADERA_AIF_RATE_CTRL,
3024                                       MADERA_AIF1_RATE_MASK, tar);
3025         madera_spin_sysclk(priv);
3026 
3027 out:
3028         mutex_unlock(&priv->rate_lock);
3029 
3030         return ret;
3031 }
3032 
3033 static int madera_aif_cfg_changed(struct snd_soc_component *component,
3034                                   int base, int bclk, int lrclk, int frame)
3035 {
3036         unsigned int val;
3037         int ret;
3038 
3039         ret = snd_soc_component_read(component, base + MADERA_AIF_BCLK_CTRL,
3040                                      &val);
3041         if (ret)
3042                 return ret;
3043         if (bclk != (val & MADERA_AIF1_BCLK_FREQ_MASK))
3044                 return 1;
3045 
3046         ret = snd_soc_component_read(component, base + MADERA_AIF_RX_BCLK_RATE,
3047                                      &val);
3048         if (ret)
3049                 return ret;
3050         if (lrclk != (val & MADERA_AIF1RX_BCPF_MASK))
3051                 return 1;
3052 
3053         ret = snd_soc_component_read(component, base + MADERA_AIF_FRAME_CTRL_1,
3054                                      &val);
3055         if (ret)
3056                 return ret;
3057         if (frame != (val & (MADERA_AIF1TX_WL_MASK |
3058                              MADERA_AIF1TX_SLOT_LEN_MASK)))
3059                 return 1;
3060 
3061         return 0;
3062 }
3063 
3064 static int madera_hw_params(struct snd_pcm_substream *substream,
3065                             struct snd_pcm_hw_params *params,
3066                             struct snd_soc_dai *dai)
3067 {
3068         struct snd_soc_component *component = dai->component;
3069         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3070         struct madera *madera = priv->madera;
3071         int base = dai->driver->base;
3072         const int *rates;
3073         int i, ret;
3074         unsigned int val;
3075         unsigned int channels = params_channels(params);
3076         unsigned int rate = params_rate(params);
3077         unsigned int chan_limit =
3078                         madera->pdata.codec.max_channels_clocked[dai->id - 1];
3079         int tdm_width = priv->tdm_width[dai->id - 1];
3080         int tdm_slots = priv->tdm_slots[dai->id - 1];
3081         int bclk, lrclk, wl, frame, bclk_target, num_rates;
3082         int reconfig;
3083         unsigned int aif_tx_state = 0, aif_rx_state = 0;
3084 
3085         if (rate % 4000) {
3086                 rates = &madera_44k1_bclk_rates[0];
3087                 num_rates = ARRAY_SIZE(madera_44k1_bclk_rates);
3088         } else {
3089                 rates = &madera_48k_bclk_rates[0];
3090                 num_rates = ARRAY_SIZE(madera_48k_bclk_rates);
3091         }
3092 
3093         wl = snd_pcm_format_width(params_format(params));
3094 
3095         if (tdm_slots) {
3096                 madera_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
3097                                tdm_slots, tdm_width);
3098                 bclk_target = tdm_slots * tdm_width * rate;
3099                 channels = tdm_slots;
3100         } else {
3101                 bclk_target = snd_soc_params_to_bclk(params);
3102                 tdm_width = wl;
3103         }
3104 
3105         if (chan_limit && chan_limit < channels) {
3106                 madera_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
3107                 bclk_target /= channels;
3108                 bclk_target *= chan_limit;
3109         }
3110 
3111         /* Force multiple of 2 channels for I2S mode */
3112         ret = snd_soc_component_read(component, base + MADERA_AIF_FORMAT, &val);
3113         if (ret)
3114                 return ret;
3115 
3116         val &= MADERA_AIF1_FMT_MASK;
3117         if ((channels & 1) && val == MADERA_FMT_I2S_MODE) {
3118                 madera_aif_dbg(dai, "Forcing stereo mode\n");
3119                 bclk_target /= channels;
3120                 bclk_target *= channels + 1;
3121         }
3122 
3123         for (i = 0; i < num_rates; i++) {
3124                 if (rates[i] >= bclk_target && rates[i] % rate == 0) {
3125                         bclk = i;
3126                         break;
3127                 }
3128         }
3129 
3130         if (i == num_rates) {
3131                 madera_aif_err(dai, "Unsupported sample rate %dHz\n", rate);
3132                 return -EINVAL;
3133         }
3134 
3135         lrclk = rates[bclk] / rate;
3136 
3137         madera_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
3138                        rates[bclk], rates[bclk] / lrclk);
3139 
3140         frame = wl << MADERA_AIF1TX_WL_SHIFT | tdm_width;
3141 
3142         reconfig = madera_aif_cfg_changed(component, base, bclk, lrclk, frame);
3143         if (reconfig < 0)
3144                 return reconfig;
3145 
3146         if (reconfig) {
3147                 /* Save AIF TX/RX state */
3148                 regmap_read(madera->regmap, base + MADERA_AIF_TX_ENABLES,
3149                             &aif_tx_state);
3150                 regmap_read(madera->regmap, base + MADERA_AIF_RX_ENABLES,
3151                             &aif_rx_state);
3152                 /* Disable AIF TX/RX before reconfiguring it */
3153                 regmap_update_bits(madera->regmap,
3154                                    base + MADERA_AIF_TX_ENABLES, 0xff, 0x0);
3155                 regmap_update_bits(madera->regmap,
3156                                    base + MADERA_AIF_RX_ENABLES, 0xff, 0x0);
3157         }
3158 
3159         ret = madera_hw_params_rate(substream, params, dai);
3160         if (ret != 0)
3161                 goto restore_aif;
3162 
3163         if (reconfig) {
3164                 regmap_update_bits(madera->regmap,
3165                                    base + MADERA_AIF_BCLK_CTRL,
3166                                    MADERA_AIF1_BCLK_FREQ_MASK, bclk);
3167                 regmap_update_bits(madera->regmap,
3168                                    base + MADERA_AIF_RX_BCLK_RATE,
3169                                    MADERA_AIF1RX_BCPF_MASK, lrclk);
3170                 regmap_update_bits(madera->regmap,
3171                                    base + MADERA_AIF_FRAME_CTRL_1,
3172                                    MADERA_AIF1TX_WL_MASK |
3173                                    MADERA_AIF1TX_SLOT_LEN_MASK, frame);
3174                 regmap_update_bits(madera->regmap,
3175                                    base + MADERA_AIF_FRAME_CTRL_2,
3176                                    MADERA_AIF1RX_WL_MASK |
3177                                    MADERA_AIF1RX_SLOT_LEN_MASK, frame);
3178         }
3179 
3180 restore_aif:
3181         if (reconfig) {
3182                 /* Restore AIF TX/RX state */
3183                 regmap_update_bits(madera->regmap,
3184                                    base + MADERA_AIF_TX_ENABLES,
3185                                    0xff, aif_tx_state);
3186                 regmap_update_bits(madera->regmap,
3187                                    base + MADERA_AIF_RX_ENABLES,
3188                                    0xff, aif_rx_state);
3189         }
3190 
3191         return ret;
3192 }
3193 
3194 static int madera_is_syncclk(int clk_id)
3195 {
3196         switch (clk_id) {
3197         case MADERA_CLK_SYSCLK_1:
3198         case MADERA_CLK_SYSCLK_2:
3199         case MADERA_CLK_SYSCLK_3:
3200                 return 1;
3201         case MADERA_CLK_ASYNCCLK_1:
3202         case MADERA_CLK_ASYNCCLK_2:
3203                 return 0;
3204         default:
3205                 return -EINVAL;
3206         }
3207 }
3208 
3209 static int madera_dai_set_sysclk(struct snd_soc_dai *dai,
3210                                  int clk_id, unsigned int freq, int dir)
3211 {
3212         struct snd_soc_component *component = dai->component;
3213         struct snd_soc_dapm_context *dapm =
3214                 snd_soc_component_get_dapm(component);
3215         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3216         struct madera_dai_priv *dai_priv = &priv->dai[dai->id - 1];
3217         struct snd_soc_dapm_route routes[2];
3218         int is_sync;
3219 
3220         is_sync = madera_is_syncclk(clk_id);
3221         if (is_sync < 0) {
3222                 dev_err(component->dev, "Illegal DAI clock id %d\n", clk_id);
3223                 return is_sync;
3224         }
3225 
3226         if (is_sync == madera_is_syncclk(dai_priv->clk))
3227                 return 0;
3228 
3229         if (dai->active) {
3230                 dev_err(component->dev, "Can't change clock on active DAI %d\n",
3231                         dai->id);
3232                 return -EBUSY;
3233         }
3234 
3235         dev_dbg(component->dev, "Setting AIF%d to %s\n", dai->id,
3236                 is_sync ? "SYSCLK" : "ASYNCCLK");
3237 
3238         /*
3239          * A connection to SYSCLK is always required, we only add and remove
3240          * a connection to ASYNCCLK
3241          */
3242         memset(&routes, 0, sizeof(routes));
3243         routes[0].sink = dai->driver->capture.stream_name;
3244         routes[1].sink = dai->driver->playback.stream_name;
3245         routes[0].source = "ASYNCCLK";
3246         routes[1].source = "ASYNCCLK";
3247 
3248         if (is_sync)
3249                 snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
3250         else
3251                 snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
3252 
3253         dai_priv->clk = clk_id;
3254 
3255         return snd_soc_dapm_sync(dapm);
3256 }
3257 
3258 static int madera_set_tristate(struct snd_soc_dai *dai, int tristate)
3259 {
3260         struct snd_soc_component *component = dai->component;
3261         int base = dai->driver->base;
3262         unsigned int reg;
3263         int ret;
3264 
3265         if (tristate)
3266                 reg = MADERA_AIF1_TRI;
3267         else
3268                 reg = 0;
3269 
3270         ret = snd_soc_component_update_bits(component,
3271                                             base + MADERA_AIF_RATE_CTRL,
3272                                             MADERA_AIF1_TRI, reg);
3273         if (ret < 0)
3274                 return ret;
3275         else
3276                 return 0;
3277 }
3278 
3279 static void madera_set_channels_to_mask(struct snd_soc_dai *dai,
3280                                         unsigned int base,
3281                                         int channels, unsigned int mask)
3282 {
3283         struct snd_soc_component *component = dai->component;
3284         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3285         struct madera *madera = priv->madera;
3286         int slot, i;
3287 
3288         for (i = 0; i < channels; ++i) {
3289                 slot = ffs(mask) - 1;
3290                 if (slot < 0)
3291                         return;
3292 
3293                 regmap_write(madera->regmap, base + i, slot);
3294 
3295                 mask &= ~(1 << slot);
3296         }
3297 
3298         if (mask)
3299                 madera_aif_warn(dai, "Too many channels in TDM mask\n");
3300 }
3301 
3302 static int madera_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
3303                                unsigned int rx_mask, int slots, int slot_width)
3304 {
3305         struct snd_soc_component *component = dai->component;
3306         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
3307         int base = dai->driver->base;
3308         int rx_max_chan = dai->driver->playback.channels_max;
3309         int tx_max_chan = dai->driver->capture.channels_max;
3310 
3311         /* Only support TDM for the physical AIFs */
3312         if (dai->id > MADERA_MAX_AIF)
3313                 return -ENOTSUPP;
3314 
3315         if (slots == 0) {
3316                 tx_mask = (1 << tx_max_chan) - 1;
3317                 rx_mask = (1 << rx_max_chan) - 1;
3318         }
3319 
3320         madera_set_channels_to_mask(dai, base + MADERA_AIF_FRAME_CTRL_3,
3321                                     tx_max_chan, tx_mask);
3322         madera_set_channels_to_mask(dai, base + MADERA_AIF_FRAME_CTRL_11,
3323                                     rx_max_chan, rx_mask);
3324 
3325         priv->tdm_width[dai->id - 1] = slot_width;
3326         priv->tdm_slots[dai->id - 1] = slots;
3327 
3328         return 0;
3329 }
3330 
3331 const struct snd_soc_dai_ops madera_dai_ops = {
3332         .startup = &madera_startup,
3333         .set_fmt = &madera_set_fmt,
3334         .set_tdm_slot = &madera_set_tdm_slot,
3335         .hw_params = &madera_hw_params,
3336         .set_sysclk = &madera_dai_set_sysclk,
3337         .set_tristate = &madera_set_tristate,
3338 };
3339 EXPORT_SYMBOL_GPL(madera_dai_ops);
3340 
3341 const struct snd_soc_dai_ops madera_simple_dai_ops = {
3342         .startup = &madera_startup,
3343         .hw_params = &madera_hw_params_rate,
3344         .set_sysclk = &madera_dai_set_sysclk,
3345 };
3346 EXPORT_SYMBOL_GPL(madera_simple_dai_ops);
3347 
3348 int madera_init_dai(struct madera_priv *priv, int id)
3349 {
3350         struct madera_dai_priv *dai_priv = &priv->dai[id];
3351 
3352         dai_priv->clk = MADERA_CLK_SYSCLK_1;
3353         dai_priv->constraint = madera_constraint;
3354 
3355         return 0;
3356 }
3357 EXPORT_SYMBOL_GPL(madera_init_dai);
3358 
3359 static const struct {
3360         unsigned int min;
3361         unsigned int max;
3362         u16 fratio;
3363         int ratio;
3364 } fll_sync_fratios[] = {
3365         {       0,    64000, 4, 16 },
3366         {   64000,   128000, 3,  8 },
3367         {  128000,   256000, 2,  4 },
3368         {  256000,  1000000, 1,  2 },
3369         { 1000000, 13500000, 0,  1 },
3370 };
3371 
3372 static const unsigned int pseudo_fref_max[MADERA_FLL_MAX_FRATIO] = {
3373         13500000,
3374          6144000,
3375          6144000,
3376          3072000,
3377          3072000,
3378          2822400,
3379          2822400,
3380          1536000,
3381          1536000,
3382          1536000,
3383          1536000,
3384          1536000,
3385          1536000,
3386          1536000,
3387          1536000,
3388           768000,
3389 };
3390 
3391 struct madera_fll_gains {
3392         unsigned int min;
3393         unsigned int max;
3394         int gain;               /* main gain */
3395         int alt_gain;           /* alternate integer gain */
3396 };
3397 
3398 static const struct madera_fll_gains madera_fll_sync_gains[] = {
3399         {       0,   256000, 0, -1 },
3400         {  256000,  1000000, 2, -1 },
3401         { 1000000, 13500000, 4, -1 },
3402 };
3403 
3404 static const struct madera_fll_gains madera_fll_main_gains[] = {
3405         {       0,   100000, 0, 2 },
3406         {  100000,   375000, 2, 2 },
3407         {  375000,   768000, 3, 2 },
3408         {  768001,  1500000, 3, 3 },
3409         { 1500000,  6000000, 4, 3 },
3410         { 6000000, 13500000, 5, 3 },
3411 };
3412 
3413 static int madera_find_sync_fratio(unsigned int fref, int *fratio)
3414 {
3415         int i;
3416 
3417         for (i = 0; i < ARRAY_SIZE(fll_sync_fratios); i++) {
3418                 if (fll_sync_fratios[i].min <= fref &&
3419                     fref <= fll_sync_fratios[i].max) {
3420                         if (fratio)
3421                                 *fratio = fll_sync_fratios[i].fratio;
3422 
3423                         return fll_sync_fratios[i].ratio;
3424                 }
3425         }
3426 
3427         return -EINVAL;
3428 }
3429 
3430 static int madera_find_main_fratio(unsigned int fref, unsigned int fout,
3431                                    int *fratio)
3432 {
3433         int ratio = 1;
3434 
3435         while ((fout / (ratio * fref)) > MADERA_FLL_MAX_N)
3436                 ratio++;
3437 
3438         if (fratio)
3439                 *fratio = ratio - 1;
3440 
3441         return ratio;
3442 }
3443 
3444 static int madera_find_fratio(struct madera_fll *fll, unsigned int fref,
3445                               bool sync, int *fratio)
3446 {
3447         switch (fll->madera->type) {
3448         case CS47L35:
3449                 switch (fll->madera->rev) {
3450                 case 0:
3451                         /* rev A0 uses sync calculation for both loops */
3452                         return madera_find_sync_fratio(fref, fratio);
3453                 default:
3454                         if (sync)
3455                                 return madera_find_sync_fratio(fref, fratio);
3456                         else
3457                                 return madera_find_main_fratio(fref,
3458                                                                fll->fout,
3459                                                                fratio);
3460                 }
3461                 break;
3462         case CS47L85:
3463         case WM1840:
3464                 /* these use the same calculation for main and sync loops */
3465                 return madera_find_sync_fratio(fref, fratio);
3466         default:
3467                 if (sync)
3468                         return madera_find_sync_fratio(fref, fratio);
3469                 else
3470                         return madera_find_main_fratio(fref, fll->fout, fratio);
3471         }
3472 }
3473 
3474 static int madera_calc_fratio(struct madera_fll *fll,
3475                               struct madera_fll_cfg *cfg,
3476                               unsigned int fref, bool sync)
3477 {
3478         int init_ratio, ratio;
3479         int refdiv, div;
3480 
3481         /* fref must be <=13.5MHz, find initial refdiv */
3482         div = 1;
3483         cfg->refdiv = 0;
3484         while (fref > MADERA_FLL_MAX_FREF) {
3485                 div *= 2;
3486                 fref /= 2;
3487                 cfg->refdiv++;
3488 
3489                 if (div > MADERA_FLL_MAX_REFDIV)
3490                         return -EINVAL;
3491         }
3492 
3493         /* Find an appropriate FLL_FRATIO */
3494         init_ratio = madera_find_fratio(fll, fref, sync, &cfg->fratio);
3495         if (init_ratio < 0) {
3496                 madera_fll_err(fll, "Unable to find FRATIO for fref=%uHz\n",
3497                                fref);
3498                 return init_ratio;
3499         }
3500 
3501         if (!sync)
3502                 cfg->fratio = init_ratio - 1;
3503 
3504         switch (fll->madera->type) {
3505         case CS47L35:
3506                 switch (fll->madera->rev) {
3507                 case 0:
3508                         if (sync)
3509                                 return init_ratio;
3510                         break;
3511                 default:
3512                         return init_ratio;
3513                 }
3514                 break;
3515         case CS47L85:
3516         case WM1840:
3517                 if (sync)
3518                         return init_ratio;
3519                 break;
3520         default:
3521                 return init_ratio;
3522         }
3523 
3524         /*
3525          * For CS47L35 rev A0, CS47L85 and WM1840 adjust FRATIO/refdiv to avoid
3526          * integer mode if possible
3527          */
3528         refdiv = cfg->refdiv;
3529 
3530         while (div <= MADERA_FLL_MAX_REFDIV) {
3531                 /*
3532                  * start from init_ratio because this may already give a
3533                  * fractional N.K
3534                  */
3535                 for (ratio = init_ratio; ratio > 0; ratio--) {
3536                         if (fll->fout % (ratio * fref)) {
3537                                 cfg->refdiv = refdiv;
3538                                 cfg->fratio = ratio - 1;
3539                                 return ratio;
3540                         }
3541                 }
3542 
3543                 for (ratio = init_ratio + 1; ratio <= MADERA_FLL_MAX_FRATIO;
3544                      ratio++) {
3545                         if ((MADERA_FLL_VCO_CORNER / 2) /
3546                             (MADERA_FLL_VCO_MULT * ratio) < fref)
3547                                 break;
3548 
3549                         if (fref > pseudo_fref_max[ratio - 1])
3550                                 break;
3551 
3552                         if (fll->fout % (ratio * fref)) {
3553                                 cfg->refdiv = refdiv;
3554                                 cfg->fratio = ratio - 1;
3555                                 return ratio;
3556                         }
3557                 }
3558 
3559                 div *= 2;
3560                 fref /= 2;
3561                 refdiv++;
3562                 init_ratio = madera_find_fratio(fll, fref, sync, NULL);
3563         }
3564 
3565         madera_fll_warn(fll, "Falling back to integer mode operation\n");
3566 
3567         return cfg->fratio + 1;
3568 }
3569 
3570 static int madera_find_fll_gain(struct madera_fll *fll,
3571                                 struct madera_fll_cfg *cfg,
3572                                 unsigned int fref,
3573                                 const struct madera_fll_gains *gains,
3574                                 int n_gains)
3575 {
3576         int i;
3577 
3578         for (i = 0; i < n_gains; i++) {
3579                 if (gains[i].min <= fref && fref <= gains[i].max) {
3580                         cfg->gain = gains[i].gain;
3581                         cfg->alt_gain = gains[i].alt_gain;
3582                         return 0;
3583                 }
3584         }
3585 
3586         madera_fll_err(fll, "Unable to find gain for fref=%uHz\n", fref);
3587 
3588         return -EINVAL;
3589 }
3590 
3591 static int madera_calc_fll(struct madera_fll *fll,
3592                            struct madera_fll_cfg *cfg,
3593                            unsigned int fref, bool sync)
3594 {
3595         unsigned int gcd_fll;
3596         const struct madera_fll_gains *gains;
3597         int n_gains;
3598         int ratio, ret;
3599 
3600         madera_fll_dbg(fll, "fref=%u Fout=%u fvco=%u\n",
3601                        fref, fll->fout, fll->fout * MADERA_FLL_VCO_MULT);
3602 
3603         /* Find an appropriate FLL_FRATIO and refdiv */
3604         ratio = madera_calc_fratio(fll, cfg, fref, sync);
3605         if (ratio < 0)
3606                 return ratio;
3607 
3608         /* Apply the division for our remaining calculations */
3609         fref = fref / (1 << cfg->refdiv);
3610 
3611         cfg->n = fll->fout / (ratio * fref);
3612 
3613         if (fll->fout % (ratio * fref)) {
3614                 gcd_fll = gcd(fll->fout, ratio * fref);
3615                 madera_fll_dbg(fll, "GCD=%u\n", gcd_fll);
3616 
3617                 cfg->theta = (fll->fout - (cfg->n * ratio * fref))
3618                         / gcd_fll;
3619                 cfg->lambda = (ratio * fref) / gcd_fll;
3620         } else {
3621                 cfg->theta = 0;
3622                 cfg->lambda = 0;
3623         }
3624 
3625         /*
3626          * Round down to 16bit range with cost of accuracy lost.
3627          * Denominator must be bigger than numerator so we only
3628          * take care of it.
3629          */
3630         while (cfg->lambda >= (1 << 16)) {
3631                 cfg->theta >>= 1;
3632                 cfg->lambda >>= 1;
3633         }
3634 
3635         switch (fll->madera->type) {
3636         case CS47L35:
3637                 switch (fll->madera->rev) {
3638                 case 0:
3639                         /* Rev A0 uses the sync gains for both loops */
3640                         gains = madera_fll_sync_gains;
3641                         n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3642                         break;
3643                 default:
3644                         if (sync) {
3645                                 gains = madera_fll_sync_gains;
3646                                 n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3647                         } else {
3648                                 gains = madera_fll_main_gains;
3649                                 n_gains = ARRAY_SIZE(madera_fll_main_gains);
3650                         }
3651                         break;
3652                 }
3653                 break;
3654         case CS47L85:
3655         case WM1840:
3656                 /* These use the sync gains for both loops */
3657                 gains = madera_fll_sync_gains;
3658                 n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3659                 break;
3660         default:
3661                 if (sync) {
3662                         gains = madera_fll_sync_gains;
3663                         n_gains = ARRAY_SIZE(madera_fll_sync_gains);
3664                 } else {
3665                         gains = madera_fll_main_gains;
3666                         n_gains = ARRAY_SIZE(madera_fll_main_gains);
3667                 }
3668                 break;
3669         }
3670 
3671         ret = madera_find_fll_gain(fll, cfg, fref, gains, n_gains);
3672         if (ret)
3673                 return ret;
3674 
3675         madera_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n",
3676                        cfg->n, cfg->theta, cfg->lambda);
3677         madera_fll_dbg(fll, "FRATIO=0x%x(%d) REFCLK_DIV=0x%x(%d)\n",
3678                        cfg->fratio, ratio, cfg->refdiv, 1 << cfg->refdiv);
3679         madera_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain);
3680 
3681         return 0;
3682 }
3683 
3684 static bool madera_write_fll(struct madera *madera, unsigned int base,
3685                              struct madera_fll_cfg *cfg, int source,
3686                              bool sync, int gain)
3687 {
3688         bool change, fll_change;
3689 
3690         fll_change = false;
3691         regmap_update_bits_check(madera->regmap,
3692                                  base + MADERA_FLL_CONTROL_3_OFFS,
3693                                  MADERA_FLL1_THETA_MASK,
3694                                  cfg->theta, &change);
3695         fll_change |= change;
3696         regmap_update_bits_check(madera->regmap,
3697                                  base + MADERA_FLL_CONTROL_4_OFFS,
3698                                  MADERA_FLL1_LAMBDA_MASK,
3699                                  cfg->lambda, &change);
3700         fll_change |= change;
3701         regmap_update_bits_check(madera->regmap,
3702                                  base + MADERA_FLL_CONTROL_5_OFFS,
3703                                  MADERA_FLL1_FRATIO_MASK,
3704                                  cfg->fratio << MADERA_FLL1_FRATIO_SHIFT,
3705                                  &change);
3706         fll_change |= change;
3707         regmap_update_bits_check(madera->regmap,
3708                                  base + MADERA_FLL_CONTROL_6_OFFS,
3709                                  MADERA_FLL1_REFCLK_DIV_MASK |
3710                                  MADERA_FLL1_REFCLK_SRC_MASK,
3711                                  cfg->refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT |
3712                                  source << MADERA_FLL1_REFCLK_SRC_SHIFT,
3713                                  &change);
3714         fll_change |= change;
3715 
3716         if (sync) {
3717                 regmap_update_bits_check(madera->regmap,
3718                                          base + MADERA_FLL_SYNCHRONISER_7_OFFS,
3719                                          MADERA_FLL1_GAIN_MASK,
3720                                          gain << MADERA_FLL1_GAIN_SHIFT,
3721                                          &change);
3722                 fll_change |= change;
3723         } else {
3724                 regmap_update_bits_check(madera->regmap,
3725                                          base + MADERA_FLL_CONTROL_7_OFFS,
3726                                          MADERA_FLL1_GAIN_MASK,
3727                                          gain << MADERA_FLL1_GAIN_SHIFT,
3728                                          &change);
3729                 fll_change |= change;
3730         }
3731 
3732         regmap_update_bits_check(madera->regmap,
3733                                  base + MADERA_FLL_CONTROL_2_OFFS,
3734                                  MADERA_FLL1_CTRL_UPD | MADERA_FLL1_N_MASK,
3735                                  MADERA_FLL1_CTRL_UPD | cfg->n, &change);
3736         fll_change |= change;
3737 
3738         return fll_change;
3739 }
3740 
3741 static int madera_is_enabled_fll(struct madera_fll *fll, int base)
3742 {
3743         struct madera *madera = fll->madera;
3744         unsigned int reg;
3745         int ret;
3746 
3747         ret = regmap_read(madera->regmap,
3748                           base + MADERA_FLL_CONTROL_1_OFFS, &reg);
3749         if (ret != 0) {
3750                 madera_fll_err(fll, "Failed to read current state: %d\n", ret);
3751                 return ret;
3752         }
3753 
3754         return reg & MADERA_FLL1_ENA;
3755 }
3756 
3757 static int madera_wait_for_fll(struct madera_fll *fll, bool requested)
3758 {
3759         struct madera *madera = fll->madera;
3760         unsigned int val = 0;
3761         bool status;
3762         int i;
3763 
3764         madera_fll_dbg(fll, "Waiting for FLL...\n");
3765 
3766         for (i = 0; i < 30; i++) {
3767                 regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_2, &val);
3768                 status = val & (MADERA_FLL1_LOCK_STS1 << (fll->id - 1));
3769                 if (status == requested)
3770                         return 0;
3771 
3772                 switch (i) {
3773                 case 0 ... 5:
3774                         usleep_range(75, 125);
3775                         break;
3776                 case 11 ... 20:
3777                         usleep_range(750, 1250);
3778                         break;
3779                 default:
3780                         msleep(20);
3781                         break;
3782                 }
3783         }
3784 
3785         madera_fll_warn(fll, "Timed out waiting for lock\n");
3786 
3787         return -ETIMEDOUT;
3788 }
3789 
3790 static bool madera_set_fll_phase_integrator(struct madera_fll *fll,
3791                                             struct madera_fll_cfg *ref_cfg,
3792                                             bool sync)
3793 {
3794         unsigned int val;
3795         bool reg_change;
3796 
3797         if (!sync && ref_cfg->theta == 0)
3798                 val = (1 << MADERA_FLL1_PHASE_ENA_SHIFT) |
3799                       (2 << MADERA_FLL1_PHASE_GAIN_SHIFT);
3800         else
3801                 val = 2 << MADERA_FLL1_PHASE_GAIN_SHIFT;
3802 
3803         regmap_update_bits_check(fll->madera->regmap,
3804                                  fll->base + MADERA_FLL_EFS_2_OFFS,
3805                                  MADERA_FLL1_PHASE_ENA_MASK |
3806                                  MADERA_FLL1_PHASE_GAIN_MASK,
3807                                  val, &reg_change);
3808 
3809         return reg_change;
3810 }
3811 
3812 static void madera_disable_fll(struct madera_fll *fll)
3813 {
3814         struct madera *madera = fll->madera;
3815         unsigned int sync_base;
3816         bool change;
3817 
3818         switch (madera->type) {
3819         case CS47L35:
3820                 sync_base = fll->base + CS47L35_FLL_SYNCHRONISER_OFFS;
3821                 break;
3822         default:
3823                 sync_base = fll->base + MADERA_FLL_SYNCHRONISER_OFFS;
3824                 break;
3825         }
3826 
3827         madera_fll_dbg(fll, "Disabling FLL\n");
3828 
3829         regmap_update_bits(madera->regmap,
3830                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
3831                            MADERA_FLL1_FREERUN, MADERA_FLL1_FREERUN);
3832         regmap_update_bits_check(madera->regmap,
3833                                  fll->base + MADERA_FLL_CONTROL_1_OFFS,
3834                                  MADERA_FLL1_ENA, 0, &change);
3835         regmap_update_bits(madera->regmap,
3836                            sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
3837                            MADERA_FLL1_SYNC_ENA, 0);
3838         regmap_update_bits(madera->regmap,
3839                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
3840                            MADERA_FLL1_FREERUN, 0);
3841 
3842         madera_wait_for_fll(fll, false);
3843 
3844         if (change)
3845                 pm_runtime_put_autosuspend(madera->dev);
3846 }
3847 
3848 static int madera_enable_fll(struct madera_fll *fll)
3849 {
3850         struct madera *madera = fll->madera;
3851         bool have_sync = false;
3852         int already_enabled = madera_is_enabled_fll(fll, fll->base);
3853         int sync_enabled;
3854         struct madera_fll_cfg cfg;
3855         unsigned int sync_base;
3856         int gain, ret;
3857         bool fll_change = false;
3858 
3859         if (already_enabled < 0)
3860                 return already_enabled; /* error getting current state */
3861 
3862         if (fll->ref_src < 0 || fll->ref_freq == 0) {
3863                 madera_fll_err(fll, "No REFCLK\n");
3864                 ret = -EINVAL;
3865                 goto err;
3866         }
3867 
3868         madera_fll_dbg(fll, "Enabling FLL, initially %s\n",
3869                        already_enabled ? "enabled" : "disabled");
3870 
3871         if (fll->fout < MADERA_FLL_MIN_FOUT ||
3872             fll->fout > MADERA_FLL_MAX_FOUT) {
3873                 madera_fll_err(fll, "invalid fout %uHz\n", fll->fout);
3874                 ret = -EINVAL;
3875                 goto err;
3876         }
3877 
3878         switch (madera->type) {
3879         case CS47L35:
3880                 sync_base = fll->base + CS47L35_FLL_SYNCHRONISER_OFFS;
3881                 break;
3882         default:
3883                 sync_base = fll->base + MADERA_FLL_SYNCHRONISER_OFFS;
3884                 break;
3885         }
3886 
3887         sync_enabled = madera_is_enabled_fll(fll, sync_base);
3888         if (sync_enabled < 0)
3889                 return sync_enabled;
3890 
3891         if (already_enabled) {
3892                 /* Facilitate smooth refclk across the transition */
3893                 regmap_update_bits(fll->madera->regmap,
3894                                    fll->base + MADERA_FLL_CONTROL_1_OFFS,
3895                                    MADERA_FLL1_FREERUN,
3896                                    MADERA_FLL1_FREERUN);
3897                 udelay(32);
3898                 regmap_update_bits(fll->madera->regmap,
3899                                    fll->base + MADERA_FLL_CONTROL_7_OFFS,
3900                                    MADERA_FLL1_GAIN_MASK, 0);
3901         }
3902 
3903         /* Apply SYNCCLK setting */
3904         if (fll->sync_src >= 0) {
3905                 ret = madera_calc_fll(fll, &cfg, fll->sync_freq, true);
3906                 if (ret < 0)
3907                         goto err;
3908 
3909                 fll_change |= madera_write_fll(madera, sync_base,
3910                                                &cfg, fll->sync_src,
3911                                                true, cfg.gain);
3912                 have_sync = true;
3913         }
3914 
3915         if (already_enabled && !!sync_enabled != have_sync)
3916                 madera_fll_warn(fll, "Synchroniser changed on active FLL\n");
3917 
3918         /* Apply REFCLK setting */
3919         ret = madera_calc_fll(fll, &cfg, fll->ref_freq, false);
3920         if (ret < 0)
3921                 goto err;
3922 
3923         /* Ref path hardcodes lambda to 65536 when sync is on */
3924         if (have_sync && cfg.lambda)
3925                 cfg.theta = (cfg.theta * (1 << 16)) / cfg.lambda;
3926 
3927         switch (fll->madera->type) {
3928         case CS47L35:
3929                 switch (fll->madera->rev) {
3930                 case 0:
3931                         gain = cfg.gain;
3932                         break;
3933                 default:
3934                         fll_change |=
3935                                 madera_set_fll_phase_integrator(fll, &cfg,
3936                                                                 have_sync);
3937                         if (!have_sync && cfg.theta == 0)
3938                                 gain = cfg.alt_gain;
3939                         else
3940                                 gain = cfg.gain;
3941                         break;
3942                 }
3943                 break;
3944         case CS47L85:
3945         case WM1840:
3946                 gain = cfg.gain;
3947                 break;
3948         default:
3949                 fll_change |= madera_set_fll_phase_integrator(fll, &cfg,
3950                                                               have_sync);
3951                 if (!have_sync && cfg.theta == 0)
3952                         gain = cfg.alt_gain;
3953                 else
3954                         gain = cfg.gain;
3955                 break;
3956         }
3957 
3958         fll_change |= madera_write_fll(madera, fll->base,
3959                                        &cfg, fll->ref_src,
3960                                        false, gain);
3961 
3962         /*
3963          * Increase the bandwidth if we're not using a low frequency
3964          * sync source.
3965          */
3966         if (have_sync && fll->sync_freq > 100000)
3967                 regmap_update_bits(madera->regmap,
3968                                    sync_base + MADERA_FLL_SYNCHRONISER_7_OFFS,
3969                                    MADERA_FLL1_SYNC_DFSAT_MASK, 0);
3970         else
3971                 regmap_update_bits(madera->regmap,
3972                                    sync_base + MADERA_FLL_SYNCHRONISER_7_OFFS,
3973                                    MADERA_FLL1_SYNC_DFSAT_MASK,
3974                                    MADERA_FLL1_SYNC_DFSAT);
3975 
3976         if (!already_enabled)
3977                 pm_runtime_get_sync(madera->dev);
3978 
3979         if (have_sync)
3980                 regmap_update_bits(madera->regmap,
3981                                    sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
3982                                    MADERA_FLL1_SYNC_ENA,
3983                                    MADERA_FLL1_SYNC_ENA);
3984         regmap_update_bits(madera->regmap,
3985                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
3986                            MADERA_FLL1_ENA, MADERA_FLL1_ENA);
3987 
3988         if (already_enabled)
3989                 regmap_update_bits(madera->regmap,
3990                                    fll->base + MADERA_FLL_CONTROL_1_OFFS,
3991                                    MADERA_FLL1_FREERUN, 0);
3992 
3993         if (fll_change || !already_enabled)
3994                 madera_wait_for_fll(fll, true);
3995 
3996         return 0;
3997 
3998 err:
3999          /* In case of error don't leave the FLL running with an old config */
4000         madera_disable_fll(fll);
4001 
4002         return ret;
4003 }
4004 
4005 static int madera_apply_fll(struct madera_fll *fll)
4006 {
4007         if (fll->fout) {
4008                 return madera_enable_fll(fll);
4009         } else {
4010                 madera_disable_fll(fll);
4011                 return 0;
4012         }
4013 }
4014 
4015 int madera_set_fll_syncclk(struct madera_fll *fll, int source,
4016                            unsigned int fref, unsigned int fout)
4017 {
4018         /*
4019          * fout is ignored, since the synchronizer is an optional extra
4020          * constraint on the Fout generated from REFCLK, so the Fout is
4021          * set when configuring REFCLK
4022          */
4023 
4024         if (fll->sync_src == source && fll->sync_freq == fref)
4025                 return 0;
4026 
4027         fll->sync_src = source;
4028         fll->sync_freq = fref;
4029 
4030         return madera_apply_fll(fll);
4031 }
4032 EXPORT_SYMBOL_GPL(madera_set_fll_syncclk);
4033 
4034 int madera_set_fll_refclk(struct madera_fll *fll, int source,
4035                           unsigned int fref, unsigned int fout)
4036 {
4037         int ret;
4038 
4039         if (fll->ref_src == source &&
4040             fll->ref_freq == fref && fll->fout == fout)
4041                 return 0;
4042 
4043         /*
4044          * Changes of fout on an enabled FLL aren't allowed except when
4045          * setting fout==0 to disable the FLL
4046          */
4047         if (fout && fout != fll->fout) {
4048                 ret = madera_is_enabled_fll(fll, fll->base);
4049                 if (ret < 0)
4050                         return ret;
4051 
4052                 if (ret) {
4053                         madera_fll_err(fll, "Can't change Fout on active FLL\n");
4054                         return -EBUSY;
4055                 }
4056         }
4057 
4058         fll->ref_src = source;
4059         fll->ref_freq = fref;
4060         fll->fout = fout;
4061 
4062         return madera_apply_fll(fll);
4063 }
4064 EXPORT_SYMBOL_GPL(madera_set_fll_refclk);
4065 
4066 int madera_init_fll(struct madera *madera, int id, int base,
4067                     struct madera_fll *fll)
4068 {
4069         fll->id = id;
4070         fll->base = base;
4071         fll->madera = madera;
4072         fll->ref_src = MADERA_FLL_SRC_NONE;
4073         fll->sync_src = MADERA_FLL_SRC_NONE;
4074 
4075         regmap_update_bits(madera->regmap,
4076                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
4077                            MADERA_FLL1_FREERUN, 0);
4078 
4079         return 0;
4080 }
4081 EXPORT_SYMBOL_GPL(madera_init_fll);
4082 
4083 static const struct reg_sequence madera_fll_ao_32K_49M_patch[] = {
4084         { MADERA_FLLAO_CONTROL_2,  0x02EE },
4085         { MADERA_FLLAO_CONTROL_3,  0x0000 },
4086         { MADERA_FLLAO_CONTROL_4,  0x0001 },
4087         { MADERA_FLLAO_CONTROL_5,  0x0002 },
4088         { MADERA_FLLAO_CONTROL_6,  0x8001 },
4089         { MADERA_FLLAO_CONTROL_7,  0x0004 },
4090         { MADERA_FLLAO_CONTROL_8,  0x0077 },
4091         { MADERA_FLLAO_CONTROL_10, 0x06D8 },
4092         { MADERA_FLLAO_CONTROL_11, 0x0085 },
4093         { MADERA_FLLAO_CONTROL_2,  0x82EE },
4094 };
4095 
4096 static const struct reg_sequence madera_fll_ao_32K_45M_patch[] = {
4097         { MADERA_FLLAO_CONTROL_2,  0x02B1 },
4098         { MADERA_FLLAO_CONTROL_3,  0x0001 },
4099         { MADERA_FLLAO_CONTROL_4,  0x0010 },
4100         { MADERA_FLLAO_CONTROL_5,  0x0002 },
4101         { MADERA_FLLAO_CONTROL_6,  0x8001 },
4102         { MADERA_FLLAO_CONTROL_7,  0x0004 },
4103         { MADERA_FLLAO_CONTROL_8,  0x0077 },
4104         { MADERA_FLLAO_CONTROL_10, 0x06D8 },
4105         { MADERA_FLLAO_CONTROL_11, 0x0005 },
4106         { MADERA_FLLAO_CONTROL_2,  0x82B1 },
4107 };
4108 
4109 struct madera_fllao_patch {
4110         unsigned int fin;
4111         unsigned int fout;
4112         const struct reg_sequence *patch;
4113         unsigned int patch_size;
4114 };
4115 
4116 static const struct madera_fllao_patch madera_fllao_settings[] = {
4117         {
4118                 .fin = 32768,
4119                 .fout = 49152000,
4120                 .patch = madera_fll_ao_32K_49M_patch,
4121                 .patch_size = ARRAY_SIZE(madera_fll_ao_32K_49M_patch),
4122 
4123         },
4124         {
4125                 .fin = 32768,
4126                 .fout = 45158400,
4127                 .patch = madera_fll_ao_32K_45M_patch,
4128                 .patch_size = ARRAY_SIZE(madera_fll_ao_32K_45M_patch),
4129         },
4130 };
4131 
4132 static int madera_enable_fll_ao(struct madera_fll *fll,
4133                                 const struct reg_sequence *patch,
4134                                 unsigned int patch_size)
4135 {
4136         struct madera *madera = fll->madera;
4137         int already_enabled = madera_is_enabled_fll(fll, fll->base);
4138         unsigned int val;
4139         int i;
4140 
4141         if (already_enabled < 0)
4142                 return already_enabled;
4143 
4144         if (!already_enabled)
4145                 pm_runtime_get_sync(madera->dev);
4146 
4147         madera_fll_dbg(fll, "Enabling FLL_AO, initially %s\n",
4148                        already_enabled ? "enabled" : "disabled");
4149 
4150         /* FLL_AO_HOLD must be set before configuring any registers */
4151         regmap_update_bits(fll->madera->regmap,
4152                            fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4153                            MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD);
4154 
4155         for (i = 0; i < patch_size; i++) {
4156                 val = patch[i].def;
4157 
4158                 /* modify the patch to apply fll->ref_src as input clock */
4159                 if (patch[i].reg == MADERA_FLLAO_CONTROL_6) {
4160                         val &= ~MADERA_FLL_AO_REFCLK_SRC_MASK;
4161                         val |= (fll->ref_src << MADERA_FLL_AO_REFCLK_SRC_SHIFT)
4162                                 & MADERA_FLL_AO_REFCLK_SRC_MASK;
4163                 }
4164 
4165                 regmap_write(madera->regmap, patch[i].reg, val);
4166         }
4167 
4168         regmap_update_bits(madera->regmap,
4169                            fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4170                            MADERA_FLL_AO_ENA, MADERA_FLL_AO_ENA);
4171 
4172         /* Release the hold so that fll_ao locks to external frequency */
4173         regmap_update_bits(madera->regmap,
4174                            fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4175                            MADERA_FLL_AO_HOLD, 0);
4176 
4177         if (!already_enabled)
4178                 madera_wait_for_fll(fll, true);
4179 
4180         return 0;
4181 }
4182 
4183 static int madera_disable_fll_ao(struct madera_fll *fll)
4184 {
4185         struct madera *madera = fll->madera;
4186         bool change;
4187 
4188         madera_fll_dbg(fll, "Disabling FLL_AO\n");
4189 
4190         regmap_update_bits(madera->regmap,
4191                            fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4192                            MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD);
4193         regmap_update_bits_check(madera->regmap,
4194                                  fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
4195                                  MADERA_FLL_AO_ENA, 0, &change);
4196 
4197         madera_wait_for_fll(fll, false);
4198 
4199         /*
4200          * ctrl_up gates the writes to all fll_ao register, setting it to 0
4201          * here ensures that after a runtime suspend/resume cycle when one
4202          * enables the fllao then ctrl_up is the last bit that is configured
4203          * by the fllao enable code rather than the cache sync operation which
4204          * would have updated it much earlier before writing out all fllao
4205          * registers
4206          */
4207         regmap_update_bits(madera->regmap,
4208                            fll->base + MADERA_FLLAO_CONTROL_2_OFFS,
4209                            MADERA_FLL_AO_CTRL_UPD_MASK, 0);
4210 
4211         if (change)
4212                 pm_runtime_put_autosuspend(madera->dev);
4213 
4214         return 0;
4215 }
4216 
4217 int madera_set_fll_ao_refclk(struct madera_fll *fll, int source,
4218                              unsigned int fin, unsigned int fout)
4219 {
4220         int ret = 0;
4221         const struct reg_sequence *patch = NULL;
4222         int patch_size = 0;
4223         unsigned int i;
4224 
4225         if (fll->ref_src == source &&
4226             fll->ref_freq == fin && fll->fout == fout)
4227                 return 0;
4228 
4229         madera_fll_dbg(fll, "Change FLL_AO refclk to fin=%u fout=%u source=%d\n",
4230                        fin, fout, source);
4231 
4232         if (fout && (fll->ref_freq != fin || fll->fout != fout)) {
4233                 for (i = 0; i < ARRAY_SIZE(madera_fllao_settings); i++) {
4234                         if (madera_fllao_settings[i].fin == fin &&
4235                             madera_fllao_settings[i].fout == fout)
4236                                 break;
4237                 }
4238 
4239                 if (i == ARRAY_SIZE(madera_fllao_settings)) {
4240                         madera_fll_err(fll,
4241                                        "No matching configuration for FLL_AO\n");
4242                         return -EINVAL;
4243                 }
4244 
4245                 patch = madera_fllao_settings[i].patch;
4246                 patch_size = madera_fllao_settings[i].patch_size;
4247         }
4248 
4249         fll->ref_src = source;
4250         fll->ref_freq = fin;
4251         fll->fout = fout;
4252 
4253         if (fout)
4254                 ret = madera_enable_fll_ao(fll, patch, patch_size);
4255         else
4256                 madera_disable_fll_ao(fll);
4257 
4258         return ret;
4259 }
4260 EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk);
4261 
4262 static int madera_fllhj_disable(struct madera_fll *fll)
4263 {
4264         struct madera *madera = fll->madera;
4265         bool change;
4266 
4267         madera_fll_dbg(fll, "Disabling FLL\n");
4268 
4269         /* Disable lockdet, but don't set ctrl_upd update but.  This allows the
4270          * lock status bit to clear as normal, but should the FLL be enabled
4271          * again due to a control clock being required, the lock won't re-assert
4272          * as the FLL config registers are automatically applied when the FLL
4273          * enables.
4274          */
4275         regmap_update_bits(madera->regmap,
4276                            fll->base + MADERA_FLL_CONTROL_11_OFFS,
4277                            MADERA_FLL1_LOCKDET_MASK, 0);
4278         regmap_update_bits(madera->regmap,
4279                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
4280                            MADERA_FLL1_HOLD_MASK, MADERA_FLL1_HOLD_MASK);
4281         regmap_update_bits_check(madera->regmap,
4282                                  fll->base + MADERA_FLL_CONTROL_1_OFFS,
4283                                  MADERA_FLL1_ENA_MASK, 0, &change);
4284 
4285         madera_wait_for_fll(fll, false);
4286 
4287         /* ctrl_up gates the writes to all the fll's registers, setting it to 0
4288          * here ensures that after a runtime suspend/resume cycle when one
4289          * enables the fll then ctrl_up is the last bit that is configured
4290          * by the fll enable code rather than the cache sync operation which
4291          * would have updated it much earlier before writing out all fll
4292          * registers
4293          */
4294         regmap_update_bits(madera->regmap,
4295                            fll->base + MADERA_FLL_CONTROL_2_OFFS,
4296                            MADERA_FLL1_CTRL_UPD_MASK, 0);
4297 
4298         if (change)
4299                 pm_runtime_put_autosuspend(madera->dev);
4300 
4301         return 0;
4302 }
4303 
4304 static int madera_fllhj_apply(struct madera_fll *fll, int fin)
4305 {
4306         struct madera *madera = fll->madera;
4307         int refdiv, fref, fout, lockdet_thr, fbdiv, hp, fast_clk, fllgcd;
4308         bool frac = false;
4309         unsigned int fll_n, min_n, max_n, ratio, theta, lambda;
4310         unsigned int gains, val, num;
4311 
4312         madera_fll_dbg(fll, "fin=%d, fout=%d\n", fin, fll->fout);
4313 
4314         for (refdiv = 0; refdiv < 4; refdiv++)
4315                 if ((fin / (1 << refdiv)) <= MADERA_FLLHJ_MAX_THRESH)
4316                         break;
4317 
4318         fref = fin / (1 << refdiv);
4319 
4320         /* Use simple heuristic approach to find a configuration that
4321          * should work for most input clocks.
4322          */
4323         fast_clk = 0;
4324         fout = fll->fout;
4325         frac = fout % fref;
4326 
4327         if (fref < MADERA_FLLHJ_LOW_THRESH) {
4328                 lockdet_thr = 2;
4329                 gains = MADERA_FLLHJ_LOW_GAINS;
4330                 if (frac)
4331                         fbdiv = 256;
4332                 else
4333                         fbdiv = 4;
4334         } else if (fref < MADERA_FLLHJ_MID_THRESH) {
4335                 lockdet_thr = 8;
4336                 gains = MADERA_FLLHJ_MID_GAINS;
4337                 fbdiv = 1;
4338         } else {
4339                 lockdet_thr = 8;
4340                 gains = MADERA_FLLHJ_HIGH_GAINS;
4341                 fbdiv = 1;
4342                 /* For high speed input clocks, enable 300MHz fast oscillator
4343                  * when we're in fractional divider mode.
4344                  */
4345                 if (frac) {
4346                         fast_clk = 0x3;
4347                         fout = fll->fout * 6;
4348                 }
4349         }
4350         /* Use high performance mode for fractional configurations. */
4351         if (frac) {
4352                 hp = 0x3;
4353                 min_n = MADERA_FLLHJ_FRAC_MIN_N;
4354                 max_n = MADERA_FLLHJ_FRAC_MAX_N;
4355         } else {
4356                 hp = 0x0;
4357                 min_n = MADERA_FLLHJ_INT_MIN_N;
4358                 max_n = MADERA_FLLHJ_INT_MAX_N;
4359         }
4360 
4361         ratio = fout / fref;
4362 
4363         madera_fll_dbg(fll, "refdiv=%d, fref=%d, frac:%d\n",
4364                        refdiv, fref, frac);
4365 
4366         while (ratio / fbdiv < min_n) {
4367                 fbdiv /= 2;
4368                 if (fbdiv < 1) {
4369                         madera_fll_err(fll, "FBDIV (%d) must be >= 1\n", fbdiv);
4370                         return -EINVAL;
4371                 }
4372         }
4373         while (frac && (ratio / fbdiv > max_n)) {
4374                 fbdiv *= 2;
4375                 if (fbdiv >= 1024) {
4376                         madera_fll_err(fll, "FBDIV (%u) >= 1024\n", fbdiv);
4377                         return -EINVAL;
4378                 }
4379         }
4380 
4381         madera_fll_dbg(fll, "lockdet=%d, hp=0x%x, fbdiv:%d\n",
4382                        lockdet_thr, hp, fbdiv);
4383 
4384         /* Calculate N.K values */
4385         fllgcd = gcd(fout, fbdiv * fref);
4386         num = fout / fllgcd;
4387         lambda = (fref * fbdiv) / fllgcd;
4388         fll_n = num / lambda;
4389         theta = num % lambda;
4390 
4391         madera_fll_dbg(fll, "fll_n=%d, gcd=%d, theta=%d, lambda=%d\n",
4392                        fll_n, fllgcd, theta, lambda);
4393 
4394         /* Some sanity checks before any registers are written. */
4395         if (fll_n < min_n || fll_n > max_n) {
4396                 madera_fll_err(fll, "N not in valid %s mode range %d-%d: %d\n",
4397                                frac ? "fractional" : "integer", min_n, max_n,
4398                                fll_n);
4399                 return -EINVAL;
4400         }
4401         if (fbdiv < 1 || (frac && fbdiv >= 1024) || (!frac && fbdiv >= 256)) {
4402                 madera_fll_err(fll, "Invalid fbdiv for %s mode (%u)\n",
4403                                frac ? "fractional" : "integer", fbdiv);
4404                 return -EINVAL;
4405         }
4406 
4407         /* clear the ctrl_upd bit to guarantee we write to it later. */
4408         regmap_write(madera->regmap,
4409                      fll->base + MADERA_FLL_CONTROL_2_OFFS,
4410                      fll_n << MADERA_FLL1_N_SHIFT);
4411         regmap_update_bits(madera->regmap,
4412                            fll->base + MADERA_FLL_CONTROL_3_OFFS,
4413                            MADERA_FLL1_THETA_MASK,
4414                            theta << MADERA_FLL1_THETA_SHIFT);
4415         regmap_update_bits(madera->regmap,
4416                            fll->base + MADERA_FLL_CONTROL_4_OFFS,
4417                            MADERA_FLL1_LAMBDA_MASK,
4418                            lambda << MADERA_FLL1_LAMBDA_SHIFT);
4419         regmap_update_bits(madera->regmap,
4420                            fll->base + MADERA_FLL_CONTROL_5_OFFS,
4421                            MADERA_FLL1_FB_DIV_MASK,
4422                            fbdiv << MADERA_FLL1_FB_DIV_SHIFT);
4423         regmap_update_bits(madera->regmap,
4424                            fll->base + MADERA_FLL_CONTROL_6_OFFS,
4425                            MADERA_FLL1_REFCLK_DIV_MASK,
4426                            refdiv << MADERA_FLL1_REFCLK_DIV_SHIFT);
4427         regmap_update_bits(madera->regmap,
4428                            fll->base + MADERA_FLL_GAIN_OFFS,
4429                            0xffff,
4430                            gains);
4431         val = hp << MADERA_FLL1_HP_SHIFT;
4432         val |= 1 << MADERA_FLL1_PHASEDET_ENA_SHIFT;
4433         regmap_update_bits(madera->regmap,
4434                            fll->base + MADERA_FLL_CONTROL_10_OFFS,
4435                            MADERA_FLL1_HP_MASK | MADERA_FLL1_PHASEDET_ENA_MASK,
4436                            val);
4437         regmap_update_bits(madera->regmap,
4438                            fll->base + MADERA_FLL_CONTROL_11_OFFS,
4439                            MADERA_FLL1_LOCKDET_THR_MASK,
4440                            lockdet_thr << MADERA_FLL1_LOCKDET_THR_SHIFT);
4441         regmap_update_bits(madera->regmap,
4442                            fll->base + MADERA_FLL1_DIGITAL_TEST_1_OFFS,
4443                            MADERA_FLL1_SYNC_EFS_ENA_MASK |
4444                            MADERA_FLL1_CLK_VCO_FAST_SRC_MASK,
4445                            fast_clk);
4446 
4447         return 0;
4448 }
4449 
4450 static int madera_fllhj_enable(struct madera_fll *fll)
4451 {
4452         struct madera *madera = fll->madera;
4453         int already_enabled = madera_is_enabled_fll(fll, fll->base);
4454         int ret;
4455 
4456         if (already_enabled < 0)
4457                 return already_enabled;
4458 
4459         if (!already_enabled)
4460                 pm_runtime_get_sync(madera->dev);
4461 
4462         madera_fll_dbg(fll, "Enabling FLL, initially %s\n",
4463                        already_enabled ? "enabled" : "disabled");
4464 
4465         /* FLLn_HOLD must be set before configuring any registers */
4466         regmap_update_bits(fll->madera->regmap,
4467                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
4468                            MADERA_FLL1_HOLD_MASK,
4469                            MADERA_FLL1_HOLD_MASK);
4470 
4471         /* Apply refclk */
4472         ret = madera_fllhj_apply(fll, fll->ref_freq);
4473         if (ret) {
4474                 madera_fll_err(fll, "Failed to set FLL: %d\n", ret);
4475                 goto out;
4476         }
4477         regmap_update_bits(madera->regmap,
4478                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
4479                            CS47L92_FLL1_REFCLK_SRC_MASK,
4480                            fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT);
4481 
4482         regmap_update_bits(madera->regmap,
4483                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
4484                            MADERA_FLL1_ENA_MASK,
4485                            MADERA_FLL1_ENA_MASK);
4486 
4487 out:
4488         regmap_update_bits(madera->regmap,
4489                            fll->base + MADERA_FLL_CONTROL_11_OFFS,
4490                            MADERA_FLL1_LOCKDET_MASK,
4491                            MADERA_FLL1_LOCKDET_MASK);
4492 
4493         regmap_update_bits(madera->regmap,
4494                            fll->base + MADERA_FLL_CONTROL_2_OFFS,
4495                            MADERA_FLL1_CTRL_UPD_MASK,
4496                            MADERA_FLL1_CTRL_UPD_MASK);
4497 
4498         /* Release the hold so that flln locks to external frequency */
4499         regmap_update_bits(madera->regmap,
4500                            fll->base + MADERA_FLL_CONTROL_1_OFFS,
4501                            MADERA_FLL1_HOLD_MASK,
4502                            0);
4503 
4504         if (!already_enabled)
4505                 madera_wait_for_fll(fll, true);
4506 
4507         return 0;
4508 }
4509 
4510 static int madera_fllhj_validate(struct madera_fll *fll,
4511                                  unsigned int ref_in,
4512                                  unsigned int fout)
4513 {
4514         if (fout && !ref_in) {
4515                 madera_fll_err(fll, "fllout set without valid input clk\n");
4516                 return -EINVAL;
4517         }
4518 
4519         if (fll->fout && fout != fll->fout) {
4520                 madera_fll_err(fll, "Can't change output on active FLL\n");
4521                 return -EINVAL;
4522         }
4523 
4524         if (ref_in / MADERA_FLL_MAX_REFDIV > MADERA_FLLHJ_MAX_THRESH) {
4525                 madera_fll_err(fll, "Can't scale %dMHz to <=13MHz\n", ref_in);
4526                 return -EINVAL;
4527         }
4528 
4529         return 0;
4530 }
4531 
4532 int madera_fllhj_set_refclk(struct madera_fll *fll, int source,
4533                             unsigned int fin, unsigned int fout)
4534 {
4535         int ret = 0;
4536 
4537         /* To remain consistent with previous FLLs, we expect fout to be
4538          * provided in the form of the required sysclk rate, which is
4539          * 2x the calculated fll out.
4540          */
4541         if (fout)
4542                 fout /= 2;
4543 
4544         if (fll->ref_src == source && fll->ref_freq == fin &&
4545             fll->fout == fout)
4546                 return 0;
4547 
4548         if (fin && fout && madera_fllhj_validate(fll, fin, fout))
4549                 return -EINVAL;
4550 
4551         fll->ref_src = source;
4552         fll->ref_freq = fin;
4553         fll->fout = fout;
4554 
4555         if (fout)
4556                 ret = madera_fllhj_enable(fll);
4557         else
4558                 madera_fllhj_disable(fll);
4559 
4560         return ret;
4561 }
4562 EXPORT_SYMBOL_GPL(madera_fllhj_set_refclk);
4563 
4564 /**
4565  * madera_set_output_mode - Set the mode of the specified output
4566  *
4567  * @component: Device to configure
4568  * @output: Output number
4569  * @diff: True to set the output to differential mode
4570  *
4571  * Some systems use external analogue switches to connect more
4572  * analogue devices to the CODEC than are supported by the device.  In
4573  * some systems this requires changing the switched output from single
4574  * ended to differential mode dynamically at runtime, an operation
4575  * supported using this function.
4576  *
4577  * Most systems have a single static configuration and should use
4578  * platform data instead.
4579  */
4580 int madera_set_output_mode(struct snd_soc_component *component, int output,
4581                            bool differential)
4582 {
4583         unsigned int reg, val;
4584         int ret;
4585 
4586         if (output < 1 || output > MADERA_MAX_OUTPUT)
4587                 return -EINVAL;
4588 
4589         reg = MADERA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
4590 
4591         if (differential)
4592                 val = MADERA_OUT1_MONO;
4593         else
4594                 val = 0;
4595 
4596         ret = snd_soc_component_update_bits(component, reg, MADERA_OUT1_MONO,
4597                                             val);
4598         if (ret < 0)
4599                 return ret;
4600         else
4601                 return 0;
4602 }
4603 EXPORT_SYMBOL_GPL(madera_set_output_mode);
4604 
4605 static bool madera_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
4606 {
4607         s16 a = be16_to_cpu(_a);
4608         s16 b = be16_to_cpu(_b);
4609 
4610         if (!mode) {
4611                 return abs(a) >= 4096;
4612         } else {
4613                 if (abs(b) >= 4096)
4614                         return true;
4615 
4616                 return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
4617         }
4618 }
4619 
4620 int madera_eq_coeff_put(struct snd_kcontrol *kcontrol,
4621                         struct snd_ctl_elem_value *ucontrol)
4622 {
4623         struct snd_soc_component *component =
4624                 snd_soc_kcontrol_component(kcontrol);
4625         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
4626         struct madera *madera = priv->madera;
4627         struct soc_bytes *params = (void *)kcontrol->private_value;
4628         unsigned int val;
4629         __be16 *data;
4630         int len;
4631         int ret;
4632 
4633         len = params->num_regs * regmap_get_val_bytes(madera->regmap);
4634 
4635         data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
4636         if (!data)
4637                 return -ENOMEM;
4638 
4639         data[0] &= cpu_to_be16(MADERA_EQ1_B1_MODE);
4640 
4641         if (madera_eq_filter_unstable(!!data[0], data[1], data[2]) ||
4642             madera_eq_filter_unstable(true, data[4], data[5]) ||
4643             madera_eq_filter_unstable(true, data[8], data[9]) ||
4644             madera_eq_filter_unstable(true, data[12], data[13]) ||
4645             madera_eq_filter_unstable(false, data[16], data[17])) {
4646                 dev_err(madera->dev, "Rejecting unstable EQ coefficients\n");
4647                 ret = -EINVAL;
4648                 goto out;
4649         }
4650 
4651         ret = regmap_read(madera->regmap, params->base, &val);
4652         if (ret != 0)
4653                 goto out;
4654 
4655         val &= ~MADERA_EQ1_B1_MODE;
4656         data[0] |= cpu_to_be16(val);
4657 
4658         ret = regmap_raw_write(madera->regmap, params->base, data, len);
4659 
4660 out:
4661         kfree(data);
4662 
4663         return ret;
4664 }
4665 EXPORT_SYMBOL_GPL(madera_eq_coeff_put);
4666 
4667 int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
4668                           struct snd_ctl_elem_value *ucontrol)
4669 {
4670         struct snd_soc_component *component =
4671                 snd_soc_kcontrol_component(kcontrol);
4672         struct madera_priv *priv = snd_soc_component_get_drvdata(component);
4673         struct madera *madera = priv->madera;
4674         __be16 *data = (__be16 *)ucontrol->value.bytes.data;
4675         s16 val = be16_to_cpu(*data);
4676 
4677         if (abs(val) >= 4096) {
4678                 dev_err(madera->dev, "Rejecting unstable LHPF coefficients\n");
4679                 return -EINVAL;
4680         }
4681 
4682         return snd_soc_bytes_put(kcontrol, ucontrol);
4683 }
4684 EXPORT_SYMBOL_GPL(madera_lhpf_coeff_put);
4685 
4686 MODULE_SOFTDEP("pre: madera");
4687 MODULE_DESCRIPTION("ASoC Cirrus Logic Madera codec support");
4688 MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
4689 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
4690 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */