linux/sound/soc/codecs/madera.c
<<
>>
Prefs
   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
 156static 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
 166static 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
 190int 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}
 200EXPORT_SYMBOL_GPL(madera_sysclk_ev);
 201
 202static 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
 221int 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}
 255EXPORT_SYMBOL_GPL(madera_spk_ev);
 256
 257static 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
 284int 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}
 304EXPORT_SYMBOL_GPL(madera_init_overheat);
 305
 306int 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}
 315EXPORT_SYMBOL_GPL(madera_free_overheat);
 316
 317static 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
 349static 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
 377static 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
 411int 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}
 429EXPORT_SYMBOL_GPL(madera_core_init);
 430
 431int madera_core_free(struct madera_priv *priv)
 432{
 433        mutex_destroy(&priv->rate_lock);
 434
 435        return 0;
 436}
 437EXPORT_SYMBOL_GPL(madera_core_free);
 438
 439static 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
 449int 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}
 489EXPORT_SYMBOL_GPL(madera_domain_clk_ev);
 490
 491int 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
 568end:
 569        snd_soc_dapm_mutex_unlock(dapm);
 570
 571        return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
 572}
 573EXPORT_SYMBOL_GPL(madera_out1_demux_put);
 574
 575int 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}
 593EXPORT_SYMBOL_GPL(madera_out1_demux_get);
 594
 595static 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
 652static const char * const madera_inmux_texts[] = {
 653        "A",
 654        "B",
 655};
 656
 657static SOC_ENUM_SINGLE_DECL(madera_in1muxl_enum,
 658                            MADERA_ADC_DIGITAL_VOLUME_1L,
 659                            MADERA_IN1L_SRC_SHIFT,
 660                            madera_inmux_texts);
 661
 662static SOC_ENUM_SINGLE_DECL(madera_in1muxr_enum,
 663                            MADERA_ADC_DIGITAL_VOLUME_1R,
 664                            MADERA_IN1R_SRC_SHIFT,
 665                            madera_inmux_texts);
 666
 667static SOC_ENUM_SINGLE_DECL(madera_in2muxl_enum,
 668                            MADERA_ADC_DIGITAL_VOLUME_2L,
 669                            MADERA_IN2L_SRC_SHIFT,
 670                            madera_inmux_texts);
 671
 672static SOC_ENUM_SINGLE_DECL(madera_in2muxr_enum,
 673                            MADERA_ADC_DIGITAL_VOLUME_2R,
 674                            MADERA_IN2R_SRC_SHIFT,
 675                            madera_inmux_texts);
 676
 677const 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};
 687EXPORT_SYMBOL_GPL(madera_inmux);
 688
 689static const char * const madera_dmode_texts[] = {
 690        "Analog",
 691        "Digital",
 692};
 693
 694static SOC_ENUM_SINGLE_DECL(madera_in1dmode_enum,
 695                            MADERA_IN1L_CONTROL,
 696                            MADERA_IN1_MODE_SHIFT,
 697                            madera_dmode_texts);
 698
 699static SOC_ENUM_SINGLE_DECL(madera_in2dmode_enum,
 700                            MADERA_IN2L_CONTROL,
 701                            MADERA_IN2_MODE_SHIFT,
 702                            madera_dmode_texts);
 703
 704static SOC_ENUM_SINGLE_DECL(madera_in3dmode_enum,
 705                            MADERA_IN3L_CONTROL,
 706                            MADERA_IN3_MODE_SHIFT,
 707                            madera_dmode_texts);
 708
 709const 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};
 714EXPORT_SYMBOL_GPL(madera_inmode);
 715
 716static 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
 820static 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
 841static 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
 878static 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
 895const 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};
 911EXPORT_SYMBOL_GPL(madera_adsp_rate_controls);
 912
 913static 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
 952err:
 953        dev_err(dsp->dev, "Failed to set DSP%d clock: %d\n", dsp->num, ret);
 954
 955        return ret;
 956}
 957
 958int 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}
 999EXPORT_SYMBOL_GPL(madera_set_adsp_clk);
1000
1001int 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        }
1045out:
1046        mutex_unlock(&priv->rate_lock);
1047
1048        return ret;
1049}
1050EXPORT_SYMBOL_GPL(madera_rate_put);
1051
1052static 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
1145int 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}
1154EXPORT_SYMBOL_GPL(madera_init_inputs);
1155
1156static 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
1165int 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}
1219EXPORT_SYMBOL_GPL(madera_init_outputs);
1220
1221int 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}
1238EXPORT_SYMBOL_GPL(madera_init_bus_error_irq);
1239
1240void 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}
1248EXPORT_SYMBOL_GPL(madera_free_bus_error_irq);
1249
1250const 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};
1400EXPORT_SYMBOL_GPL(madera_mixer_texts);
1401
1402const 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};
1552EXPORT_SYMBOL_GPL(madera_mixer_values);
1553
1554const DECLARE_TLV_DB_SCALE(madera_ana_tlv, 0, 100, 0);
1555EXPORT_SYMBOL_GPL(madera_ana_tlv);
1556
1557const DECLARE_TLV_DB_SCALE(madera_eq_tlv, -1200, 100, 0);
1558EXPORT_SYMBOL_GPL(madera_eq_tlv);
1559
1560const DECLARE_TLV_DB_SCALE(madera_digital_tlv, -6400, 50, 0);
1561EXPORT_SYMBOL_GPL(madera_digital_tlv);
1562
1563const DECLARE_TLV_DB_SCALE(madera_noise_tlv, -13200, 600, 0);
1564EXPORT_SYMBOL_GPL(madera_noise_tlv);
1565
1566const DECLARE_TLV_DB_SCALE(madera_ng_tlv, -12000, 600, 0);
1567EXPORT_SYMBOL_GPL(madera_ng_tlv);
1568
1569const DECLARE_TLV_DB_SCALE(madera_mixer_tlv, -3200, 100, 0);
1570EXPORT_SYMBOL_GPL(madera_mixer_tlv);
1571
1572const 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};
1576EXPORT_SYMBOL_GPL(madera_rate_text);
1577
1578const unsigned int madera_rate_val[MADERA_RATE_ENUM_SIZE] = {
1579        0x0, 0x1, 0x2, 0x8, 0x9,
1580};
1581EXPORT_SYMBOL_GPL(madera_rate_val);
1582
1583static 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
1587static const unsigned int madera_dfc_width_val[MADERA_DFC_WIDTH_ENUM_SIZE] = {
1588        7, 15, 19, 23, 31,
1589};
1590
1591static 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
1596static const unsigned int madera_dfc_type_val[MADERA_DFC_TYPE_ENUM_SIZE] = {
1597        0, 1, 2, 4, 5,
1598};
1599
1600const 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};
1714EXPORT_SYMBOL_GPL(madera_dfc_width);
1715
1716const 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};
1830EXPORT_SYMBOL_GPL(madera_dfc_type);
1831
1832const 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};
1851EXPORT_SYMBOL_GPL(madera_isrc_fsh);
1852
1853const 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};
1872EXPORT_SYMBOL_GPL(madera_isrc_fsl);
1873
1874const 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};
1886EXPORT_SYMBOL_GPL(madera_asrc1_rate);
1887
1888const 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};
1898EXPORT_SYMBOL_GPL(madera_asrc1_bidir_rate);
1899
1900const 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};
1912EXPORT_SYMBOL_GPL(madera_asrc2_rate);
1913
1914static 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
1919SOC_ENUM_SINGLE_DECL(madera_in_vd_ramp,
1920                     MADERA_INPUT_VOLUME_RAMP,
1921                     MADERA_IN_VD_RAMP_SHIFT,
1922                     madera_vol_ramp_text);
1923EXPORT_SYMBOL_GPL(madera_in_vd_ramp);
1924
1925SOC_ENUM_SINGLE_DECL(madera_in_vi_ramp,
1926                     MADERA_INPUT_VOLUME_RAMP,
1927                     MADERA_IN_VI_RAMP_SHIFT,
1928                     madera_vol_ramp_text);
1929EXPORT_SYMBOL_GPL(madera_in_vi_ramp);
1930
1931SOC_ENUM_SINGLE_DECL(madera_out_vd_ramp,
1932                     MADERA_OUTPUT_VOLUME_RAMP,
1933                     MADERA_OUT_VD_RAMP_SHIFT,
1934                     madera_vol_ramp_text);
1935EXPORT_SYMBOL_GPL(madera_out_vd_ramp);
1936
1937SOC_ENUM_SINGLE_DECL(madera_out_vi_ramp,
1938                     MADERA_OUTPUT_VOLUME_RAMP,
1939                     MADERA_OUT_VI_RAMP_SHIFT,
1940                     madera_vol_ramp_text);
1941EXPORT_SYMBOL_GPL(madera_out_vi_ramp);
1942
1943static const char * const madera_lhpf_mode_text[] = {
1944        "Low-pass", "High-pass"
1945};
1946
1947SOC_ENUM_SINGLE_DECL(madera_lhpf1_mode,
1948                     MADERA_HPLPF1_1,
1949                     MADERA_LHPF1_MODE_SHIFT,
1950                     madera_lhpf_mode_text);
1951EXPORT_SYMBOL_GPL(madera_lhpf1_mode);
1952
1953SOC_ENUM_SINGLE_DECL(madera_lhpf2_mode,
1954                     MADERA_HPLPF2_1,
1955                     MADERA_LHPF2_MODE_SHIFT,
1956                     madera_lhpf_mode_text);
1957EXPORT_SYMBOL_GPL(madera_lhpf2_mode);
1958
1959SOC_ENUM_SINGLE_DECL(madera_lhpf3_mode,
1960                     MADERA_HPLPF3_1,
1961                     MADERA_LHPF3_MODE_SHIFT,
1962                     madera_lhpf_mode_text);
1963EXPORT_SYMBOL_GPL(madera_lhpf3_mode);
1964
1965SOC_ENUM_SINGLE_DECL(madera_lhpf4_mode,
1966                     MADERA_HPLPF4_1,
1967                     MADERA_LHPF4_MODE_SHIFT,
1968                     madera_lhpf_mode_text);
1969EXPORT_SYMBOL_GPL(madera_lhpf4_mode);
1970
1971static const char * const madera_ng_hold_text[] = {
1972        "30ms", "120ms", "250ms", "500ms",
1973};
1974
1975SOC_ENUM_SINGLE_DECL(madera_ng_hold,
1976                     MADERA_NOISE_GATE_CONTROL,
1977                     MADERA_NGATE_HOLD_SHIFT,
1978                     madera_ng_hold_text);
1979EXPORT_SYMBOL_GPL(madera_ng_hold);
1980
1981static const char * const madera_in_hpf_cut_text[] = {
1982        "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
1983};
1984
1985SOC_ENUM_SINGLE_DECL(madera_in_hpf_cut_enum,
1986                     MADERA_HPF_CONTROL,
1987                     MADERA_IN_HPF_CUT_SHIFT,
1988                     madera_in_hpf_cut_text);
1989EXPORT_SYMBOL_GPL(madera_in_hpf_cut_enum);
1990
1991static const char * const madera_in_dmic_osr_text[MADERA_OSR_ENUM_SIZE] = {
1992        "384kHz", "768kHz", "1.536MHz", "3.072MHz", "6.144MHz",
1993};
1994
1995static const unsigned int madera_in_dmic_osr_val[MADERA_OSR_ENUM_SIZE] = {
1996        2, 3, 4, 5, 6,
1997};
1998
1999const 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};
2019EXPORT_SYMBOL_GPL(madera_in_dmic_osr);
2020
2021static const char * const madera_anc_input_src_text[] = {
2022        "None", "IN1", "IN2", "IN3", "IN4", "IN5", "IN6",
2023};
2024
2025static const char * const madera_anc_channel_src_text[] = {
2026        "None", "Left", "Right", "Combine",
2027};
2028
2029const 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};
2047EXPORT_SYMBOL_GPL(madera_anc_input_src);
2048
2049static const char * const madera_anc_ng_texts[] = {
2050        "None", "Internal", "External",
2051};
2052
2053SOC_ENUM_SINGLE_DECL(madera_anc_ng_enum, SND_SOC_NOPM, 0, madera_anc_ng_texts);
2054EXPORT_SYMBOL_GPL(madera_anc_ng_enum);
2055
2056static const char * const madera_out_anc_src_text[] = {
2057        "None", "RXANCL", "RXANCR",
2058};
2059
2060const 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};
2110EXPORT_SYMBOL_GPL(madera_output_anc_src);
2111
2112int 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);
2139exit:
2140        snd_soc_dapm_mutex_unlock(dapm);
2141
2142        return ret;
2143}
2144EXPORT_SYMBOL_GPL(madera_dfc_put);
2145
2146int 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
2176exit:
2177        snd_soc_dapm_mutex_unlock(dapm);
2178
2179        return ret;
2180}
2181EXPORT_SYMBOL_GPL(madera_lp_mode_put);
2182
2183const 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};
2192EXPORT_SYMBOL_GPL(madera_dsp_trigger_output_mux);
2193
2194const 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};
2198EXPORT_SYMBOL_GPL(madera_drc_activity_output_mux);
2199
2200static 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
2220int 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}
2266EXPORT_SYMBOL_GPL(madera_in_ev);
2267
2268int 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}
2366EXPORT_SYMBOL_GPL(madera_out_ev);
2367
2368int 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}
2418EXPORT_SYMBOL_GPL(madera_hp_ev);
2419
2420int 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}
2441EXPORT_SYMBOL_GPL(madera_anc_ev);
2442
2443static const unsigned int madera_opclk_ref_48k_rates[] = {
2444        6144000,
2445        12288000,
2446        24576000,
2447        49152000,
2448};
2449
2450static const unsigned int madera_opclk_ref_44k1_rates[] = {
2451        5644800,
2452        11289600,
2453        22579200,
2454        45158400,
2455};
2456
2457static 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
2512static 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
2536static 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
2563static 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
2583static 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
2635int 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}
2715EXPORT_SYMBOL_GPL(madera_set_sysclk);
2716
2717static 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
2811static 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
2833static 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
2855static 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
2891static const struct snd_pcm_hw_constraint_list madera_constraint = {
2892        .count  = ARRAY_SIZE(madera_sr_vals),
2893        .list   = madera_sr_vals,
2894};
2895
2896static 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
2948static 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
3027out:
3028        mutex_unlock(&priv->rate_lock);
3029
3030        return ret;
3031}
3032
3033static 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
3064static 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
3180restore_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
3194static 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
3209static 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
3258static 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
3279static 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
3302static 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
3331const 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};
3339EXPORT_SYMBOL_GPL(madera_dai_ops);
3340
3341const 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};
3346EXPORT_SYMBOL_GPL(madera_simple_dai_ops);
3347
3348int 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}
3357EXPORT_SYMBOL_GPL(madera_init_dai);
3358
3359static 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
3372static 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
3391struct 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
3398static 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
3404static 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
3413static 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
3430static 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
3444static 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
3474static 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
3570static 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
3591static 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
3684static 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
3741static 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
3757static 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
3790static 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
3812static 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
3848static 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
3998err:
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
4005static 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
4015int 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}
4032EXPORT_SYMBOL_GPL(madera_set_fll_syncclk);
4033
4034int 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}
4064EXPORT_SYMBOL_GPL(madera_set_fll_refclk);
4065
4066int 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}
4081EXPORT_SYMBOL_GPL(madera_init_fll);
4082
4083static 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
4096static 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
4109struct madera_fllao_patch {
4110        unsigned int fin;
4111        unsigned int fout;
4112        const struct reg_sequence *patch;
4113        unsigned int patch_size;
4114};
4115
4116static 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
4132static 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
4183static 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
4217int 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}
4260EXPORT_SYMBOL_GPL(madera_set_fll_ao_refclk);
4261
4262static 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
4304static 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
4450static 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
4487out:
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
4510static 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
4532int 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}
4562EXPORT_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 */
4580int 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}
4603EXPORT_SYMBOL_GPL(madera_set_output_mode);
4604
4605static 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
4620int 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
4660out:
4661        kfree(data);
4662
4663        return ret;
4664}
4665EXPORT_SYMBOL_GPL(madera_eq_coeff_put);
4666
4667int 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}
4684EXPORT_SYMBOL_GPL(madera_lhpf_coeff_put);
4685
4686MODULE_SOFTDEP("pre: madera");
4687MODULE_DESCRIPTION("ASoC Cirrus Logic Madera codec support");
4688MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
4689MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
4690MODULE_LICENSE("GPL v2");
4691