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