linux/sound/soc/codecs/arizona.c
<<
>>
Prefs
   1/*
   2 * arizona.c - Wolfson Arizona class device shared support
   3 *
   4 * Copyright 2012 Wolfson Microelectronics plc
   5 *
   6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/delay.h>
  14#include <linux/gcd.h>
  15#include <linux/module.h>
  16#include <linux/pm_runtime.h>
  17#include <sound/pcm.h>
  18#include <sound/pcm_params.h>
  19#include <sound/tlv.h>
  20
  21#include <linux/mfd/arizona/core.h>
  22#include <linux/mfd/arizona/registers.h>
  23
  24#include "arizona.h"
  25
  26#define ARIZONA_AIF_BCLK_CTRL                   0x00
  27#define ARIZONA_AIF_TX_PIN_CTRL                 0x01
  28#define ARIZONA_AIF_RX_PIN_CTRL                 0x02
  29#define ARIZONA_AIF_RATE_CTRL                   0x03
  30#define ARIZONA_AIF_FORMAT                      0x04
  31#define ARIZONA_AIF_TX_BCLK_RATE                0x05
  32#define ARIZONA_AIF_RX_BCLK_RATE                0x06
  33#define ARIZONA_AIF_FRAME_CTRL_1                0x07
  34#define ARIZONA_AIF_FRAME_CTRL_2                0x08
  35#define ARIZONA_AIF_FRAME_CTRL_3                0x09
  36#define ARIZONA_AIF_FRAME_CTRL_4                0x0A
  37#define ARIZONA_AIF_FRAME_CTRL_5                0x0B
  38#define ARIZONA_AIF_FRAME_CTRL_6                0x0C
  39#define ARIZONA_AIF_FRAME_CTRL_7                0x0D
  40#define ARIZONA_AIF_FRAME_CTRL_8                0x0E
  41#define ARIZONA_AIF_FRAME_CTRL_9                0x0F
  42#define ARIZONA_AIF_FRAME_CTRL_10               0x10
  43#define ARIZONA_AIF_FRAME_CTRL_11               0x11
  44#define ARIZONA_AIF_FRAME_CTRL_12               0x12
  45#define ARIZONA_AIF_FRAME_CTRL_13               0x13
  46#define ARIZONA_AIF_FRAME_CTRL_14               0x14
  47#define ARIZONA_AIF_FRAME_CTRL_15               0x15
  48#define ARIZONA_AIF_FRAME_CTRL_16               0x16
  49#define ARIZONA_AIF_FRAME_CTRL_17               0x17
  50#define ARIZONA_AIF_FRAME_CTRL_18               0x18
  51#define ARIZONA_AIF_TX_ENABLES                  0x19
  52#define ARIZONA_AIF_RX_ENABLES                  0x1A
  53#define ARIZONA_AIF_FORCE_WRITE                 0x1B
  54
  55#define ARIZONA_FLL_VCO_CORNER 141900000
  56#define ARIZONA_FLL_MAX_FREF   13500000
  57#define ARIZONA_FLL_MIN_FVCO   90000000
  58#define ARIZONA_FLL_MAX_FRATIO 16
  59#define ARIZONA_FLL_MAX_REFDIV 8
  60#define ARIZONA_FLL_MIN_OUTDIV 2
  61#define ARIZONA_FLL_MAX_OUTDIV 7
  62
  63#define ARIZONA_FMT_DSP_MODE_A          0
  64#define ARIZONA_FMT_DSP_MODE_B          1
  65#define ARIZONA_FMT_I2S_MODE            2
  66#define ARIZONA_FMT_LEFT_JUSTIFIED_MODE 3
  67
  68#define arizona_fll_err(_fll, fmt, ...) \
  69        dev_err(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
  70#define arizona_fll_warn(_fll, fmt, ...) \
  71        dev_warn(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
  72#define arizona_fll_dbg(_fll, fmt, ...) \
  73        dev_dbg(_fll->arizona->dev, "FLL%d: " fmt, _fll->id, ##__VA_ARGS__)
  74
  75#define arizona_aif_err(_dai, fmt, ...) \
  76        dev_err(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
  77#define arizona_aif_warn(_dai, fmt, ...) \
  78        dev_warn(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
  79#define arizona_aif_dbg(_dai, fmt, ...) \
  80        dev_dbg(_dai->dev, "AIF%d: " fmt, _dai->id, ##__VA_ARGS__)
  81
  82static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
  83                          struct snd_kcontrol *kcontrol,
  84                          int event)
  85{
  86        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  87        struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
  88        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
  89        bool manual_ena = false;
  90        int val;
  91
  92        switch (arizona->type) {
  93        case WM5102:
  94                switch (arizona->rev) {
  95                case 0:
  96                        break;
  97                default:
  98                        manual_ena = true;
  99                        break;
 100                }
 101        default:
 102                break;
 103        }
 104
 105        switch (event) {
 106        case SND_SOC_DAPM_PRE_PMU:
 107                if (!priv->spk_ena && manual_ena) {
 108                        regmap_write_async(arizona->regmap, 0x4f5, 0x25a);
 109                        priv->spk_ena_pending = true;
 110                }
 111                break;
 112        case SND_SOC_DAPM_POST_PMU:
 113                val = snd_soc_read(codec, ARIZONA_INTERRUPT_RAW_STATUS_3);
 114                if (val & ARIZONA_SPK_OVERHEAT_STS) {
 115                        dev_crit(arizona->dev,
 116                                 "Speaker not enabled due to temperature\n");
 117                        return -EBUSY;
 118                }
 119
 120                regmap_update_bits_async(arizona->regmap,
 121                                         ARIZONA_OUTPUT_ENABLES_1,
 122                                         1 << w->shift, 1 << w->shift);
 123
 124                if (priv->spk_ena_pending) {
 125                        msleep(75);
 126                        regmap_write_async(arizona->regmap, 0x4f5, 0xda);
 127                        priv->spk_ena_pending = false;
 128                        priv->spk_ena++;
 129                }
 130                break;
 131        case SND_SOC_DAPM_PRE_PMD:
 132                if (manual_ena) {
 133                        priv->spk_ena--;
 134                        if (!priv->spk_ena)
 135                                regmap_write_async(arizona->regmap,
 136                                                   0x4f5, 0x25a);
 137                }
 138
 139                regmap_update_bits_async(arizona->regmap,
 140                                         ARIZONA_OUTPUT_ENABLES_1,
 141                                         1 << w->shift, 0);
 142                break;
 143        case SND_SOC_DAPM_POST_PMD:
 144                if (manual_ena) {
 145                        if (!priv->spk_ena)
 146                                regmap_write_async(arizona->regmap,
 147                                                   0x4f5, 0x0da);
 148                }
 149                break;
 150        default:
 151                break;
 152        }
 153
 154        return 0;
 155}
 156
 157static irqreturn_t arizona_thermal_warn(int irq, void *data)
 158{
 159        struct arizona *arizona = data;
 160        unsigned int val;
 161        int ret;
 162
 163        ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
 164                          &val);
 165        if (ret != 0) {
 166                dev_err(arizona->dev, "Failed to read thermal status: %d\n",
 167                        ret);
 168        } else if (val & ARIZONA_SPK_OVERHEAT_WARN_STS) {
 169                dev_crit(arizona->dev, "Thermal warning\n");
 170        }
 171
 172        return IRQ_HANDLED;
 173}
 174
 175static irqreturn_t arizona_thermal_shutdown(int irq, void *data)
 176{
 177        struct arizona *arizona = data;
 178        unsigned int val;
 179        int ret;
 180
 181        ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_3,
 182                          &val);
 183        if (ret != 0) {
 184                dev_err(arizona->dev, "Failed to read thermal status: %d\n",
 185                        ret);
 186        } else if (val & ARIZONA_SPK_OVERHEAT_STS) {
 187                dev_crit(arizona->dev, "Thermal shutdown\n");
 188                ret = regmap_update_bits(arizona->regmap,
 189                                         ARIZONA_OUTPUT_ENABLES_1,
 190                                         ARIZONA_OUT4L_ENA |
 191                                         ARIZONA_OUT4R_ENA, 0);
 192                if (ret != 0)
 193                        dev_crit(arizona->dev,
 194                                 "Failed to disable speaker outputs: %d\n",
 195                                 ret);
 196        }
 197
 198        return IRQ_HANDLED;
 199}
 200
 201static const struct snd_soc_dapm_widget arizona_spkl =
 202        SND_SOC_DAPM_PGA_E("OUT4L", SND_SOC_NOPM,
 203                           ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
 204                           SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
 205
 206static const struct snd_soc_dapm_widget arizona_spkr =
 207        SND_SOC_DAPM_PGA_E("OUT4R", SND_SOC_NOPM,
 208                           ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_spk_ev,
 209                           SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU);
 210
 211int arizona_init_spk(struct snd_soc_codec *codec)
 212{
 213        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 214        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 215        struct arizona *arizona = priv->arizona;
 216        int ret;
 217
 218        ret = snd_soc_dapm_new_controls(dapm, &arizona_spkl, 1);
 219        if (ret != 0)
 220                return ret;
 221
 222        switch (arizona->type) {
 223        case WM8997:
 224                break;
 225        default:
 226                ret = snd_soc_dapm_new_controls(dapm, &arizona_spkr, 1);
 227                if (ret != 0)
 228                        return ret;
 229                break;
 230        }
 231
 232        ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN,
 233                                  "Thermal warning", arizona_thermal_warn,
 234                                  arizona);
 235        if (ret != 0)
 236                dev_err(arizona->dev,
 237                        "Failed to get thermal warning IRQ: %d\n",
 238                        ret);
 239
 240        ret = arizona_request_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT,
 241                                  "Thermal shutdown", arizona_thermal_shutdown,
 242                                  arizona);
 243        if (ret != 0)
 244                dev_err(arizona->dev,
 245                        "Failed to get thermal shutdown IRQ: %d\n",
 246                        ret);
 247
 248        return 0;
 249}
 250EXPORT_SYMBOL_GPL(arizona_init_spk);
 251
 252int arizona_free_spk(struct snd_soc_codec *codec)
 253{
 254        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 255        struct arizona *arizona = priv->arizona;
 256
 257        arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT_WARN, arizona);
 258        arizona_free_irq(arizona, ARIZONA_IRQ_SPK_OVERHEAT, arizona);
 259
 260        return 0;
 261}
 262EXPORT_SYMBOL_GPL(arizona_free_spk);
 263
 264static const struct snd_soc_dapm_route arizona_mono_routes[] = {
 265        { "OUT1R", NULL, "OUT1L" },
 266        { "OUT2R", NULL, "OUT2L" },
 267        { "OUT3R", NULL, "OUT3L" },
 268        { "OUT4R", NULL, "OUT4L" },
 269        { "OUT5R", NULL, "OUT5L" },
 270        { "OUT6R", NULL, "OUT6L" },
 271};
 272
 273int arizona_init_mono(struct snd_soc_codec *codec)
 274{
 275        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 276        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 277        struct arizona *arizona = priv->arizona;
 278        int i;
 279
 280        for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
 281                if (arizona->pdata.out_mono[i])
 282                        snd_soc_dapm_add_routes(dapm,
 283                                                &arizona_mono_routes[i], 1);
 284        }
 285
 286        return 0;
 287}
 288EXPORT_SYMBOL_GPL(arizona_init_mono);
 289
 290int arizona_init_gpio(struct snd_soc_codec *codec)
 291{
 292        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 293        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 294        struct arizona *arizona = priv->arizona;
 295        int i;
 296
 297        switch (arizona->type) {
 298        case WM5110:
 299        case WM8280:
 300                snd_soc_dapm_disable_pin(dapm, "DRC2 Signal Activity");
 301                break;
 302        default:
 303                break;
 304        }
 305
 306        snd_soc_dapm_disable_pin(dapm, "DRC1 Signal Activity");
 307
 308        for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) {
 309                switch (arizona->pdata.gpio_defaults[i] & ARIZONA_GPN_FN_MASK) {
 310                case ARIZONA_GP_FN_DRC1_SIGNAL_DETECT:
 311                        snd_soc_dapm_enable_pin(dapm, "DRC1 Signal Activity");
 312                        break;
 313                case ARIZONA_GP_FN_DRC2_SIGNAL_DETECT:
 314                        snd_soc_dapm_enable_pin(dapm, "DRC2 Signal Activity");
 315                        break;
 316                default:
 317                        break;
 318                }
 319        }
 320
 321        return 0;
 322}
 323EXPORT_SYMBOL_GPL(arizona_init_gpio);
 324
 325const char * const arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = {
 326        "None",
 327        "Tone Generator 1",
 328        "Tone Generator 2",
 329        "Haptics",
 330        "AEC",
 331        "AEC2",
 332        "Mic Mute Mixer",
 333        "Noise Generator",
 334        "IN1L",
 335        "IN1R",
 336        "IN2L",
 337        "IN2R",
 338        "IN3L",
 339        "IN3R",
 340        "IN4L",
 341        "IN4R",
 342        "AIF1RX1",
 343        "AIF1RX2",
 344        "AIF1RX3",
 345        "AIF1RX4",
 346        "AIF1RX5",
 347        "AIF1RX6",
 348        "AIF1RX7",
 349        "AIF1RX8",
 350        "AIF2RX1",
 351        "AIF2RX2",
 352        "AIF2RX3",
 353        "AIF2RX4",
 354        "AIF2RX5",
 355        "AIF2RX6",
 356        "AIF3RX1",
 357        "AIF3RX2",
 358        "SLIMRX1",
 359        "SLIMRX2",
 360        "SLIMRX3",
 361        "SLIMRX4",
 362        "SLIMRX5",
 363        "SLIMRX6",
 364        "SLIMRX7",
 365        "SLIMRX8",
 366        "EQ1",
 367        "EQ2",
 368        "EQ3",
 369        "EQ4",
 370        "DRC1L",
 371        "DRC1R",
 372        "DRC2L",
 373        "DRC2R",
 374        "LHPF1",
 375        "LHPF2",
 376        "LHPF3",
 377        "LHPF4",
 378        "DSP1.1",
 379        "DSP1.2",
 380        "DSP1.3",
 381        "DSP1.4",
 382        "DSP1.5",
 383        "DSP1.6",
 384        "DSP2.1",
 385        "DSP2.2",
 386        "DSP2.3",
 387        "DSP2.4",
 388        "DSP2.5",
 389        "DSP2.6",
 390        "DSP3.1",
 391        "DSP3.2",
 392        "DSP3.3",
 393        "DSP3.4",
 394        "DSP3.5",
 395        "DSP3.6",
 396        "DSP4.1",
 397        "DSP4.2",
 398        "DSP4.3",
 399        "DSP4.4",
 400        "DSP4.5",
 401        "DSP4.6",
 402        "ASRC1L",
 403        "ASRC1R",
 404        "ASRC2L",
 405        "ASRC2R",
 406        "ISRC1INT1",
 407        "ISRC1INT2",
 408        "ISRC1INT3",
 409        "ISRC1INT4",
 410        "ISRC1DEC1",
 411        "ISRC1DEC2",
 412        "ISRC1DEC3",
 413        "ISRC1DEC4",
 414        "ISRC2INT1",
 415        "ISRC2INT2",
 416        "ISRC2INT3",
 417        "ISRC2INT4",
 418        "ISRC2DEC1",
 419        "ISRC2DEC2",
 420        "ISRC2DEC3",
 421        "ISRC2DEC4",
 422        "ISRC3INT1",
 423        "ISRC3INT2",
 424        "ISRC3INT3",
 425        "ISRC3INT4",
 426        "ISRC3DEC1",
 427        "ISRC3DEC2",
 428        "ISRC3DEC3",
 429        "ISRC3DEC4",
 430};
 431EXPORT_SYMBOL_GPL(arizona_mixer_texts);
 432
 433unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = {
 434        0x00,  /* None */
 435        0x04,  /* Tone */
 436        0x05,
 437        0x06,  /* Haptics */
 438        0x08,  /* AEC */
 439        0x09,  /* AEC2 */
 440        0x0c,  /* Noise mixer */
 441        0x0d,  /* Comfort noise */
 442        0x10,  /* IN1L */
 443        0x11,
 444        0x12,
 445        0x13,
 446        0x14,
 447        0x15,
 448        0x16,
 449        0x17,
 450        0x20,  /* AIF1RX1 */
 451        0x21,
 452        0x22,
 453        0x23,
 454        0x24,
 455        0x25,
 456        0x26,
 457        0x27,
 458        0x28,  /* AIF2RX1 */
 459        0x29,
 460        0x2a,
 461        0x2b,
 462        0x2c,
 463        0x2d,
 464        0x30,  /* AIF3RX1 */
 465        0x31,
 466        0x38,  /* SLIMRX1 */
 467        0x39,
 468        0x3a,
 469        0x3b,
 470        0x3c,
 471        0x3d,
 472        0x3e,
 473        0x3f,
 474        0x50,  /* EQ1 */
 475        0x51,
 476        0x52,
 477        0x53,
 478        0x58,  /* DRC1L */
 479        0x59,
 480        0x5a,
 481        0x5b,
 482        0x60,  /* LHPF1 */
 483        0x61,
 484        0x62,
 485        0x63,
 486        0x68,  /* DSP1.1 */
 487        0x69,
 488        0x6a,
 489        0x6b,
 490        0x6c,
 491        0x6d,
 492        0x70,  /* DSP2.1 */
 493        0x71,
 494        0x72,
 495        0x73,
 496        0x74,
 497        0x75,
 498        0x78,  /* DSP3.1 */
 499        0x79,
 500        0x7a,
 501        0x7b,
 502        0x7c,
 503        0x7d,
 504        0x80,  /* DSP4.1 */
 505        0x81,
 506        0x82,
 507        0x83,
 508        0x84,
 509        0x85,
 510        0x90,  /* ASRC1L */
 511        0x91,
 512        0x92,
 513        0x93,
 514        0xa0,  /* ISRC1INT1 */
 515        0xa1,
 516        0xa2,
 517        0xa3,
 518        0xa4,  /* ISRC1DEC1 */
 519        0xa5,
 520        0xa6,
 521        0xa7,
 522        0xa8,  /* ISRC2DEC1 */
 523        0xa9,
 524        0xaa,
 525        0xab,
 526        0xac,  /* ISRC2INT1 */
 527        0xad,
 528        0xae,
 529        0xaf,
 530        0xb0,  /* ISRC3DEC1 */
 531        0xb1,
 532        0xb2,
 533        0xb3,
 534        0xb4,  /* ISRC3INT1 */
 535        0xb5,
 536        0xb6,
 537        0xb7,
 538};
 539EXPORT_SYMBOL_GPL(arizona_mixer_values);
 540
 541const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0);
 542EXPORT_SYMBOL_GPL(arizona_mixer_tlv);
 543
 544const char * const arizona_sample_rate_text[ARIZONA_SAMPLE_RATE_ENUM_SIZE] = {
 545        "12kHz", "24kHz", "48kHz", "96kHz", "192kHz",
 546        "11.025kHz", "22.05kHz", "44.1kHz", "88.2kHz", "176.4kHz",
 547        "4kHz", "8kHz", "16kHz", "32kHz",
 548};
 549EXPORT_SYMBOL_GPL(arizona_sample_rate_text);
 550
 551const unsigned int arizona_sample_rate_val[ARIZONA_SAMPLE_RATE_ENUM_SIZE] = {
 552        0x01, 0x02, 0x03, 0x04, 0x05, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
 553        0x10, 0x11, 0x12, 0x13,
 554};
 555EXPORT_SYMBOL_GPL(arizona_sample_rate_val);
 556
 557const char *arizona_sample_rate_val_to_name(unsigned int rate_val)
 558{
 559        int i;
 560
 561        for (i = 0; i < ARRAY_SIZE(arizona_sample_rate_val); ++i) {
 562                if (arizona_sample_rate_val[i] == rate_val)
 563                        return arizona_sample_rate_text[i];
 564        }
 565
 566        return "Illegal";
 567}
 568EXPORT_SYMBOL_GPL(arizona_sample_rate_val_to_name);
 569
 570const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE] = {
 571        "SYNCCLK rate", "8kHz", "16kHz", "ASYNCCLK rate",
 572};
 573EXPORT_SYMBOL_GPL(arizona_rate_text);
 574
 575const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE] = {
 576        0, 1, 2, 8,
 577};
 578EXPORT_SYMBOL_GPL(arizona_rate_val);
 579
 580
 581const struct soc_enum arizona_isrc_fsh[] = {
 582        SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_1,
 583                              ARIZONA_ISRC1_FSH_SHIFT, 0xf,
 584                              ARIZONA_RATE_ENUM_SIZE,
 585                              arizona_rate_text, arizona_rate_val),
 586        SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_1,
 587                              ARIZONA_ISRC2_FSH_SHIFT, 0xf,
 588                              ARIZONA_RATE_ENUM_SIZE,
 589                              arizona_rate_text, arizona_rate_val),
 590        SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_1,
 591                              ARIZONA_ISRC3_FSH_SHIFT, 0xf,
 592                              ARIZONA_RATE_ENUM_SIZE,
 593                              arizona_rate_text, arizona_rate_val),
 594};
 595EXPORT_SYMBOL_GPL(arizona_isrc_fsh);
 596
 597const struct soc_enum arizona_isrc_fsl[] = {
 598        SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_1_CTRL_2,
 599                              ARIZONA_ISRC1_FSL_SHIFT, 0xf,
 600                              ARIZONA_RATE_ENUM_SIZE,
 601                              arizona_rate_text, arizona_rate_val),
 602        SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_2_CTRL_2,
 603                              ARIZONA_ISRC2_FSL_SHIFT, 0xf,
 604                              ARIZONA_RATE_ENUM_SIZE,
 605                              arizona_rate_text, arizona_rate_val),
 606        SOC_VALUE_ENUM_SINGLE(ARIZONA_ISRC_3_CTRL_2,
 607                              ARIZONA_ISRC3_FSL_SHIFT, 0xf,
 608                              ARIZONA_RATE_ENUM_SIZE,
 609                              arizona_rate_text, arizona_rate_val),
 610};
 611EXPORT_SYMBOL_GPL(arizona_isrc_fsl);
 612
 613const struct soc_enum arizona_asrc_rate1 =
 614        SOC_VALUE_ENUM_SINGLE(ARIZONA_ASRC_RATE1,
 615                              ARIZONA_ASRC_RATE1_SHIFT, 0xf,
 616                              ARIZONA_RATE_ENUM_SIZE - 1,
 617                              arizona_rate_text, arizona_rate_val);
 618EXPORT_SYMBOL_GPL(arizona_asrc_rate1);
 619
 620static const char *arizona_vol_ramp_text[] = {
 621        "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB",
 622        "15ms/6dB", "30ms/6dB",
 623};
 624
 625SOC_ENUM_SINGLE_DECL(arizona_in_vd_ramp,
 626                     ARIZONA_INPUT_VOLUME_RAMP,
 627                     ARIZONA_IN_VD_RAMP_SHIFT,
 628                     arizona_vol_ramp_text);
 629EXPORT_SYMBOL_GPL(arizona_in_vd_ramp);
 630
 631SOC_ENUM_SINGLE_DECL(arizona_in_vi_ramp,
 632                     ARIZONA_INPUT_VOLUME_RAMP,
 633                     ARIZONA_IN_VI_RAMP_SHIFT,
 634                     arizona_vol_ramp_text);
 635EXPORT_SYMBOL_GPL(arizona_in_vi_ramp);
 636
 637SOC_ENUM_SINGLE_DECL(arizona_out_vd_ramp,
 638                     ARIZONA_OUTPUT_VOLUME_RAMP,
 639                     ARIZONA_OUT_VD_RAMP_SHIFT,
 640                     arizona_vol_ramp_text);
 641EXPORT_SYMBOL_GPL(arizona_out_vd_ramp);
 642
 643SOC_ENUM_SINGLE_DECL(arizona_out_vi_ramp,
 644                     ARIZONA_OUTPUT_VOLUME_RAMP,
 645                     ARIZONA_OUT_VI_RAMP_SHIFT,
 646                     arizona_vol_ramp_text);
 647EXPORT_SYMBOL_GPL(arizona_out_vi_ramp);
 648
 649static const char *arizona_lhpf_mode_text[] = {
 650        "Low-pass", "High-pass"
 651};
 652
 653SOC_ENUM_SINGLE_DECL(arizona_lhpf1_mode,
 654                     ARIZONA_HPLPF1_1,
 655                     ARIZONA_LHPF1_MODE_SHIFT,
 656                     arizona_lhpf_mode_text);
 657EXPORT_SYMBOL_GPL(arizona_lhpf1_mode);
 658
 659SOC_ENUM_SINGLE_DECL(arizona_lhpf2_mode,
 660                     ARIZONA_HPLPF2_1,
 661                     ARIZONA_LHPF2_MODE_SHIFT,
 662                     arizona_lhpf_mode_text);
 663EXPORT_SYMBOL_GPL(arizona_lhpf2_mode);
 664
 665SOC_ENUM_SINGLE_DECL(arizona_lhpf3_mode,
 666                     ARIZONA_HPLPF3_1,
 667                     ARIZONA_LHPF3_MODE_SHIFT,
 668                     arizona_lhpf_mode_text);
 669EXPORT_SYMBOL_GPL(arizona_lhpf3_mode);
 670
 671SOC_ENUM_SINGLE_DECL(arizona_lhpf4_mode,
 672                     ARIZONA_HPLPF4_1,
 673                     ARIZONA_LHPF4_MODE_SHIFT,
 674                     arizona_lhpf_mode_text);
 675EXPORT_SYMBOL_GPL(arizona_lhpf4_mode);
 676
 677static const char *arizona_ng_hold_text[] = {
 678        "30ms", "120ms", "250ms", "500ms",
 679};
 680
 681SOC_ENUM_SINGLE_DECL(arizona_ng_hold,
 682                     ARIZONA_NOISE_GATE_CONTROL,
 683                     ARIZONA_NGATE_HOLD_SHIFT,
 684                     arizona_ng_hold_text);
 685EXPORT_SYMBOL_GPL(arizona_ng_hold);
 686
 687static const char * const arizona_in_hpf_cut_text[] = {
 688        "2.5Hz", "5Hz", "10Hz", "20Hz", "40Hz"
 689};
 690
 691SOC_ENUM_SINGLE_DECL(arizona_in_hpf_cut_enum,
 692                     ARIZONA_HPF_CONTROL,
 693                     ARIZONA_IN_HPF_CUT_SHIFT,
 694                     arizona_in_hpf_cut_text);
 695EXPORT_SYMBOL_GPL(arizona_in_hpf_cut_enum);
 696
 697static const char * const arizona_in_dmic_osr_text[] = {
 698        "1.536MHz", "3.072MHz", "6.144MHz", "768kHz",
 699};
 700
 701const struct soc_enum arizona_in_dmic_osr[] = {
 702        SOC_ENUM_SINGLE(ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT,
 703                        ARRAY_SIZE(arizona_in_dmic_osr_text),
 704                        arizona_in_dmic_osr_text),
 705        SOC_ENUM_SINGLE(ARIZONA_IN2L_CONTROL, ARIZONA_IN2_OSR_SHIFT,
 706                        ARRAY_SIZE(arizona_in_dmic_osr_text),
 707                        arizona_in_dmic_osr_text),
 708        SOC_ENUM_SINGLE(ARIZONA_IN3L_CONTROL, ARIZONA_IN3_OSR_SHIFT,
 709                        ARRAY_SIZE(arizona_in_dmic_osr_text),
 710                        arizona_in_dmic_osr_text),
 711        SOC_ENUM_SINGLE(ARIZONA_IN4L_CONTROL, ARIZONA_IN4_OSR_SHIFT,
 712                        ARRAY_SIZE(arizona_in_dmic_osr_text),
 713                        arizona_in_dmic_osr_text),
 714};
 715EXPORT_SYMBOL_GPL(arizona_in_dmic_osr);
 716
 717static const char * const arizona_anc_input_src_text[] = {
 718        "None", "IN1", "IN2", "IN3", "IN4",
 719};
 720
 721static const char * const arizona_anc_channel_src_text[] = {
 722        "None", "Left", "Right", "Combine",
 723};
 724
 725const struct soc_enum arizona_anc_input_src[] = {
 726        SOC_ENUM_SINGLE(ARIZONA_ANC_SRC,
 727                        ARIZONA_IN_RXANCL_SEL_SHIFT,
 728                        ARRAY_SIZE(arizona_anc_input_src_text),
 729                        arizona_anc_input_src_text),
 730        SOC_ENUM_SINGLE(ARIZONA_FCL_ADC_REFORMATTER_CONTROL,
 731                        ARIZONA_FCL_MIC_MODE_SEL,
 732                        ARRAY_SIZE(arizona_anc_channel_src_text),
 733                        arizona_anc_channel_src_text),
 734        SOC_ENUM_SINGLE(ARIZONA_ANC_SRC,
 735                        ARIZONA_IN_RXANCR_SEL_SHIFT,
 736                        ARRAY_SIZE(arizona_anc_input_src_text),
 737                        arizona_anc_input_src_text),
 738        SOC_ENUM_SINGLE(ARIZONA_FCR_ADC_REFORMATTER_CONTROL,
 739                        ARIZONA_FCR_MIC_MODE_SEL,
 740                        ARRAY_SIZE(arizona_anc_channel_src_text),
 741                        arizona_anc_channel_src_text),
 742};
 743EXPORT_SYMBOL_GPL(arizona_anc_input_src);
 744
 745static const char * const arizona_anc_ng_texts[] = {
 746        "None",
 747        "Internal",
 748        "External",
 749};
 750
 751SOC_ENUM_SINGLE_DECL(arizona_anc_ng_enum, SND_SOC_NOPM, 0,
 752                     arizona_anc_ng_texts);
 753EXPORT_SYMBOL_GPL(arizona_anc_ng_enum);
 754
 755static const char * const arizona_output_anc_src_text[] = {
 756        "None", "RXANCL", "RXANCR",
 757};
 758
 759const struct soc_enum arizona_output_anc_src[] = {
 760        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1L,
 761                        ARIZONA_OUT1L_ANC_SRC_SHIFT,
 762                        ARRAY_SIZE(arizona_output_anc_src_text),
 763                        arizona_output_anc_src_text),
 764        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_1R,
 765                        ARIZONA_OUT1R_ANC_SRC_SHIFT,
 766                        ARRAY_SIZE(arizona_output_anc_src_text),
 767                        arizona_output_anc_src_text),
 768        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2L,
 769                        ARIZONA_OUT2L_ANC_SRC_SHIFT,
 770                        ARRAY_SIZE(arizona_output_anc_src_text),
 771                        arizona_output_anc_src_text),
 772        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_2R,
 773                        ARIZONA_OUT2R_ANC_SRC_SHIFT,
 774                        ARRAY_SIZE(arizona_output_anc_src_text),
 775                        arizona_output_anc_src_text),
 776        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_3L,
 777                        ARIZONA_OUT3L_ANC_SRC_SHIFT,
 778                        ARRAY_SIZE(arizona_output_anc_src_text),
 779                        arizona_output_anc_src_text),
 780        SOC_ENUM_SINGLE(ARIZONA_DAC_VOLUME_LIMIT_3R,
 781                        ARIZONA_OUT3R_ANC_SRC_SHIFT,
 782                        ARRAY_SIZE(arizona_output_anc_src_text),
 783                        arizona_output_anc_src_text),
 784        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4L,
 785                        ARIZONA_OUT4L_ANC_SRC_SHIFT,
 786                        ARRAY_SIZE(arizona_output_anc_src_text),
 787                        arizona_output_anc_src_text),
 788        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_4R,
 789                        ARIZONA_OUT4R_ANC_SRC_SHIFT,
 790                        ARRAY_SIZE(arizona_output_anc_src_text),
 791                        arizona_output_anc_src_text),
 792        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5L,
 793                        ARIZONA_OUT5L_ANC_SRC_SHIFT,
 794                        ARRAY_SIZE(arizona_output_anc_src_text),
 795                        arizona_output_anc_src_text),
 796        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_5R,
 797                        ARIZONA_OUT5R_ANC_SRC_SHIFT,
 798                        ARRAY_SIZE(arizona_output_anc_src_text),
 799                        arizona_output_anc_src_text),
 800        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6L,
 801                        ARIZONA_OUT6L_ANC_SRC_SHIFT,
 802                        ARRAY_SIZE(arizona_output_anc_src_text),
 803                        arizona_output_anc_src_text),
 804        SOC_ENUM_SINGLE(ARIZONA_OUTPUT_PATH_CONFIG_6R,
 805                        ARIZONA_OUT6R_ANC_SRC_SHIFT,
 806                        ARRAY_SIZE(arizona_output_anc_src_text),
 807                        arizona_output_anc_src_text),
 808};
 809EXPORT_SYMBOL_GPL(arizona_output_anc_src);
 810
 811static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena)
 812{
 813        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 814        unsigned int val;
 815        int i;
 816
 817        if (ena)
 818                val = ARIZONA_IN_VU;
 819        else
 820                val = 0;
 821
 822        for (i = 0; i < priv->num_inputs; i++)
 823                snd_soc_update_bits(codec,
 824                                    ARIZONA_ADC_DIGITAL_VOLUME_1L + (i * 4),
 825                                    ARIZONA_IN_VU, val);
 826}
 827
 828bool arizona_input_analog(struct snd_soc_codec *codec, int shift)
 829{
 830        unsigned int reg = ARIZONA_IN1L_CONTROL + ((shift / 2) * 8);
 831        unsigned int val = snd_soc_read(codec, reg);
 832
 833        return !(val & ARIZONA_IN1_MODE_MASK);
 834}
 835EXPORT_SYMBOL_GPL(arizona_input_analog);
 836
 837int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
 838                  int event)
 839{
 840        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 841        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 842        unsigned int reg;
 843
 844        if (w->shift % 2)
 845                reg = ARIZONA_ADC_DIGITAL_VOLUME_1L + ((w->shift / 2) * 8);
 846        else
 847                reg = ARIZONA_ADC_DIGITAL_VOLUME_1R + ((w->shift / 2) * 8);
 848
 849        switch (event) {
 850        case SND_SOC_DAPM_PRE_PMU:
 851                priv->in_pending++;
 852                break;
 853        case SND_SOC_DAPM_POST_PMU:
 854                snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE, 0);
 855
 856                /* If this is the last input pending then allow VU */
 857                priv->in_pending--;
 858                if (priv->in_pending == 0) {
 859                        msleep(1);
 860                        arizona_in_set_vu(codec, 1);
 861                }
 862                break;
 863        case SND_SOC_DAPM_PRE_PMD:
 864                snd_soc_update_bits(codec, reg,
 865                                    ARIZONA_IN1L_MUTE | ARIZONA_IN_VU,
 866                                    ARIZONA_IN1L_MUTE | ARIZONA_IN_VU);
 867                break;
 868        case SND_SOC_DAPM_POST_PMD:
 869                /* Disable volume updates if no inputs are enabled */
 870                reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES);
 871                if (reg == 0)
 872                        arizona_in_set_vu(codec, 0);
 873                break;
 874        default:
 875                break;
 876        }
 877
 878        return 0;
 879}
 880EXPORT_SYMBOL_GPL(arizona_in_ev);
 881
 882int arizona_out_ev(struct snd_soc_dapm_widget *w,
 883                   struct snd_kcontrol *kcontrol,
 884                   int event)
 885{
 886        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 887        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 888
 889        switch (event) {
 890        case SND_SOC_DAPM_PRE_PMU:
 891                switch (w->shift) {
 892                case ARIZONA_OUT1L_ENA_SHIFT:
 893                case ARIZONA_OUT1R_ENA_SHIFT:
 894                case ARIZONA_OUT2L_ENA_SHIFT:
 895                case ARIZONA_OUT2R_ENA_SHIFT:
 896                case ARIZONA_OUT3L_ENA_SHIFT:
 897                case ARIZONA_OUT3R_ENA_SHIFT:
 898                        priv->out_up_pending++;
 899                        priv->out_up_delay += 17;
 900                        break;
 901                default:
 902                        break;
 903                }
 904                break;
 905        case SND_SOC_DAPM_POST_PMU:
 906                switch (w->shift) {
 907                case ARIZONA_OUT1L_ENA_SHIFT:
 908                case ARIZONA_OUT1R_ENA_SHIFT:
 909                case ARIZONA_OUT2L_ENA_SHIFT:
 910                case ARIZONA_OUT2R_ENA_SHIFT:
 911                case ARIZONA_OUT3L_ENA_SHIFT:
 912                case ARIZONA_OUT3R_ENA_SHIFT:
 913                        priv->out_up_pending--;
 914                        if (!priv->out_up_pending) {
 915                                msleep(priv->out_up_delay);
 916                                priv->out_up_delay = 0;
 917                        }
 918                        break;
 919
 920                default:
 921                        break;
 922                }
 923                break;
 924        case SND_SOC_DAPM_PRE_PMD:
 925                switch (w->shift) {
 926                case ARIZONA_OUT1L_ENA_SHIFT:
 927                case ARIZONA_OUT1R_ENA_SHIFT:
 928                case ARIZONA_OUT2L_ENA_SHIFT:
 929                case ARIZONA_OUT2R_ENA_SHIFT:
 930                case ARIZONA_OUT3L_ENA_SHIFT:
 931                case ARIZONA_OUT3R_ENA_SHIFT:
 932                        priv->out_down_pending++;
 933                        priv->out_down_delay++;
 934                        break;
 935                default:
 936                        break;
 937                }
 938                break;
 939        case SND_SOC_DAPM_POST_PMD:
 940                switch (w->shift) {
 941                case ARIZONA_OUT1L_ENA_SHIFT:
 942                case ARIZONA_OUT1R_ENA_SHIFT:
 943                case ARIZONA_OUT2L_ENA_SHIFT:
 944                case ARIZONA_OUT2R_ENA_SHIFT:
 945                case ARIZONA_OUT3L_ENA_SHIFT:
 946                case ARIZONA_OUT3R_ENA_SHIFT:
 947                        priv->out_down_pending--;
 948                        if (!priv->out_down_pending) {
 949                                msleep(priv->out_down_delay);
 950                                priv->out_down_delay = 0;
 951                        }
 952                        break;
 953                default:
 954                        break;
 955                }
 956                break;
 957        default:
 958                break;
 959        }
 960
 961        return 0;
 962}
 963EXPORT_SYMBOL_GPL(arizona_out_ev);
 964
 965int arizona_hp_ev(struct snd_soc_dapm_widget *w,
 966                   struct snd_kcontrol *kcontrol,
 967                   int event)
 968{
 969        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 970        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 971        struct arizona *arizona = priv->arizona;
 972        unsigned int mask = 1 << w->shift;
 973        unsigned int val;
 974
 975        switch (event) {
 976        case SND_SOC_DAPM_POST_PMU:
 977                val = mask;
 978                break;
 979        case SND_SOC_DAPM_PRE_PMD:
 980                val = 0;
 981                break;
 982        case SND_SOC_DAPM_PRE_PMU:
 983        case SND_SOC_DAPM_POST_PMD:
 984                return arizona_out_ev(w, kcontrol, event);
 985        default:
 986                return -EINVAL;
 987        }
 988
 989        /* Store the desired state for the HP outputs */
 990        priv->arizona->hp_ena &= ~mask;
 991        priv->arizona->hp_ena |= val;
 992
 993        /* Force off if HPDET clamp is active */
 994        if (priv->arizona->hpdet_clamp)
 995                val = 0;
 996
 997        regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,
 998                                 mask, val);
 999
1000        return arizona_out_ev(w, kcontrol, event);
1001}
1002EXPORT_SYMBOL_GPL(arizona_hp_ev);
1003
1004static int arizona_dvfs_enable(struct snd_soc_codec *codec)
1005{
1006        const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1007        struct arizona *arizona = priv->arizona;
1008        int ret;
1009
1010        ret = regulator_set_voltage(arizona->dcvdd, 1800000, 1800000);
1011        if (ret) {
1012                dev_err(codec->dev, "Failed to boost DCVDD: %d\n", ret);
1013                return ret;
1014        }
1015
1016        ret = regmap_update_bits(arizona->regmap,
1017                                 ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
1018                                 ARIZONA_SUBSYS_MAX_FREQ,
1019                                 ARIZONA_SUBSYS_MAX_FREQ);
1020        if (ret) {
1021                dev_err(codec->dev, "Failed to enable subsys max: %d\n", ret);
1022                regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
1023                return ret;
1024        }
1025
1026        return 0;
1027}
1028
1029static int arizona_dvfs_disable(struct snd_soc_codec *codec)
1030{
1031        const struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1032        struct arizona *arizona = priv->arizona;
1033        int ret;
1034
1035        ret = regmap_update_bits(arizona->regmap,
1036                                 ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
1037                                 ARIZONA_SUBSYS_MAX_FREQ, 0);
1038        if (ret) {
1039                dev_err(codec->dev, "Failed to disable subsys max: %d\n", ret);
1040                return ret;
1041        }
1042
1043        ret = regulator_set_voltage(arizona->dcvdd, 1200000, 1800000);
1044        if (ret) {
1045                dev_err(codec->dev, "Failed to unboost DCVDD: %d\n", ret);
1046                return ret;
1047        }
1048
1049        return 0;
1050}
1051
1052int arizona_dvfs_up(struct snd_soc_codec *codec, unsigned int flags)
1053{
1054        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1055        int ret = 0;
1056
1057        mutex_lock(&priv->dvfs_lock);
1058
1059        if (!priv->dvfs_cached && !priv->dvfs_reqs) {
1060                ret = arizona_dvfs_enable(codec);
1061                if (ret)
1062                        goto err;
1063        }
1064
1065        priv->dvfs_reqs |= flags;
1066err:
1067        mutex_unlock(&priv->dvfs_lock);
1068        return ret;
1069}
1070EXPORT_SYMBOL_GPL(arizona_dvfs_up);
1071
1072int arizona_dvfs_down(struct snd_soc_codec *codec, unsigned int flags)
1073{
1074        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1075        unsigned int old_reqs;
1076        int ret = 0;
1077
1078        mutex_lock(&priv->dvfs_lock);
1079
1080        old_reqs = priv->dvfs_reqs;
1081        priv->dvfs_reqs &= ~flags;
1082
1083        if (!priv->dvfs_cached && old_reqs && !priv->dvfs_reqs)
1084                ret = arizona_dvfs_disable(codec);
1085
1086        mutex_unlock(&priv->dvfs_lock);
1087        return ret;
1088}
1089EXPORT_SYMBOL_GPL(arizona_dvfs_down);
1090
1091int arizona_dvfs_sysclk_ev(struct snd_soc_dapm_widget *w,
1092                           struct snd_kcontrol *kcontrol, int event)
1093{
1094        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1095        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1096        int ret = 0;
1097
1098        mutex_lock(&priv->dvfs_lock);
1099
1100        switch (event) {
1101        case SND_SOC_DAPM_POST_PMU:
1102                if (priv->dvfs_reqs)
1103                        ret = arizona_dvfs_enable(codec);
1104
1105                priv->dvfs_cached = false;
1106                break;
1107        case SND_SOC_DAPM_PRE_PMD:
1108                /* We must ensure DVFS is disabled before the codec goes into
1109                 * suspend so that we are never in an illegal state of DVFS
1110                 * enabled without enough DCVDD
1111                 */
1112                priv->dvfs_cached = true;
1113
1114                if (priv->dvfs_reqs)
1115                        ret = arizona_dvfs_disable(codec);
1116                break;
1117        default:
1118                break;
1119        }
1120
1121        mutex_unlock(&priv->dvfs_lock);
1122        return ret;
1123}
1124EXPORT_SYMBOL_GPL(arizona_dvfs_sysclk_ev);
1125
1126void arizona_init_dvfs(struct arizona_priv *priv)
1127{
1128        mutex_init(&priv->dvfs_lock);
1129}
1130EXPORT_SYMBOL_GPL(arizona_init_dvfs);
1131
1132int arizona_anc_ev(struct snd_soc_dapm_widget *w,
1133                   struct snd_kcontrol *kcontrol,
1134                   int event)
1135{
1136        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
1137        unsigned int mask = 0x3 << w->shift;
1138        unsigned int val;
1139
1140        switch (event) {
1141        case SND_SOC_DAPM_POST_PMU:
1142                val = 1 << w->shift;
1143                break;
1144        case SND_SOC_DAPM_PRE_PMD:
1145                val = 1 << (w->shift + 1);
1146                break;
1147        default:
1148                return 0;
1149        }
1150
1151        snd_soc_update_bits(codec, ARIZONA_CLOCK_CONTROL, mask, val);
1152
1153        return 0;
1154}
1155EXPORT_SYMBOL_GPL(arizona_anc_ev);
1156
1157static unsigned int arizona_opclk_ref_48k_rates[] = {
1158        6144000,
1159        12288000,
1160        24576000,
1161        49152000,
1162};
1163
1164static unsigned int arizona_opclk_ref_44k1_rates[] = {
1165        5644800,
1166        11289600,
1167        22579200,
1168        45158400,
1169};
1170
1171static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk,
1172                             unsigned int freq)
1173{
1174        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1175        unsigned int reg;
1176        unsigned int *rates;
1177        int ref, div, refclk;
1178
1179        switch (clk) {
1180        case ARIZONA_CLK_OPCLK:
1181                reg = ARIZONA_OUTPUT_SYSTEM_CLOCK;
1182                refclk = priv->sysclk;
1183                break;
1184        case ARIZONA_CLK_ASYNC_OPCLK:
1185                reg = ARIZONA_OUTPUT_ASYNC_CLOCK;
1186                refclk = priv->asyncclk;
1187                break;
1188        default:
1189                return -EINVAL;
1190        }
1191
1192        if (refclk % 8000)
1193                rates = arizona_opclk_ref_44k1_rates;
1194        else
1195                rates = arizona_opclk_ref_48k_rates;
1196
1197        for (ref = 0; ref < ARRAY_SIZE(arizona_opclk_ref_48k_rates) &&
1198                     rates[ref] <= refclk; ref++) {
1199                div = 1;
1200                while (rates[ref] / div >= freq && div < 32) {
1201                        if (rates[ref] / div == freq) {
1202                                dev_dbg(codec->dev, "Configured %dHz OPCLK\n",
1203                                        freq);
1204                                snd_soc_update_bits(codec, reg,
1205                                                    ARIZONA_OPCLK_DIV_MASK |
1206                                                    ARIZONA_OPCLK_SEL_MASK,
1207                                                    (div <<
1208                                                     ARIZONA_OPCLK_DIV_SHIFT) |
1209                                                    ref);
1210                                return 0;
1211                        }
1212                        div++;
1213                }
1214        }
1215
1216        dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq);
1217        return -EINVAL;
1218}
1219
1220int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
1221                       int source, unsigned int freq, int dir)
1222{
1223        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1224        struct arizona *arizona = priv->arizona;
1225        char *name;
1226        unsigned int reg;
1227        unsigned int mask = ARIZONA_SYSCLK_FREQ_MASK | ARIZONA_SYSCLK_SRC_MASK;
1228        unsigned int val = source << ARIZONA_SYSCLK_SRC_SHIFT;
1229        int *clk;
1230
1231        switch (clk_id) {
1232        case ARIZONA_CLK_SYSCLK:
1233                name = "SYSCLK";
1234                reg = ARIZONA_SYSTEM_CLOCK_1;
1235                clk = &priv->sysclk;
1236                mask |= ARIZONA_SYSCLK_FRAC;
1237                break;
1238        case ARIZONA_CLK_ASYNCCLK:
1239                name = "ASYNCCLK";
1240                reg = ARIZONA_ASYNC_CLOCK_1;
1241                clk = &priv->asyncclk;
1242                break;
1243        case ARIZONA_CLK_OPCLK:
1244        case ARIZONA_CLK_ASYNC_OPCLK:
1245                return arizona_set_opclk(codec, clk_id, freq);
1246        default:
1247                return -EINVAL;
1248        }
1249
1250        switch (freq) {
1251        case  5644800:
1252        case  6144000:
1253                break;
1254        case 11289600:
1255        case 12288000:
1256                val |= ARIZONA_CLK_12MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1257                break;
1258        case 22579200:
1259        case 24576000:
1260                val |= ARIZONA_CLK_24MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1261                break;
1262        case 45158400:
1263        case 49152000:
1264                val |= ARIZONA_CLK_49MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1265                break;
1266        case 67737600:
1267        case 73728000:
1268                val |= ARIZONA_CLK_73MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1269                break;
1270        case 90316800:
1271        case 98304000:
1272                val |= ARIZONA_CLK_98MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1273                break;
1274        case 135475200:
1275        case 147456000:
1276                val |= ARIZONA_CLK_147MHZ << ARIZONA_SYSCLK_FREQ_SHIFT;
1277                break;
1278        case 0:
1279                dev_dbg(arizona->dev, "%s cleared\n", name);
1280                *clk = freq;
1281                return 0;
1282        default:
1283                return -EINVAL;
1284        }
1285
1286        *clk = freq;
1287
1288        if (freq % 6144000)
1289                val |= ARIZONA_SYSCLK_FRAC;
1290
1291        dev_dbg(arizona->dev, "%s set to %uHz", name, freq);
1292
1293        return regmap_update_bits(arizona->regmap, reg, mask, val);
1294}
1295EXPORT_SYMBOL_GPL(arizona_set_sysclk);
1296
1297static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1298{
1299        struct snd_soc_codec *codec = dai->codec;
1300        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1301        struct arizona *arizona = priv->arizona;
1302        int lrclk, bclk, mode, base;
1303
1304        base = dai->driver->base;
1305
1306        lrclk = 0;
1307        bclk = 0;
1308
1309        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1310        case SND_SOC_DAIFMT_DSP_A:
1311                mode = ARIZONA_FMT_DSP_MODE_A;
1312                break;
1313        case SND_SOC_DAIFMT_DSP_B:
1314                if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1315                                != SND_SOC_DAIFMT_CBM_CFM) {
1316                        arizona_aif_err(dai, "DSP_B not valid in slave mode\n");
1317                        return -EINVAL;
1318                }
1319                mode = ARIZONA_FMT_DSP_MODE_B;
1320                break;
1321        case SND_SOC_DAIFMT_I2S:
1322                mode = ARIZONA_FMT_I2S_MODE;
1323                break;
1324        case SND_SOC_DAIFMT_LEFT_J:
1325                if ((fmt & SND_SOC_DAIFMT_MASTER_MASK)
1326                                != SND_SOC_DAIFMT_CBM_CFM) {
1327                        arizona_aif_err(dai, "LEFT_J not valid in slave mode\n");
1328                        return -EINVAL;
1329                }
1330                mode = ARIZONA_FMT_LEFT_JUSTIFIED_MODE;
1331                break;
1332        default:
1333                arizona_aif_err(dai, "Unsupported DAI format %d\n",
1334                                fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1335                return -EINVAL;
1336        }
1337
1338        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1339        case SND_SOC_DAIFMT_CBS_CFS:
1340                break;
1341        case SND_SOC_DAIFMT_CBS_CFM:
1342                lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1343                break;
1344        case SND_SOC_DAIFMT_CBM_CFS:
1345                bclk |= ARIZONA_AIF1_BCLK_MSTR;
1346                break;
1347        case SND_SOC_DAIFMT_CBM_CFM:
1348                bclk |= ARIZONA_AIF1_BCLK_MSTR;
1349                lrclk |= ARIZONA_AIF1TX_LRCLK_MSTR;
1350                break;
1351        default:
1352                arizona_aif_err(dai, "Unsupported master mode %d\n",
1353                                fmt & SND_SOC_DAIFMT_MASTER_MASK);
1354                return -EINVAL;
1355        }
1356
1357        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1358        case SND_SOC_DAIFMT_NB_NF:
1359                break;
1360        case SND_SOC_DAIFMT_IB_IF:
1361                bclk |= ARIZONA_AIF1_BCLK_INV;
1362                lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1363                break;
1364        case SND_SOC_DAIFMT_IB_NF:
1365                bclk |= ARIZONA_AIF1_BCLK_INV;
1366                break;
1367        case SND_SOC_DAIFMT_NB_IF:
1368                lrclk |= ARIZONA_AIF1TX_LRCLK_INV;
1369                break;
1370        default:
1371                return -EINVAL;
1372        }
1373
1374        regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL,
1375                                 ARIZONA_AIF1_BCLK_INV |
1376                                 ARIZONA_AIF1_BCLK_MSTR,
1377                                 bclk);
1378        regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL,
1379                                 ARIZONA_AIF1TX_LRCLK_INV |
1380                                 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
1381        regmap_update_bits_async(arizona->regmap,
1382                                 base + ARIZONA_AIF_RX_PIN_CTRL,
1383                                 ARIZONA_AIF1RX_LRCLK_INV |
1384                                 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
1385        regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT,
1386                           ARIZONA_AIF1_FMT_MASK, mode);
1387
1388        return 0;
1389}
1390
1391static const int arizona_48k_bclk_rates[] = {
1392        -1,
1393        48000,
1394        64000,
1395        96000,
1396        128000,
1397        192000,
1398        256000,
1399        384000,
1400        512000,
1401        768000,
1402        1024000,
1403        1536000,
1404        2048000,
1405        3072000,
1406        4096000,
1407        6144000,
1408        8192000,
1409        12288000,
1410        24576000,
1411};
1412
1413static const int arizona_44k1_bclk_rates[] = {
1414        -1,
1415        44100,
1416        58800,
1417        88200,
1418        117600,
1419        177640,
1420        235200,
1421        352800,
1422        470400,
1423        705600,
1424        940800,
1425        1411200,
1426        1881600,
1427        2822400,
1428        3763200,
1429        5644800,
1430        7526400,
1431        11289600,
1432        22579200,
1433};
1434
1435static const unsigned int arizona_sr_vals[] = {
1436        0,
1437        12000,
1438        24000,
1439        48000,
1440        96000,
1441        192000,
1442        384000,
1443        768000,
1444        0,
1445        11025,
1446        22050,
1447        44100,
1448        88200,
1449        176400,
1450        352800,
1451        705600,
1452        4000,
1453        8000,
1454        16000,
1455        32000,
1456        64000,
1457        128000,
1458        256000,
1459        512000,
1460};
1461
1462#define ARIZONA_48K_RATE_MASK   0x0F003E
1463#define ARIZONA_44K1_RATE_MASK  0x003E00
1464#define ARIZONA_RATE_MASK       (ARIZONA_48K_RATE_MASK | ARIZONA_44K1_RATE_MASK)
1465
1466static const struct snd_pcm_hw_constraint_list arizona_constraint = {
1467        .count  = ARRAY_SIZE(arizona_sr_vals),
1468        .list   = arizona_sr_vals,
1469};
1470
1471static int arizona_startup(struct snd_pcm_substream *substream,
1472                           struct snd_soc_dai *dai)
1473{
1474        struct snd_soc_codec *codec = dai->codec;
1475        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1476        struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1477        unsigned int base_rate;
1478
1479        if (!substream->runtime)
1480                return 0;
1481
1482        switch (dai_priv->clk) {
1483        case ARIZONA_CLK_SYSCLK:
1484                base_rate = priv->sysclk;
1485                break;
1486        case ARIZONA_CLK_ASYNCCLK:
1487                base_rate = priv->asyncclk;
1488                break;
1489        default:
1490                return 0;
1491        }
1492
1493        if (base_rate == 0)
1494                dai_priv->constraint.mask = ARIZONA_RATE_MASK;
1495        else if (base_rate % 8000)
1496                dai_priv->constraint.mask = ARIZONA_44K1_RATE_MASK;
1497        else
1498                dai_priv->constraint.mask = ARIZONA_48K_RATE_MASK;
1499
1500        return snd_pcm_hw_constraint_list(substream->runtime, 0,
1501                                          SNDRV_PCM_HW_PARAM_RATE,
1502                                          &dai_priv->constraint);
1503}
1504
1505static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
1506                                        unsigned int rate)
1507{
1508        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1509        struct arizona *arizona = priv->arizona;
1510        struct reg_sequence dac_comp[] = {
1511                { 0x80, 0x3 },
1512                { ARIZONA_DAC_COMP_1, 0 },
1513                { ARIZONA_DAC_COMP_2, 0 },
1514                { 0x80, 0x0 },
1515        };
1516
1517        mutex_lock(&arizona->dac_comp_lock);
1518
1519        dac_comp[1].def = arizona->dac_comp_coeff;
1520        if (rate >= 176400)
1521                dac_comp[2].def = arizona->dac_comp_enabled;
1522
1523        mutex_unlock(&arizona->dac_comp_lock);
1524
1525        regmap_multi_reg_write(arizona->regmap,
1526                               dac_comp,
1527                               ARRAY_SIZE(dac_comp));
1528}
1529
1530static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
1531                                  struct snd_pcm_hw_params *params,
1532                                  struct snd_soc_dai *dai)
1533{
1534        struct snd_soc_codec *codec = dai->codec;
1535        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1536        struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1537        int base = dai->driver->base;
1538        int i, sr_val, ret;
1539
1540        /*
1541         * We will need to be more flexible than this in future,
1542         * currently we use a single sample rate for SYSCLK.
1543         */
1544        for (i = 0; i < ARRAY_SIZE(arizona_sr_vals); i++)
1545                if (arizona_sr_vals[i] == params_rate(params))
1546                        break;
1547        if (i == ARRAY_SIZE(arizona_sr_vals)) {
1548                arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1549                                params_rate(params));
1550                return -EINVAL;
1551        }
1552        sr_val = i;
1553
1554        switch (priv->arizona->type) {
1555        case WM5102:
1556        case WM8997:
1557                if (arizona_sr_vals[sr_val] >= 88200)
1558                        ret = arizona_dvfs_up(codec, ARIZONA_DVFS_SR1_RQ);
1559                else
1560                        ret = arizona_dvfs_down(codec, ARIZONA_DVFS_SR1_RQ);
1561
1562                if (ret) {
1563                        arizona_aif_err(dai, "Failed to change DVFS %d\n", ret);
1564                        return ret;
1565                }
1566                break;
1567        default:
1568                break;
1569        }
1570
1571        switch (dai_priv->clk) {
1572        case ARIZONA_CLK_SYSCLK:
1573                switch (priv->arizona->type) {
1574                case WM5102:
1575                        arizona_wm5102_set_dac_comp(codec,
1576                                                    params_rate(params));
1577                        break;
1578                default:
1579                        break;
1580                }
1581
1582                snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
1583                                    ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
1584                if (base)
1585                        snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1586                                            ARIZONA_AIF1_RATE_MASK, 0);
1587                break;
1588        case ARIZONA_CLK_ASYNCCLK:
1589                snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
1590                                    ARIZONA_ASYNC_SAMPLE_RATE_1_MASK, sr_val);
1591                if (base)
1592                        snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1593                                            ARIZONA_AIF1_RATE_MASK,
1594                                            8 << ARIZONA_AIF1_RATE_SHIFT);
1595                break;
1596        default:
1597                arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
1598                return -EINVAL;
1599        }
1600
1601        return 0;
1602}
1603
1604static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
1605                                    int base, int bclk, int lrclk, int frame)
1606{
1607        int val;
1608
1609        val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
1610        if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
1611                return true;
1612
1613        val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
1614        if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
1615                return true;
1616
1617        val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
1618        if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
1619                             ARIZONA_AIF1TX_SLOT_LEN_MASK)))
1620                return true;
1621
1622        return false;
1623}
1624
1625static int arizona_hw_params(struct snd_pcm_substream *substream,
1626                             struct snd_pcm_hw_params *params,
1627                             struct snd_soc_dai *dai)
1628{
1629        struct snd_soc_codec *codec = dai->codec;
1630        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1631        struct arizona *arizona = priv->arizona;
1632        int base = dai->driver->base;
1633        const int *rates;
1634        int i, ret, val;
1635        int channels = params_channels(params);
1636        int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
1637        int tdm_width = arizona->tdm_width[dai->id - 1];
1638        int tdm_slots = arizona->tdm_slots[dai->id - 1];
1639        int bclk, lrclk, wl, frame, bclk_target;
1640        bool reconfig;
1641        unsigned int aif_tx_state, aif_rx_state;
1642
1643        if (params_rate(params) % 4000)
1644                rates = &arizona_44k1_bclk_rates[0];
1645        else
1646                rates = &arizona_48k_bclk_rates[0];
1647
1648        wl = params_width(params);
1649
1650        if (tdm_slots) {
1651                arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
1652                                tdm_slots, tdm_width);
1653                bclk_target = tdm_slots * tdm_width * params_rate(params);
1654                channels = tdm_slots;
1655        } else {
1656                bclk_target = snd_soc_params_to_bclk(params);
1657                tdm_width = wl;
1658        }
1659
1660        if (chan_limit && chan_limit < channels) {
1661                arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
1662                bclk_target /= channels;
1663                bclk_target *= chan_limit;
1664        }
1665
1666        /* Force multiple of 2 channels for I2S mode */
1667        val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
1668        val &= ARIZONA_AIF1_FMT_MASK;
1669        if ((channels & 1) && (val == ARIZONA_FMT_I2S_MODE)) {
1670                arizona_aif_dbg(dai, "Forcing stereo mode\n");
1671                bclk_target /= channels;
1672                bclk_target *= channels + 1;
1673        }
1674
1675        for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
1676                if (rates[i] >= bclk_target &&
1677                    rates[i] % params_rate(params) == 0) {
1678                        bclk = i;
1679                        break;
1680                }
1681        }
1682        if (i == ARRAY_SIZE(arizona_44k1_bclk_rates)) {
1683                arizona_aif_err(dai, "Unsupported sample rate %dHz\n",
1684                                params_rate(params));
1685                return -EINVAL;
1686        }
1687
1688        lrclk = rates[bclk] / params_rate(params);
1689
1690        arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
1691                        rates[bclk], rates[bclk] / lrclk);
1692
1693        frame = wl << ARIZONA_AIF1TX_WL_SHIFT | tdm_width;
1694
1695        reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
1696
1697        if (reconfig) {
1698                /* Save AIF TX/RX state */
1699                aif_tx_state = snd_soc_read(codec,
1700                                            base + ARIZONA_AIF_TX_ENABLES);
1701                aif_rx_state = snd_soc_read(codec,
1702                                            base + ARIZONA_AIF_RX_ENABLES);
1703                /* Disable AIF TX/RX before reconfiguring it */
1704                regmap_update_bits_async(arizona->regmap,
1705                                    base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
1706                regmap_update_bits(arizona->regmap,
1707                                    base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
1708        }
1709
1710        ret = arizona_hw_params_rate(substream, params, dai);
1711        if (ret != 0)
1712                goto restore_aif;
1713
1714        if (reconfig) {
1715                regmap_update_bits_async(arizona->regmap,
1716                                         base + ARIZONA_AIF_BCLK_CTRL,
1717                                         ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
1718                regmap_update_bits_async(arizona->regmap,
1719                                         base + ARIZONA_AIF_TX_BCLK_RATE,
1720                                         ARIZONA_AIF1TX_BCPF_MASK, lrclk);
1721                regmap_update_bits_async(arizona->regmap,
1722                                         base + ARIZONA_AIF_RX_BCLK_RATE,
1723                                         ARIZONA_AIF1RX_BCPF_MASK, lrclk);
1724                regmap_update_bits_async(arizona->regmap,
1725                                         base + ARIZONA_AIF_FRAME_CTRL_1,
1726                                         ARIZONA_AIF1TX_WL_MASK |
1727                                         ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
1728                regmap_update_bits(arizona->regmap,
1729                                   base + ARIZONA_AIF_FRAME_CTRL_2,
1730                                   ARIZONA_AIF1RX_WL_MASK |
1731                                   ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
1732        }
1733
1734restore_aif:
1735        if (reconfig) {
1736                /* Restore AIF TX/RX state */
1737                regmap_update_bits_async(arizona->regmap,
1738                                         base + ARIZONA_AIF_TX_ENABLES,
1739                                         0xff, aif_tx_state);
1740                regmap_update_bits(arizona->regmap,
1741                                   base + ARIZONA_AIF_RX_ENABLES,
1742                                   0xff, aif_rx_state);
1743        }
1744        return ret;
1745}
1746
1747static const char *arizona_dai_clk_str(int clk_id)
1748{
1749        switch (clk_id) {
1750        case ARIZONA_CLK_SYSCLK:
1751                return "SYSCLK";
1752        case ARIZONA_CLK_ASYNCCLK:
1753                return "ASYNCCLK";
1754        default:
1755                return "Unknown clock";
1756        }
1757}
1758
1759static int arizona_dai_set_sysclk(struct snd_soc_dai *dai,
1760                                  int clk_id, unsigned int freq, int dir)
1761{
1762        struct snd_soc_codec *codec = dai->codec;
1763        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
1764        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1765        struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1];
1766        struct snd_soc_dapm_route routes[2];
1767
1768        switch (clk_id) {
1769        case ARIZONA_CLK_SYSCLK:
1770        case ARIZONA_CLK_ASYNCCLK:
1771                break;
1772        default:
1773                return -EINVAL;
1774        }
1775
1776        if (clk_id == dai_priv->clk)
1777                return 0;
1778
1779        if (dai->active) {
1780                dev_err(codec->dev, "Can't change clock on active DAI %d\n",
1781                        dai->id);
1782                return -EBUSY;
1783        }
1784
1785        dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1,
1786                arizona_dai_clk_str(clk_id));
1787
1788        memset(&routes, 0, sizeof(routes));
1789        routes[0].sink = dai->driver->capture.stream_name;
1790        routes[1].sink = dai->driver->playback.stream_name;
1791
1792        routes[0].source = arizona_dai_clk_str(dai_priv->clk);
1793        routes[1].source = arizona_dai_clk_str(dai_priv->clk);
1794        snd_soc_dapm_del_routes(dapm, routes, ARRAY_SIZE(routes));
1795
1796        routes[0].source = arizona_dai_clk_str(clk_id);
1797        routes[1].source = arizona_dai_clk_str(clk_id);
1798        snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
1799
1800        dai_priv->clk = clk_id;
1801
1802        return snd_soc_dapm_sync(dapm);
1803}
1804
1805static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
1806{
1807        struct snd_soc_codec *codec = dai->codec;
1808        int base = dai->driver->base;
1809        unsigned int reg;
1810
1811        if (tristate)
1812                reg = ARIZONA_AIF1_TRI;
1813        else
1814                reg = 0;
1815
1816        return snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
1817                                   ARIZONA_AIF1_TRI, reg);
1818}
1819
1820static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
1821                                         unsigned int base,
1822                                         int channels, unsigned int mask)
1823{
1824        struct snd_soc_codec *codec = dai->codec;
1825        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1826        struct arizona *arizona = priv->arizona;
1827        int slot, i;
1828
1829        for (i = 0; i < channels; ++i) {
1830                slot = ffs(mask) - 1;
1831                if (slot < 0)
1832                        return;
1833
1834                regmap_write(arizona->regmap, base + i, slot);
1835
1836                mask &= ~(1 << slot);
1837        }
1838
1839        if (mask)
1840                arizona_aif_warn(dai, "Too many channels in TDM mask\n");
1841}
1842
1843static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
1844                                unsigned int rx_mask, int slots, int slot_width)
1845{
1846        struct snd_soc_codec *codec = dai->codec;
1847        struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
1848        struct arizona *arizona = priv->arizona;
1849        int base = dai->driver->base;
1850        int rx_max_chan = dai->driver->playback.channels_max;
1851        int tx_max_chan = dai->driver->capture.channels_max;
1852
1853        /* Only support TDM for the physical AIFs */
1854        if (dai->id > ARIZONA_MAX_AIF)
1855                return -ENOTSUPP;
1856
1857        if (slots == 0) {
1858                tx_mask = (1 << tx_max_chan) - 1;
1859                rx_mask = (1 << rx_max_chan) - 1;
1860        }
1861
1862        arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
1863                                     tx_max_chan, tx_mask);
1864        arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
1865                                     rx_max_chan, rx_mask);
1866
1867        arizona->tdm_width[dai->id - 1] = slot_width;
1868        arizona->tdm_slots[dai->id - 1] = slots;
1869
1870        return 0;
1871}
1872
1873const struct snd_soc_dai_ops arizona_dai_ops = {
1874        .startup = arizona_startup,
1875        .set_fmt = arizona_set_fmt,
1876        .set_tdm_slot = arizona_set_tdm_slot,
1877        .hw_params = arizona_hw_params,
1878        .set_sysclk = arizona_dai_set_sysclk,
1879        .set_tristate = arizona_set_tristate,
1880};
1881EXPORT_SYMBOL_GPL(arizona_dai_ops);
1882
1883const struct snd_soc_dai_ops arizona_simple_dai_ops = {
1884        .startup = arizona_startup,
1885        .hw_params = arizona_hw_params_rate,
1886        .set_sysclk = arizona_dai_set_sysclk,
1887};
1888EXPORT_SYMBOL_GPL(arizona_simple_dai_ops);
1889
1890int arizona_init_dai(struct arizona_priv *priv, int id)
1891{
1892        struct arizona_dai_priv *dai_priv = &priv->dai[id];
1893
1894        dai_priv->clk = ARIZONA_CLK_SYSCLK;
1895        dai_priv->constraint = arizona_constraint;
1896
1897        return 0;
1898}
1899EXPORT_SYMBOL_GPL(arizona_init_dai);
1900
1901static struct {
1902        unsigned int min;
1903        unsigned int max;
1904        u16 fratio;
1905        int ratio;
1906} fll_fratios[] = {
1907        {       0,    64000, 4, 16 },
1908        {   64000,   128000, 3,  8 },
1909        {  128000,   256000, 2,  4 },
1910        {  256000,  1000000, 1,  2 },
1911        { 1000000, 13500000, 0,  1 },
1912};
1913
1914static const unsigned int pseudo_fref_max[ARIZONA_FLL_MAX_FRATIO] = {
1915        13500000,
1916         6144000,
1917         6144000,
1918         3072000,
1919         3072000,
1920         2822400,
1921         2822400,
1922         1536000,
1923         1536000,
1924         1536000,
1925         1536000,
1926         1536000,
1927         1536000,
1928         1536000,
1929         1536000,
1930          768000,
1931};
1932
1933static struct {
1934        unsigned int min;
1935        unsigned int max;
1936        u16 gain;
1937} fll_gains[] = {
1938        {       0,   256000, 0 },
1939        {  256000,  1000000, 2 },
1940        { 1000000, 13500000, 4 },
1941};
1942
1943struct arizona_fll_cfg {
1944        int n;
1945        int theta;
1946        int lambda;
1947        int refdiv;
1948        int outdiv;
1949        int fratio;
1950        int gain;
1951};
1952
1953static int arizona_validate_fll(struct arizona_fll *fll,
1954                                unsigned int Fref,
1955                                unsigned int Fout)
1956{
1957        unsigned int Fvco_min;
1958
1959        if (fll->fout && Fout != fll->fout) {
1960                arizona_fll_err(fll,
1961                                "Can't change output on active FLL\n");
1962                return -EINVAL;
1963        }
1964
1965        if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
1966                arizona_fll_err(fll,
1967                                "Can't scale %dMHz in to <=13.5MHz\n",
1968                                Fref);
1969                return -EINVAL;
1970        }
1971
1972        Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
1973        if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
1974                arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1975                                Fout);
1976                return -EINVAL;
1977        }
1978
1979        return 0;
1980}
1981
1982static int arizona_find_fratio(unsigned int Fref, int *fratio)
1983{
1984        int i;
1985
1986        /* Find an appropriate FLL_FRATIO */
1987        for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
1988                if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
1989                        if (fratio)
1990                                *fratio = fll_fratios[i].fratio;
1991                        return fll_fratios[i].ratio;
1992                }
1993        }
1994
1995        return -EINVAL;
1996}
1997
1998static int arizona_calc_fratio(struct arizona_fll *fll,
1999                               struct arizona_fll_cfg *cfg,
2000                               unsigned int target,
2001                               unsigned int Fref, bool sync)
2002{
2003        int init_ratio, ratio;
2004        int refdiv, div;
2005
2006        /* Fref must be <=13.5MHz, find initial refdiv */
2007        div = 1;
2008        cfg->refdiv = 0;
2009        while (Fref > ARIZONA_FLL_MAX_FREF) {
2010                div *= 2;
2011                Fref /= 2;
2012                cfg->refdiv++;
2013
2014                if (div > ARIZONA_FLL_MAX_REFDIV)
2015                        return -EINVAL;
2016        }
2017
2018        /* Find an appropriate FLL_FRATIO */
2019        init_ratio = arizona_find_fratio(Fref, &cfg->fratio);
2020        if (init_ratio < 0) {
2021                arizona_fll_err(fll, "Unable to find FRATIO for Fref=%uHz\n",
2022                                Fref);
2023                return init_ratio;
2024        }
2025
2026        switch (fll->arizona->type) {
2027        case WM5102:
2028        case WM8997:
2029                return init_ratio;
2030        case WM5110:
2031        case WM8280:
2032                if (fll->arizona->rev < 3 || sync)
2033                        return init_ratio;
2034                break;
2035        default:
2036                if (sync)
2037                        return init_ratio;
2038                break;
2039        }
2040
2041        cfg->fratio = init_ratio - 1;
2042
2043        /* Adjust FRATIO/refdiv to avoid integer mode if possible */
2044        refdiv = cfg->refdiv;
2045
2046        arizona_fll_dbg(fll, "pseudo: initial ratio=%u fref=%u refdiv=%u\n",
2047                        init_ratio, Fref, refdiv);
2048
2049        while (div <= ARIZONA_FLL_MAX_REFDIV) {
2050                for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
2051                     ratio++) {
2052                        if ((ARIZONA_FLL_VCO_CORNER / 2) /
2053                            (fll->vco_mult * ratio) < Fref) {
2054                                arizona_fll_dbg(fll, "pseudo: hit VCO corner\n");
2055                                break;
2056                        }
2057
2058                        if (Fref > pseudo_fref_max[ratio - 1]) {
2059                                arizona_fll_dbg(fll,
2060                                        "pseudo: exceeded max fref(%u) for ratio=%u\n",
2061                                        pseudo_fref_max[ratio - 1],
2062                                        ratio);
2063                                break;
2064                        }
2065
2066                        if (target % (ratio * Fref)) {
2067                                cfg->refdiv = refdiv;
2068                                cfg->fratio = ratio - 1;
2069                                arizona_fll_dbg(fll,
2070                                        "pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n",
2071                                        Fref, refdiv, div, ratio);
2072                                return ratio;
2073                        }
2074                }
2075
2076                for (ratio = init_ratio - 1; ratio > 0; ratio--) {
2077                        if (target % (ratio * Fref)) {
2078                                cfg->refdiv = refdiv;
2079                                cfg->fratio = ratio - 1;
2080                                arizona_fll_dbg(fll,
2081                                        "pseudo: found fref=%u refdiv=%d(%d) ratio=%d\n",
2082                                        Fref, refdiv, div, ratio);
2083                                return ratio;
2084                        }
2085                }
2086
2087                div *= 2;
2088                Fref /= 2;
2089                refdiv++;
2090                init_ratio = arizona_find_fratio(Fref, NULL);
2091                arizona_fll_dbg(fll,
2092                                "pseudo: change fref=%u refdiv=%d(%d) ratio=%u\n",
2093                                Fref, refdiv, div, init_ratio);
2094        }
2095
2096        arizona_fll_warn(fll, "Falling back to integer mode operation\n");
2097        return cfg->fratio + 1;
2098}
2099
2100static int arizona_calc_fll(struct arizona_fll *fll,
2101                            struct arizona_fll_cfg *cfg,
2102                            unsigned int Fref, bool sync)
2103{
2104        unsigned int target, div, gcd_fll;
2105        int i, ratio;
2106
2107        arizona_fll_dbg(fll, "Fref=%u Fout=%u\n", Fref, fll->fout);
2108
2109        /* Fvco should be over the targt; don't check the upper bound */
2110        div = ARIZONA_FLL_MIN_OUTDIV;
2111        while (fll->fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
2112                div++;
2113                if (div > ARIZONA_FLL_MAX_OUTDIV)
2114                        return -EINVAL;
2115        }
2116        target = fll->fout * div / fll->vco_mult;
2117        cfg->outdiv = div;
2118
2119        arizona_fll_dbg(fll, "Fvco=%dHz\n", target);
2120
2121        /* Find an appropriate FLL_FRATIO and refdiv */
2122        ratio = arizona_calc_fratio(fll, cfg, target, Fref, sync);
2123        if (ratio < 0)
2124                return ratio;
2125
2126        /* Apply the division for our remaining calculations */
2127        Fref = Fref / (1 << cfg->refdiv);
2128
2129        cfg->n = target / (ratio * Fref);
2130
2131        if (target % (ratio * Fref)) {
2132                gcd_fll = gcd(target, ratio * Fref);
2133                arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
2134
2135                cfg->theta = (target - (cfg->n * ratio * Fref))
2136                        / gcd_fll;
2137                cfg->lambda = (ratio * Fref) / gcd_fll;
2138        } else {
2139                cfg->theta = 0;
2140                cfg->lambda = 0;
2141        }
2142
2143        /* Round down to 16bit range with cost of accuracy lost.
2144         * Denominator must be bigger than numerator so we only
2145         * take care of it.
2146         */
2147        while (cfg->lambda >= (1 << 16)) {
2148                cfg->theta >>= 1;
2149                cfg->lambda >>= 1;
2150        }
2151
2152        for (i = 0; i < ARRAY_SIZE(fll_gains); i++) {
2153                if (fll_gains[i].min <= Fref && Fref <= fll_gains[i].max) {
2154                        cfg->gain = fll_gains[i].gain;
2155                        break;
2156                }
2157        }
2158        if (i == ARRAY_SIZE(fll_gains)) {
2159                arizona_fll_err(fll, "Unable to find gain for Fref=%uHz\n",
2160                                Fref);
2161                return -EINVAL;
2162        }
2163
2164        arizona_fll_dbg(fll, "N=%d THETA=%d LAMBDA=%d\n",
2165                        cfg->n, cfg->theta, cfg->lambda);
2166        arizona_fll_dbg(fll, "FRATIO=0x%x(%d) OUTDIV=%d REFCLK_DIV=0x%x(%d)\n",
2167                        cfg->fratio, ratio, cfg->outdiv,
2168                        cfg->refdiv, 1 << cfg->refdiv);
2169        arizona_fll_dbg(fll, "GAIN=0x%x(%d)\n", cfg->gain, 1 << cfg->gain);
2170
2171        return 0;
2172
2173}
2174
2175static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
2176                              struct arizona_fll_cfg *cfg, int source,
2177                              bool sync)
2178{
2179        regmap_update_bits_async(arizona->regmap, base + 3,
2180                                 ARIZONA_FLL1_THETA_MASK, cfg->theta);
2181        regmap_update_bits_async(arizona->regmap, base + 4,
2182                                 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
2183        regmap_update_bits_async(arizona->regmap, base + 5,
2184                                 ARIZONA_FLL1_FRATIO_MASK,
2185                                 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
2186        regmap_update_bits_async(arizona->regmap, base + 6,
2187                                 ARIZONA_FLL1_CLK_REF_DIV_MASK |
2188                                 ARIZONA_FLL1_CLK_REF_SRC_MASK,
2189                                 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
2190                                 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);
2191
2192        if (sync) {
2193                regmap_update_bits(arizona->regmap, base + 0x7,
2194                                   ARIZONA_FLL1_GAIN_MASK,
2195                                   cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2196        } else {
2197                regmap_update_bits(arizona->regmap, base + 0x5,
2198                                   ARIZONA_FLL1_OUTDIV_MASK,
2199                                   cfg->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
2200                regmap_update_bits(arizona->regmap, base + 0x9,
2201                                   ARIZONA_FLL1_GAIN_MASK,
2202                                   cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
2203        }
2204
2205        regmap_update_bits_async(arizona->regmap, base + 2,
2206                                 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
2207                                 ARIZONA_FLL1_CTRL_UPD | cfg->n);
2208}
2209
2210static int arizona_is_enabled_fll(struct arizona_fll *fll)
2211{
2212        struct arizona *arizona = fll->arizona;
2213        unsigned int reg;
2214        int ret;
2215
2216        ret = regmap_read(arizona->regmap, fll->base + 1, &reg);
2217        if (ret != 0) {
2218                arizona_fll_err(fll, "Failed to read current state: %d\n",
2219                                ret);
2220                return ret;
2221        }
2222
2223        return reg & ARIZONA_FLL1_ENA;
2224}
2225
2226static int arizona_enable_fll(struct arizona_fll *fll)
2227{
2228        struct arizona *arizona = fll->arizona;
2229        bool use_sync = false;
2230        int already_enabled = arizona_is_enabled_fll(fll);
2231        struct arizona_fll_cfg cfg;
2232        int i;
2233        unsigned int val;
2234
2235        if (already_enabled < 0)
2236                return already_enabled;
2237
2238        if (already_enabled) {
2239                /* Facilitate smooth refclk across the transition */
2240                regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9,
2241                                         ARIZONA_FLL1_GAIN_MASK, 0);
2242                regmap_update_bits(fll->arizona->regmap, fll->base + 1,
2243                                   ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
2244                udelay(32);
2245        }
2246
2247        /*
2248         * If we have both REFCLK and SYNCCLK then enable both,
2249         * otherwise apply the SYNCCLK settings to REFCLK.
2250         */
2251        if (fll->ref_src >= 0 && fll->ref_freq &&
2252            fll->ref_src != fll->sync_src) {
2253                arizona_calc_fll(fll, &cfg, fll->ref_freq, false);
2254
2255                arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
2256                                  false);
2257                if (fll->sync_src >= 0) {
2258                        arizona_calc_fll(fll, &cfg, fll->sync_freq, true);
2259
2260                        arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
2261                                          fll->sync_src, true);
2262                        use_sync = true;
2263                }
2264        } else if (fll->sync_src >= 0) {
2265                arizona_calc_fll(fll, &cfg, fll->sync_freq, false);
2266
2267                arizona_apply_fll(arizona, fll->base, &cfg,
2268                                  fll->sync_src, false);
2269
2270                regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2271                                         ARIZONA_FLL1_SYNC_ENA, 0);
2272        } else {
2273                arizona_fll_err(fll, "No clocks provided\n");
2274                return -EINVAL;
2275        }
2276
2277        /*
2278         * Increase the bandwidth if we're not using a low frequency
2279         * sync source.
2280         */
2281        if (use_sync && fll->sync_freq > 100000)
2282                regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2283                                         ARIZONA_FLL1_SYNC_BW, 0);
2284        else
2285                regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
2286                                         ARIZONA_FLL1_SYNC_BW,
2287                                         ARIZONA_FLL1_SYNC_BW);
2288
2289        if (!already_enabled)
2290                pm_runtime_get(arizona->dev);
2291
2292        regmap_update_bits_async(arizona->regmap, fll->base + 1,
2293                                 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
2294        if (use_sync)
2295                regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
2296                                         ARIZONA_FLL1_SYNC_ENA,
2297                                         ARIZONA_FLL1_SYNC_ENA);
2298
2299        if (already_enabled)
2300                regmap_update_bits_async(arizona->regmap, fll->base + 1,
2301                                         ARIZONA_FLL1_FREERUN, 0);
2302
2303        arizona_fll_dbg(fll, "Waiting for FLL lock...\n");
2304        val = 0;
2305        for (i = 0; i < 15; i++) {
2306                if (i < 5)
2307                        usleep_range(200, 400);
2308                else
2309                        msleep(20);
2310
2311                regmap_read(arizona->regmap,
2312                            ARIZONA_INTERRUPT_RAW_STATUS_5,
2313                            &val);
2314                if (val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1)))
2315                        break;
2316        }
2317        if (i == 15)
2318                arizona_fll_warn(fll, "Timed out waiting for lock\n");
2319        else
2320                arizona_fll_dbg(fll, "FLL locked (%d polls)\n", i);
2321
2322        return 0;
2323}
2324
2325static void arizona_disable_fll(struct arizona_fll *fll)
2326{
2327        struct arizona *arizona = fll->arizona;
2328        bool change;
2329
2330        regmap_update_bits_async(arizona->regmap, fll->base + 1,
2331                                 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
2332        regmap_update_bits_check(arizona->regmap, fll->base + 1,
2333                                 ARIZONA_FLL1_ENA, 0, &change);
2334        regmap_update_bits(arizona->regmap, fll->base + 0x11,
2335                           ARIZONA_FLL1_SYNC_ENA, 0);
2336        regmap_update_bits_async(arizona->regmap, fll->base + 1,
2337                                 ARIZONA_FLL1_FREERUN, 0);
2338
2339        if (change)
2340                pm_runtime_put_autosuspend(arizona->dev);
2341}
2342
2343int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
2344                           unsigned int Fref, unsigned int Fout)
2345{
2346        int ret = 0;
2347
2348        if (fll->ref_src == source && fll->ref_freq == Fref)
2349                return 0;
2350
2351        if (fll->fout && Fref > 0) {
2352                ret = arizona_validate_fll(fll, Fref, fll->fout);
2353                if (ret != 0)
2354                        return ret;
2355        }
2356
2357        fll->ref_src = source;
2358        fll->ref_freq = Fref;
2359
2360        if (fll->fout && Fref > 0) {
2361                ret = arizona_enable_fll(fll);
2362        }
2363
2364        return ret;
2365}
2366EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
2367
2368int arizona_set_fll(struct arizona_fll *fll, int source,
2369                    unsigned int Fref, unsigned int Fout)
2370{
2371        int ret = 0;
2372
2373        if (fll->sync_src == source &&
2374            fll->sync_freq == Fref && fll->fout == Fout)
2375                return 0;
2376
2377        if (Fout) {
2378                if (fll->ref_src >= 0) {
2379                        ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
2380                        if (ret != 0)
2381                                return ret;
2382                }
2383
2384                ret = arizona_validate_fll(fll, Fref, Fout);
2385                if (ret != 0)
2386                        return ret;
2387        }
2388
2389        fll->sync_src = source;
2390        fll->sync_freq = Fref;
2391        fll->fout = Fout;
2392
2393        if (Fout)
2394                ret = arizona_enable_fll(fll);
2395        else
2396                arizona_disable_fll(fll);
2397
2398        return ret;
2399}
2400EXPORT_SYMBOL_GPL(arizona_set_fll);
2401
2402int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq,
2403                     int ok_irq, struct arizona_fll *fll)
2404{
2405        unsigned int val;
2406
2407        fll->id = id;
2408        fll->base = base;
2409        fll->arizona = arizona;
2410        fll->sync_src = ARIZONA_FLL_SRC_NONE;
2411
2412        /* Configure default refclk to 32kHz if we have one */
2413        regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val);
2414        switch (val & ARIZONA_CLK_32K_SRC_MASK) {
2415        case ARIZONA_CLK_SRC_MCLK1:
2416        case ARIZONA_CLK_SRC_MCLK2:
2417                fll->ref_src = val & ARIZONA_CLK_32K_SRC_MASK;
2418                break;
2419        default:
2420                fll->ref_src = ARIZONA_FLL_SRC_NONE;
2421        }
2422        fll->ref_freq = 32768;
2423
2424        snprintf(fll->lock_name, sizeof(fll->lock_name), "FLL%d lock", id);
2425        snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name),
2426                 "FLL%d clock OK", id);
2427
2428        regmap_update_bits(arizona->regmap, fll->base + 1,
2429                           ARIZONA_FLL1_FREERUN, 0);
2430
2431        return 0;
2432}
2433EXPORT_SYMBOL_GPL(arizona_init_fll);
2434
2435/**
2436 * arizona_set_output_mode - Set the mode of the specified output
2437 *
2438 * @codec: Device to configure
2439 * @output: Output number
2440 * @diff: True to set the output to differential mode
2441 *
2442 * Some systems use external analogue switches to connect more
2443 * analogue devices to the CODEC than are supported by the device.  In
2444 * some systems this requires changing the switched output from single
2445 * ended to differential mode dynamically at runtime, an operation
2446 * supported using this function.
2447 *
2448 * Most systems have a single static configuration and should use
2449 * platform data instead.
2450 */
2451int arizona_set_output_mode(struct snd_soc_codec *codec, int output, bool diff)
2452{
2453        unsigned int reg, val;
2454
2455        if (output < 1 || output > 6)
2456                return -EINVAL;
2457
2458        reg = ARIZONA_OUTPUT_PATH_CONFIG_1L + (output - 1) * 8;
2459
2460        if (diff)
2461                val = ARIZONA_OUT1_MONO;
2462        else
2463                val = 0;
2464
2465        return snd_soc_update_bits(codec, reg, ARIZONA_OUT1_MONO, val);
2466}
2467EXPORT_SYMBOL_GPL(arizona_set_output_mode);
2468
2469static const struct soc_enum arizona_adsp2_rate_enum[] = {
2470        SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
2471                              ARIZONA_DSP1_RATE_SHIFT, 0xf,
2472                              ARIZONA_RATE_ENUM_SIZE,
2473                              arizona_rate_text, arizona_rate_val),
2474        SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
2475                              ARIZONA_DSP1_RATE_SHIFT, 0xf,
2476                              ARIZONA_RATE_ENUM_SIZE,
2477                              arizona_rate_text, arizona_rate_val),
2478        SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
2479                              ARIZONA_DSP1_RATE_SHIFT, 0xf,
2480                              ARIZONA_RATE_ENUM_SIZE,
2481                              arizona_rate_text, arizona_rate_val),
2482        SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1,
2483                              ARIZONA_DSP1_RATE_SHIFT, 0xf,
2484                              ARIZONA_RATE_ENUM_SIZE,
2485                              arizona_rate_text, arizona_rate_val),
2486};
2487
2488const struct snd_kcontrol_new arizona_adsp2_rate_controls[] = {
2489        SOC_ENUM("DSP1 Rate", arizona_adsp2_rate_enum[0]),
2490        SOC_ENUM("DSP2 Rate", arizona_adsp2_rate_enum[1]),
2491        SOC_ENUM("DSP3 Rate", arizona_adsp2_rate_enum[2]),
2492        SOC_ENUM("DSP4 Rate", arizona_adsp2_rate_enum[3]),
2493};
2494EXPORT_SYMBOL_GPL(arizona_adsp2_rate_controls);
2495
2496static bool arizona_eq_filter_unstable(bool mode, __be16 _a, __be16 _b)
2497{
2498        s16 a = be16_to_cpu(_a);
2499        s16 b = be16_to_cpu(_b);
2500
2501        if (!mode) {
2502                return abs(a) >= 4096;
2503        } else {
2504                if (abs(b) >= 4096)
2505                        return true;
2506
2507                return (abs((a << 16) / (4096 - b)) >= 4096 << 4);
2508        }
2509}
2510
2511int arizona_eq_coeff_put(struct snd_kcontrol *kcontrol,
2512                         struct snd_ctl_elem_value *ucontrol)
2513{
2514        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2515        struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2516        struct soc_bytes *params = (void *)kcontrol->private_value;
2517        unsigned int val;
2518        __be16 *data;
2519        int len;
2520        int ret;
2521
2522        len = params->num_regs * regmap_get_val_bytes(arizona->regmap);
2523
2524        data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA);
2525        if (!data)
2526                return -ENOMEM;
2527
2528        data[0] &= cpu_to_be16(ARIZONA_EQ1_B1_MODE);
2529
2530        if (arizona_eq_filter_unstable(!!data[0], data[1], data[2]) ||
2531            arizona_eq_filter_unstable(true, data[4], data[5]) ||
2532            arizona_eq_filter_unstable(true, data[8], data[9]) ||
2533            arizona_eq_filter_unstable(true, data[12], data[13]) ||
2534            arizona_eq_filter_unstable(false, data[16], data[17])) {
2535                dev_err(arizona->dev, "Rejecting unstable EQ coefficients\n");
2536                ret = -EINVAL;
2537                goto out;
2538        }
2539
2540        ret = regmap_read(arizona->regmap, params->base, &val);
2541        if (ret != 0)
2542                goto out;
2543
2544        val &= ~ARIZONA_EQ1_B1_MODE;
2545        data[0] |= cpu_to_be16(val);
2546
2547        ret = regmap_raw_write(arizona->regmap, params->base, data, len);
2548
2549out:
2550        kfree(data);
2551        return ret;
2552}
2553EXPORT_SYMBOL_GPL(arizona_eq_coeff_put);
2554
2555int arizona_lhpf_coeff_put(struct snd_kcontrol *kcontrol,
2556                           struct snd_ctl_elem_value *ucontrol)
2557{
2558        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
2559        struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
2560        __be16 *data = (__be16 *)ucontrol->value.bytes.data;
2561        s16 val = be16_to_cpu(*data);
2562
2563        if (abs(val) >= 4096) {
2564                dev_err(arizona->dev, "Rejecting unstable LHPF coefficients\n");
2565                return -EINVAL;
2566        }
2567
2568        return snd_soc_bytes_put(kcontrol, ucontrol);
2569}
2570EXPORT_SYMBOL_GPL(arizona_lhpf_coeff_put);
2571
2572MODULE_DESCRIPTION("ASoC Wolfson Arizona class device support");
2573MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
2574MODULE_LICENSE("GPL");
2575