linux/sound/soc/codecs/adau17x1.c
<<
>>
Prefs
   1/*
   2 * Common code for ADAU1X61 and ADAU1X81 codecs
   3 *
   4 * Copyright 2011-2014 Analog Devices Inc.
   5 * Author: Lars-Peter Clausen <lars@metafoo.de>
   6 *
   7 * Licensed under the GPL-2 or later.
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/init.h>
  12#include <linux/delay.h>
  13#include <linux/slab.h>
  14#include <sound/core.h>
  15#include <sound/pcm.h>
  16#include <sound/pcm_params.h>
  17#include <sound/soc.h>
  18#include <sound/tlv.h>
  19#include <linux/gcd.h>
  20#include <linux/i2c.h>
  21#include <linux/spi/spi.h>
  22#include <linux/regmap.h>
  23
  24#include "sigmadsp.h"
  25#include "adau17x1.h"
  26
  27static const char * const adau17x1_capture_mixer_boost_text[] = {
  28        "Normal operation", "Boost Level 1", "Boost Level 2", "Boost Level 3",
  29};
  30
  31static SOC_ENUM_SINGLE_DECL(adau17x1_capture_boost_enum,
  32        ADAU17X1_REC_POWER_MGMT, 5, adau17x1_capture_mixer_boost_text);
  33
  34static const char * const adau17x1_mic_bias_mode_text[] = {
  35        "Normal operation", "High performance",
  36};
  37
  38static SOC_ENUM_SINGLE_DECL(adau17x1_mic_bias_mode_enum,
  39        ADAU17X1_MICBIAS, 3, adau17x1_mic_bias_mode_text);
  40
  41static const DECLARE_TLV_DB_MINMAX(adau17x1_digital_tlv, -9563, 0);
  42
  43static const struct snd_kcontrol_new adau17x1_controls[] = {
  44        SOC_DOUBLE_R_TLV("Digital Capture Volume",
  45                ADAU17X1_LEFT_INPUT_DIGITAL_VOL,
  46                ADAU17X1_RIGHT_INPUT_DIGITAL_VOL,
  47                0, 0xff, 1, adau17x1_digital_tlv),
  48        SOC_DOUBLE_R_TLV("Digital Playback Volume", ADAU17X1_DAC_CONTROL1,
  49                ADAU17X1_DAC_CONTROL2, 0, 0xff, 1, adau17x1_digital_tlv),
  50
  51        SOC_SINGLE("ADC High Pass Filter Switch", ADAU17X1_ADC_CONTROL,
  52                5, 1, 0),
  53        SOC_SINGLE("Playback De-emphasis Switch", ADAU17X1_DAC_CONTROL0,
  54                2, 1, 0),
  55
  56        SOC_ENUM("Capture Boost", adau17x1_capture_boost_enum),
  57
  58        SOC_ENUM("Mic Bias Mode", adau17x1_mic_bias_mode_enum),
  59};
  60
  61static int adau17x1_pll_event(struct snd_soc_dapm_widget *w,
  62        struct snd_kcontrol *kcontrol, int event)
  63{
  64        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
  65        struct adau *adau = snd_soc_codec_get_drvdata(codec);
  66        int ret;
  67
  68        if (SND_SOC_DAPM_EVENT_ON(event)) {
  69                adau->pll_regs[5] = 1;
  70        } else {
  71                adau->pll_regs[5] = 0;
  72                /* Bypass the PLL when disabled, otherwise registers will become
  73                 * inaccessible. */
  74                regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
  75                        ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL, 0);
  76        }
  77
  78        /* The PLL register is 6 bytes long and can only be written at once. */
  79        ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
  80                        adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
  81
  82        if (SND_SOC_DAPM_EVENT_ON(event)) {
  83                mdelay(5);
  84                regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
  85                        ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL,
  86                        ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL);
  87        }
  88
  89        return 0;
  90}
  91
  92static const char * const adau17x1_mono_stereo_text[] = {
  93        "Stereo",
  94        "Mono Left Channel (L+R)",
  95        "Mono Right Channel (L+R)",
  96        "Mono (L+R)",
  97};
  98
  99static SOC_ENUM_SINGLE_DECL(adau17x1_dac_mode_enum,
 100        ADAU17X1_DAC_CONTROL0, 6, adau17x1_mono_stereo_text);
 101
 102static const struct snd_kcontrol_new adau17x1_dac_mode_mux =
 103        SOC_DAPM_ENUM("DAC Mono-Stereo-Mode", adau17x1_dac_mode_enum);
 104
 105static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = {
 106        SND_SOC_DAPM_SUPPLY_S("PLL", 3, SND_SOC_NOPM, 0, 0, adau17x1_pll_event,
 107                SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 108
 109        SND_SOC_DAPM_SUPPLY("AIFCLK", SND_SOC_NOPM, 0, 0, NULL, 0),
 110
 111        SND_SOC_DAPM_SUPPLY("MICBIAS", ADAU17X1_MICBIAS, 0, 0, NULL, 0),
 112
 113        SND_SOC_DAPM_SUPPLY("Left Playback Enable", ADAU17X1_PLAY_POWER_MGMT,
 114                0, 0, NULL, 0),
 115        SND_SOC_DAPM_SUPPLY("Right Playback Enable", ADAU17X1_PLAY_POWER_MGMT,
 116                1, 0, NULL, 0),
 117
 118        SND_SOC_DAPM_MUX("Left DAC Mode Mux", SND_SOC_NOPM, 0, 0,
 119                &adau17x1_dac_mode_mux),
 120        SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0,
 121                &adau17x1_dac_mode_mux),
 122
 123        SND_SOC_DAPM_ADC("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0),
 124        SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0),
 125        SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0),
 126        SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0),
 127};
 128
 129static const struct snd_soc_dapm_route adau17x1_dapm_routes[] = {
 130        { "Left Decimator", NULL, "SYSCLK" },
 131        { "Right Decimator", NULL, "SYSCLK" },
 132        { "Left DAC", NULL, "SYSCLK" },
 133        { "Right DAC", NULL, "SYSCLK" },
 134        { "Capture", NULL, "SYSCLK" },
 135        { "Playback", NULL, "SYSCLK" },
 136
 137        { "Left DAC", NULL, "Left DAC Mode Mux" },
 138        { "Right DAC", NULL, "Right DAC Mode Mux" },
 139
 140        { "Capture", NULL, "AIFCLK" },
 141        { "Playback", NULL, "AIFCLK" },
 142};
 143
 144static const struct snd_soc_dapm_route adau17x1_dapm_pll_route = {
 145        "SYSCLK", NULL, "PLL",
 146};
 147
 148/*
 149 * The MUX register for the Capture and Playback MUXs selects either DSP as
 150 * source/destination or one of the TDM slots. The TDM slot is selected via
 151 * snd_soc_dai_set_tdm_slot(), so we only expose whether to go to the DSP or
 152 * directly to the DAI interface with this control.
 153 */
 154static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
 155        struct snd_ctl_elem_value *ucontrol)
 156{
 157        struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 158        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 159        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 160        struct snd_soc_dapm_update update;
 161        unsigned int stream = e->shift_l;
 162        unsigned int val, change;
 163        int reg;
 164
 165        if (ucontrol->value.enumerated.item[0] >= e->items)
 166                return -EINVAL;
 167
 168        switch (ucontrol->value.enumerated.item[0]) {
 169        case 0:
 170                val = 0;
 171                adau->dsp_bypass[stream] = false;
 172                break;
 173        default:
 174                val = (adau->tdm_slot[stream] * 2) + 1;
 175                adau->dsp_bypass[stream] = true;
 176                break;
 177        }
 178
 179        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
 180                reg = ADAU17X1_SERIAL_INPUT_ROUTE;
 181        else
 182                reg = ADAU17X1_SERIAL_OUTPUT_ROUTE;
 183
 184        change = snd_soc_test_bits(codec, reg, 0xff, val);
 185        if (change) {
 186                update.kcontrol = kcontrol;
 187                update.mask = 0xff;
 188                update.reg = reg;
 189                update.val = val;
 190
 191                snd_soc_dapm_mux_update_power(&codec->dapm, kcontrol,
 192                                ucontrol->value.enumerated.item[0], e, &update);
 193        }
 194
 195        return change;
 196}
 197
 198static int adau17x1_dsp_mux_enum_get(struct snd_kcontrol *kcontrol,
 199        struct snd_ctl_elem_value *ucontrol)
 200{
 201        struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 202        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 203        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 204        unsigned int stream = e->shift_l;
 205        unsigned int reg, val;
 206        int ret;
 207
 208        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
 209                reg = ADAU17X1_SERIAL_INPUT_ROUTE;
 210        else
 211                reg = ADAU17X1_SERIAL_OUTPUT_ROUTE;
 212
 213        ret = regmap_read(adau->regmap, reg, &val);
 214        if (ret)
 215                return ret;
 216
 217        if (val != 0)
 218                val = 1;
 219        ucontrol->value.enumerated.item[0] = val;
 220
 221        return 0;
 222}
 223
 224#define DECLARE_ADAU17X1_DSP_MUX_CTRL(_name, _label, _stream, _text) \
 225        const struct snd_kcontrol_new _name = \
 226                SOC_DAPM_ENUM_EXT(_label, (const struct soc_enum)\
 227                        SOC_ENUM_SINGLE(SND_SOC_NOPM, _stream, \
 228                                ARRAY_SIZE(_text), _text), \
 229                        adau17x1_dsp_mux_enum_get, adau17x1_dsp_mux_enum_put)
 230
 231static const char * const adau17x1_dac_mux_text[] = {
 232        "DSP",
 233        "AIFIN",
 234};
 235
 236static const char * const adau17x1_capture_mux_text[] = {
 237        "DSP",
 238        "Decimator",
 239};
 240
 241static DECLARE_ADAU17X1_DSP_MUX_CTRL(adau17x1_dac_mux, "DAC Playback Mux",
 242        SNDRV_PCM_STREAM_PLAYBACK, adau17x1_dac_mux_text);
 243
 244static DECLARE_ADAU17X1_DSP_MUX_CTRL(adau17x1_capture_mux, "Capture Mux",
 245        SNDRV_PCM_STREAM_CAPTURE, adau17x1_capture_mux_text);
 246
 247static const struct snd_soc_dapm_widget adau17x1_dsp_dapm_widgets[] = {
 248        SND_SOC_DAPM_PGA("DSP", ADAU17X1_DSP_RUN, 0, 0, NULL, 0),
 249        SND_SOC_DAPM_SIGGEN("DSP Siggen"),
 250
 251        SND_SOC_DAPM_MUX("DAC Playback Mux", SND_SOC_NOPM, 0, 0,
 252                &adau17x1_dac_mux),
 253        SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0,
 254                &adau17x1_capture_mux),
 255};
 256
 257static const struct snd_soc_dapm_route adau17x1_dsp_dapm_routes[] = {
 258        { "DAC Playback Mux", "DSP", "DSP" },
 259        { "DAC Playback Mux", "AIFIN", "Playback" },
 260
 261        { "Left DAC Mode Mux", "Stereo", "DAC Playback Mux" },
 262        { "Left DAC Mode Mux", "Mono (L+R)", "DAC Playback Mux" },
 263        { "Left DAC Mode Mux", "Mono Left Channel (L+R)", "DAC Playback Mux" },
 264        { "Right DAC Mode Mux", "Stereo", "DAC Playback Mux" },
 265        { "Right DAC Mode Mux", "Mono (L+R)", "DAC Playback Mux" },
 266        { "Right DAC Mode Mux", "Mono Right Channel (L+R)", "DAC Playback Mux" },
 267
 268        { "Capture Mux", "DSP", "DSP" },
 269        { "Capture Mux", "Decimator", "Left Decimator" },
 270        { "Capture Mux", "Decimator", "Right Decimator" },
 271
 272        { "Capture", NULL, "Capture Mux" },
 273
 274        { "DSP", NULL, "DSP Siggen" },
 275
 276        { "DSP", NULL, "Left Decimator" },
 277        { "DSP", NULL, "Right Decimator" },
 278};
 279
 280static const struct snd_soc_dapm_route adau17x1_no_dsp_dapm_routes[] = {
 281        { "Left DAC Mode Mux", "Stereo", "Playback" },
 282        { "Left DAC Mode Mux", "Mono (L+R)", "Playback" },
 283        { "Left DAC Mode Mux", "Mono Left Channel (L+R)", "Playback" },
 284        { "Right DAC Mode Mux", "Stereo", "Playback" },
 285        { "Right DAC Mode Mux", "Mono (L+R)", "Playback" },
 286        { "Right DAC Mode Mux", "Mono Right Channel (L+R)", "Playback" },
 287        { "Capture", NULL, "Left Decimator" },
 288        { "Capture", NULL, "Right Decimator" },
 289};
 290
 291bool adau17x1_has_dsp(struct adau *adau)
 292{
 293        switch (adau->type) {
 294        case ADAU1761:
 295        case ADAU1381:
 296        case ADAU1781:
 297                return true;
 298        default:
 299                return false;
 300        }
 301}
 302EXPORT_SYMBOL_GPL(adau17x1_has_dsp);
 303
 304static int adau17x1_hw_params(struct snd_pcm_substream *substream,
 305        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 306{
 307        struct snd_soc_codec *codec = dai->codec;
 308        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 309        unsigned int val, div, dsp_div;
 310        unsigned int freq;
 311        int ret;
 312
 313        if (adau->clk_src == ADAU17X1_CLK_SRC_PLL)
 314                freq = adau->pll_freq;
 315        else
 316                freq = adau->sysclk;
 317
 318        if (freq % params_rate(params) != 0)
 319                return -EINVAL;
 320
 321        switch (freq / params_rate(params)) {
 322        case 1024: /* fs */
 323                div = 0;
 324                dsp_div = 1;
 325                break;
 326        case 6144: /* fs / 6 */
 327                div = 1;
 328                dsp_div = 6;
 329                break;
 330        case 4096: /* fs / 4 */
 331                div = 2;
 332                dsp_div = 5;
 333                break;
 334        case 3072: /* fs / 3 */
 335                div = 3;
 336                dsp_div = 4;
 337                break;
 338        case 2048: /* fs / 2 */
 339                div = 4;
 340                dsp_div = 3;
 341                break;
 342        case 1536: /* fs / 1.5 */
 343                div = 5;
 344                dsp_div = 2;
 345                break;
 346        case 512: /* fs / 0.5 */
 347                div = 6;
 348                dsp_div = 0;
 349                break;
 350        default:
 351                return -EINVAL;
 352        }
 353
 354        regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
 355                ADAU17X1_CONVERTER0_CONVSR_MASK, div);
 356        if (adau17x1_has_dsp(adau)) {
 357                regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div);
 358                regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div);
 359        }
 360
 361        if (adau->sigmadsp) {
 362                ret = adau17x1_setup_firmware(adau, params_rate(params));
 363                if (ret < 0)
 364                        return ret;
 365        }
 366
 367        if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
 368                return 0;
 369
 370        switch (params_width(params)) {
 371        case 16:
 372                val = ADAU17X1_SERIAL_PORT1_DELAY16;
 373                break;
 374        case 24:
 375                val = ADAU17X1_SERIAL_PORT1_DELAY8;
 376                break;
 377        case 32:
 378                val = ADAU17X1_SERIAL_PORT1_DELAY0;
 379                break;
 380        default:
 381                return -EINVAL;
 382        }
 383
 384        return regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
 385                        ADAU17X1_SERIAL_PORT1_DELAY_MASK, val);
 386}
 387
 388static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
 389        int source, unsigned int freq_in, unsigned int freq_out)
 390{
 391        struct snd_soc_codec *codec = dai->codec;
 392        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 393        unsigned int r, n, m, i, j;
 394        unsigned int div;
 395        int ret;
 396
 397        if (freq_in < 8000000 || freq_in > 27000000)
 398                return -EINVAL;
 399
 400        if (!freq_out) {
 401                r = 0;
 402                n = 0;
 403                m = 0;
 404                div = 0;
 405        } else {
 406                if (freq_out % freq_in != 0) {
 407                        div = DIV_ROUND_UP(freq_in, 13500000);
 408                        freq_in /= div;
 409                        r = freq_out / freq_in;
 410                        i = freq_out % freq_in;
 411                        j = gcd(i, freq_in);
 412                        n = i / j;
 413                        m = freq_in / j;
 414                        div--;
 415                } else {
 416                        r = freq_out / freq_in;
 417                        n = 0;
 418                        m = 0;
 419                        div = 0;
 420                }
 421                if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2)
 422                        return -EINVAL;
 423        }
 424
 425        adau->pll_regs[0] = m >> 8;
 426        adau->pll_regs[1] = m & 0xff;
 427        adau->pll_regs[2] = n >> 8;
 428        adau->pll_regs[3] = n & 0xff;
 429        adau->pll_regs[4] = (r << 3) | (div << 1);
 430        if (m != 0)
 431                adau->pll_regs[4] |= 1; /* Fractional mode */
 432
 433        /* The PLL register is 6 bytes long and can only be written at once. */
 434        ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
 435                        adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
 436        if (ret)
 437                return ret;
 438
 439        adau->pll_freq = freq_out;
 440
 441        return 0;
 442}
 443
 444static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
 445                int clk_id, unsigned int freq, int dir)
 446{
 447        struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
 448        struct snd_soc_dapm_context *dapm = &dai->codec->dapm;
 449
 450        switch (clk_id) {
 451        case ADAU17X1_CLK_SRC_MCLK:
 452        case ADAU17X1_CLK_SRC_PLL:
 453                break;
 454        default:
 455                return -EINVAL;
 456        }
 457
 458        adau->sysclk = freq;
 459
 460        if (adau->clk_src != clk_id) {
 461                if (clk_id == ADAU17X1_CLK_SRC_PLL) {
 462                        snd_soc_dapm_add_routes(dapm,
 463                                &adau17x1_dapm_pll_route, 1);
 464                } else {
 465                        snd_soc_dapm_del_routes(dapm,
 466                                &adau17x1_dapm_pll_route, 1);
 467                }
 468        }
 469
 470        adau->clk_src = clk_id;
 471
 472        return 0;
 473}
 474
 475static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai,
 476                unsigned int fmt)
 477{
 478        struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
 479        unsigned int ctrl0, ctrl1;
 480        int lrclk_pol;
 481
 482        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 483        case SND_SOC_DAIFMT_CBM_CFM:
 484                ctrl0 = ADAU17X1_SERIAL_PORT0_MASTER;
 485                adau->master = true;
 486                break;
 487        case SND_SOC_DAIFMT_CBS_CFS:
 488                ctrl0 = 0;
 489                adau->master = false;
 490                break;
 491        default:
 492                return -EINVAL;
 493        }
 494
 495        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 496        case SND_SOC_DAIFMT_I2S:
 497                lrclk_pol = 0;
 498                ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1;
 499                break;
 500        case SND_SOC_DAIFMT_LEFT_J:
 501        case SND_SOC_DAIFMT_RIGHT_J:
 502                lrclk_pol = 1;
 503                ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0;
 504                break;
 505        case SND_SOC_DAIFMT_DSP_A:
 506                lrclk_pol = 1;
 507                ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE;
 508                ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1;
 509                break;
 510        case SND_SOC_DAIFMT_DSP_B:
 511                lrclk_pol = 1;
 512                ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE;
 513                ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0;
 514                break;
 515        default:
 516                return -EINVAL;
 517        }
 518
 519        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 520        case SND_SOC_DAIFMT_NB_NF:
 521                break;
 522        case SND_SOC_DAIFMT_IB_NF:
 523                ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
 524                break;
 525        case SND_SOC_DAIFMT_NB_IF:
 526                lrclk_pol = !lrclk_pol;
 527                break;
 528        case SND_SOC_DAIFMT_IB_IF:
 529                ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
 530                lrclk_pol = !lrclk_pol;
 531                break;
 532        default:
 533                return -EINVAL;
 534        }
 535
 536        if (lrclk_pol)
 537                ctrl0 |= ADAU17X1_SERIAL_PORT0_LRCLK_POL;
 538
 539        regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT0, ctrl0);
 540        regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT1, ctrl1);
 541
 542        adau->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 543
 544        return 0;
 545}
 546
 547static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai,
 548        unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 549{
 550        struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
 551        unsigned int ser_ctrl0, ser_ctrl1;
 552        unsigned int conv_ctrl0, conv_ctrl1;
 553
 554        /* I2S mode */
 555        if (slots == 0) {
 556                slots = 2;
 557                rx_mask = 3;
 558                tx_mask = 3;
 559                slot_width = 32;
 560        }
 561
 562        switch (slots) {
 563        case 2:
 564                ser_ctrl0 = ADAU17X1_SERIAL_PORT0_STEREO;
 565                break;
 566        case 4:
 567                ser_ctrl0 = ADAU17X1_SERIAL_PORT0_TDM4;
 568                break;
 569        case 8:
 570                if (adau->type == ADAU1361)
 571                        return -EINVAL;
 572
 573                ser_ctrl0 = ADAU17X1_SERIAL_PORT0_TDM8;
 574                break;
 575        default:
 576                return -EINVAL;
 577        }
 578
 579        switch (slot_width * slots) {
 580        case 32:
 581                if (adau->type == ADAU1761)
 582                        return -EINVAL;
 583
 584                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK32;
 585                break;
 586        case 64:
 587                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK64;
 588                break;
 589        case 48:
 590                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK48;
 591                break;
 592        case 128:
 593                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK128;
 594                break;
 595        case 256:
 596                if (adau->type == ADAU1361)
 597                        return -EINVAL;
 598
 599                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK256;
 600                break;
 601        default:
 602                return -EINVAL;
 603        }
 604
 605        switch (rx_mask) {
 606        case 0x03:
 607                conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(1);
 608                adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 0;
 609                break;
 610        case 0x0c:
 611                conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(2);
 612                adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 1;
 613                break;
 614        case 0x30:
 615                conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(3);
 616                adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 2;
 617                break;
 618        case 0xc0:
 619                conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(4);
 620                adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 3;
 621                break;
 622        default:
 623                return -EINVAL;
 624        }
 625
 626        switch (tx_mask) {
 627        case 0x03:
 628                conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(1);
 629                adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 0;
 630                break;
 631        case 0x0c:
 632                conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(2);
 633                adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 1;
 634                break;
 635        case 0x30:
 636                conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(3);
 637                adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 2;
 638                break;
 639        case 0xc0:
 640                conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(4);
 641                adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 3;
 642                break;
 643        default:
 644                return -EINVAL;
 645        }
 646
 647        regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
 648                ADAU17X1_CONVERTER0_DAC_PAIR_MASK, conv_ctrl0);
 649        regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER1,
 650                ADAU17X1_CONVERTER1_ADC_PAIR_MASK, conv_ctrl1);
 651        regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT0,
 652                ADAU17X1_SERIAL_PORT0_TDM_MASK, ser_ctrl0);
 653        regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
 654                ADAU17X1_SERIAL_PORT1_BCLK_MASK, ser_ctrl1);
 655
 656        if (!adau17x1_has_dsp(adau))
 657                return 0;
 658
 659        if (adau->dsp_bypass[SNDRV_PCM_STREAM_PLAYBACK]) {
 660                regmap_write(adau->regmap, ADAU17X1_SERIAL_INPUT_ROUTE,
 661                        (adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] * 2) + 1);
 662        }
 663
 664        if (adau->dsp_bypass[SNDRV_PCM_STREAM_CAPTURE]) {
 665                regmap_write(adau->regmap, ADAU17X1_SERIAL_OUTPUT_ROUTE,
 666                        (adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] * 2) + 1);
 667        }
 668
 669        return 0;
 670}
 671
 672static int adau17x1_startup(struct snd_pcm_substream *substream,
 673        struct snd_soc_dai *dai)
 674{
 675        struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
 676
 677        if (adau->sigmadsp)
 678                return sigmadsp_restrict_params(adau->sigmadsp, substream);
 679
 680        return 0;
 681}
 682
 683const struct snd_soc_dai_ops adau17x1_dai_ops = {
 684        .hw_params      = adau17x1_hw_params,
 685        .set_sysclk     = adau17x1_set_dai_sysclk,
 686        .set_fmt        = adau17x1_set_dai_fmt,
 687        .set_pll        = adau17x1_set_dai_pll,
 688        .set_tdm_slot   = adau17x1_set_dai_tdm_slot,
 689        .startup        = adau17x1_startup,
 690};
 691EXPORT_SYMBOL_GPL(adau17x1_dai_ops);
 692
 693int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
 694        enum adau17x1_micbias_voltage micbias)
 695{
 696        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 697
 698        switch (micbias) {
 699        case ADAU17X1_MICBIAS_0_90_AVDD:
 700        case ADAU17X1_MICBIAS_0_65_AVDD:
 701                break;
 702        default:
 703                return -EINVAL;
 704        }
 705
 706        return regmap_write(adau->regmap, ADAU17X1_MICBIAS, micbias << 2);
 707}
 708EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage);
 709
 710bool adau17x1_precious_register(struct device *dev, unsigned int reg)
 711{
 712        /* SigmaDSP parameter memory */
 713        if (reg < 0x400)
 714                return true;
 715
 716        return false;
 717}
 718EXPORT_SYMBOL_GPL(adau17x1_precious_register);
 719
 720bool adau17x1_readable_register(struct device *dev, unsigned int reg)
 721{
 722        /* SigmaDSP parameter memory */
 723        if (reg < 0x400)
 724                return true;
 725
 726        switch (reg) {
 727        case ADAU17X1_CLOCK_CONTROL:
 728        case ADAU17X1_PLL_CONTROL:
 729        case ADAU17X1_REC_POWER_MGMT:
 730        case ADAU17X1_MICBIAS:
 731        case ADAU17X1_SERIAL_PORT0:
 732        case ADAU17X1_SERIAL_PORT1:
 733        case ADAU17X1_CONVERTER0:
 734        case ADAU17X1_CONVERTER1:
 735        case ADAU17X1_LEFT_INPUT_DIGITAL_VOL:
 736        case ADAU17X1_RIGHT_INPUT_DIGITAL_VOL:
 737        case ADAU17X1_ADC_CONTROL:
 738        case ADAU17X1_PLAY_POWER_MGMT:
 739        case ADAU17X1_DAC_CONTROL0:
 740        case ADAU17X1_DAC_CONTROL1:
 741        case ADAU17X1_DAC_CONTROL2:
 742        case ADAU17X1_SERIAL_PORT_PAD:
 743        case ADAU17X1_CONTROL_PORT_PAD0:
 744        case ADAU17X1_CONTROL_PORT_PAD1:
 745        case ADAU17X1_DSP_SAMPLING_RATE:
 746        case ADAU17X1_SERIAL_INPUT_ROUTE:
 747        case ADAU17X1_SERIAL_OUTPUT_ROUTE:
 748        case ADAU17X1_DSP_ENABLE:
 749        case ADAU17X1_DSP_RUN:
 750        case ADAU17X1_SERIAL_SAMPLING_RATE:
 751                return true;
 752        default:
 753                break;
 754        }
 755        return false;
 756}
 757EXPORT_SYMBOL_GPL(adau17x1_readable_register);
 758
 759bool adau17x1_volatile_register(struct device *dev, unsigned int reg)
 760{
 761        /* SigmaDSP parameter and program memory */
 762        if (reg < 0x4000)
 763                return true;
 764
 765        switch (reg) {
 766        /* The PLL register is 6 bytes long */
 767        case ADAU17X1_PLL_CONTROL:
 768        case ADAU17X1_PLL_CONTROL + 1:
 769        case ADAU17X1_PLL_CONTROL + 2:
 770        case ADAU17X1_PLL_CONTROL + 3:
 771        case ADAU17X1_PLL_CONTROL + 4:
 772        case ADAU17X1_PLL_CONTROL + 5:
 773                return true;
 774        default:
 775                break;
 776        }
 777
 778        return false;
 779}
 780EXPORT_SYMBOL_GPL(adau17x1_volatile_register);
 781
 782int adau17x1_setup_firmware(struct adau *adau, unsigned int rate)
 783{
 784        int ret;
 785        int dspsr;
 786
 787        ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr);
 788        if (ret)
 789                return ret;
 790
 791        regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
 792        regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);
 793
 794        ret = sigmadsp_setup(adau->sigmadsp, rate);
 795        if (ret) {
 796                regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
 797                return ret;
 798        }
 799        regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr);
 800
 801        return 0;
 802}
 803EXPORT_SYMBOL_GPL(adau17x1_setup_firmware);
 804
 805int adau17x1_add_widgets(struct snd_soc_codec *codec)
 806{
 807        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 808        int ret;
 809
 810        ret = snd_soc_add_codec_controls(codec, adau17x1_controls,
 811                ARRAY_SIZE(adau17x1_controls));
 812        if (ret)
 813                return ret;
 814        ret = snd_soc_dapm_new_controls(&codec->dapm, adau17x1_dapm_widgets,
 815                ARRAY_SIZE(adau17x1_dapm_widgets));
 816        if (ret)
 817                return ret;
 818
 819        if (adau17x1_has_dsp(adau)) {
 820                ret = snd_soc_dapm_new_controls(&codec->dapm,
 821                        adau17x1_dsp_dapm_widgets,
 822                        ARRAY_SIZE(adau17x1_dsp_dapm_widgets));
 823                if (ret)
 824                        return ret;
 825
 826                if (!adau->sigmadsp)
 827                        return 0;
 828
 829                ret = sigmadsp_attach(adau->sigmadsp, &codec->component);
 830                if (ret) {
 831                        dev_err(codec->dev, "Failed to attach firmware: %d\n",
 832                                ret);
 833                        return ret;
 834                }
 835        }
 836
 837        return 0;
 838}
 839EXPORT_SYMBOL_GPL(adau17x1_add_widgets);
 840
 841int adau17x1_add_routes(struct snd_soc_codec *codec)
 842{
 843        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 844        int ret;
 845
 846        ret = snd_soc_dapm_add_routes(&codec->dapm, adau17x1_dapm_routes,
 847                ARRAY_SIZE(adau17x1_dapm_routes));
 848        if (ret)
 849                return ret;
 850
 851        if (adau17x1_has_dsp(adau)) {
 852                ret = snd_soc_dapm_add_routes(&codec->dapm,
 853                        adau17x1_dsp_dapm_routes,
 854                        ARRAY_SIZE(adau17x1_dsp_dapm_routes));
 855        } else {
 856                ret = snd_soc_dapm_add_routes(&codec->dapm,
 857                        adau17x1_no_dsp_dapm_routes,
 858                        ARRAY_SIZE(adau17x1_no_dsp_dapm_routes));
 859        }
 860        return ret;
 861}
 862EXPORT_SYMBOL_GPL(adau17x1_add_routes);
 863
 864int adau17x1_resume(struct snd_soc_codec *codec)
 865{
 866        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 867
 868        if (adau->switch_mode)
 869                adau->switch_mode(codec->dev);
 870
 871        regcache_sync(adau->regmap);
 872
 873        return 0;
 874}
 875EXPORT_SYMBOL_GPL(adau17x1_resume);
 876
 877int adau17x1_probe(struct device *dev, struct regmap *regmap,
 878        enum adau17x1_type type, void (*switch_mode)(struct device *dev),
 879        const char *firmware_name)
 880{
 881        struct adau *adau;
 882
 883        if (IS_ERR(regmap))
 884                return PTR_ERR(regmap);
 885
 886        adau = devm_kzalloc(dev, sizeof(*adau), GFP_KERNEL);
 887        if (!adau)
 888                return -ENOMEM;
 889
 890        adau->regmap = regmap;
 891        adau->switch_mode = switch_mode;
 892        adau->type = type;
 893
 894        dev_set_drvdata(dev, adau);
 895
 896        if (firmware_name) {
 897                adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, NULL,
 898                        firmware_name);
 899                if (IS_ERR(adau->sigmadsp)) {
 900                        dev_warn(dev, "Could not find firmware file: %ld\n",
 901                                PTR_ERR(adau->sigmadsp));
 902                        adau->sigmadsp = NULL;
 903                }
 904        }
 905
 906        if (switch_mode)
 907                switch_mode(dev);
 908
 909        return 0;
 910}
 911EXPORT_SYMBOL_GPL(adau17x1_probe);
 912
 913MODULE_DESCRIPTION("ASoC ADAU1X61/ADAU1X81 common code");
 914MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 915MODULE_LICENSE("GPL");
 916