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 snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 159        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 160        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 161        struct snd_soc_dapm_update update;
 162        unsigned int stream = e->shift_l;
 163        unsigned int val, change;
 164        int reg;
 165
 166        if (ucontrol->value.enumerated.item[0] >= e->items)
 167                return -EINVAL;
 168
 169        switch (ucontrol->value.enumerated.item[0]) {
 170        case 0:
 171                val = 0;
 172                adau->dsp_bypass[stream] = false;
 173                break;
 174        default:
 175                val = (adau->tdm_slot[stream] * 2) + 1;
 176                adau->dsp_bypass[stream] = true;
 177                break;
 178        }
 179
 180        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
 181                reg = ADAU17X1_SERIAL_INPUT_ROUTE;
 182        else
 183                reg = ADAU17X1_SERIAL_OUTPUT_ROUTE;
 184
 185        change = snd_soc_test_bits(codec, reg, 0xff, val);
 186        if (change) {
 187                update.kcontrol = kcontrol;
 188                update.mask = 0xff;
 189                update.reg = reg;
 190                update.val = val;
 191
 192                snd_soc_dapm_mux_update_power(dapm, kcontrol,
 193                                ucontrol->value.enumerated.item[0], e, &update);
 194        }
 195
 196        return change;
 197}
 198
 199static int adau17x1_dsp_mux_enum_get(struct snd_kcontrol *kcontrol,
 200        struct snd_ctl_elem_value *ucontrol)
 201{
 202        struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol);
 203        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 204        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 205        unsigned int stream = e->shift_l;
 206        unsigned int reg, val;
 207        int ret;
 208
 209        if (stream == SNDRV_PCM_STREAM_PLAYBACK)
 210                reg = ADAU17X1_SERIAL_INPUT_ROUTE;
 211        else
 212                reg = ADAU17X1_SERIAL_OUTPUT_ROUTE;
 213
 214        ret = regmap_read(adau->regmap, reg, &val);
 215        if (ret)
 216                return ret;
 217
 218        if (val != 0)
 219                val = 1;
 220        ucontrol->value.enumerated.item[0] = val;
 221
 222        return 0;
 223}
 224
 225#define DECLARE_ADAU17X1_DSP_MUX_CTRL(_name, _label, _stream, _text) \
 226        const struct snd_kcontrol_new _name = \
 227                SOC_DAPM_ENUM_EXT(_label, (const struct soc_enum)\
 228                        SOC_ENUM_SINGLE(SND_SOC_NOPM, _stream, \
 229                                ARRAY_SIZE(_text), _text), \
 230                        adau17x1_dsp_mux_enum_get, adau17x1_dsp_mux_enum_put)
 231
 232static const char * const adau17x1_dac_mux_text[] = {
 233        "DSP",
 234        "AIFIN",
 235};
 236
 237static const char * const adau17x1_capture_mux_text[] = {
 238        "DSP",
 239        "Decimator",
 240};
 241
 242static DECLARE_ADAU17X1_DSP_MUX_CTRL(adau17x1_dac_mux, "DAC Playback Mux",
 243        SNDRV_PCM_STREAM_PLAYBACK, adau17x1_dac_mux_text);
 244
 245static DECLARE_ADAU17X1_DSP_MUX_CTRL(adau17x1_capture_mux, "Capture Mux",
 246        SNDRV_PCM_STREAM_CAPTURE, adau17x1_capture_mux_text);
 247
 248static const struct snd_soc_dapm_widget adau17x1_dsp_dapm_widgets[] = {
 249        SND_SOC_DAPM_PGA("DSP", ADAU17X1_DSP_RUN, 0, 0, NULL, 0),
 250        SND_SOC_DAPM_SIGGEN("DSP Siggen"),
 251
 252        SND_SOC_DAPM_MUX("DAC Playback Mux", SND_SOC_NOPM, 0, 0,
 253                &adau17x1_dac_mux),
 254        SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0,
 255                &adau17x1_capture_mux),
 256};
 257
 258static const struct snd_soc_dapm_route adau17x1_dsp_dapm_routes[] = {
 259        { "DAC Playback Mux", "DSP", "DSP" },
 260        { "DAC Playback Mux", "AIFIN", "Playback" },
 261
 262        { "Left DAC Mode Mux", "Stereo", "DAC Playback Mux" },
 263        { "Left DAC Mode Mux", "Mono (L+R)", "DAC Playback Mux" },
 264        { "Left DAC Mode Mux", "Mono Left Channel (L+R)", "DAC Playback Mux" },
 265        { "Right DAC Mode Mux", "Stereo", "DAC Playback Mux" },
 266        { "Right DAC Mode Mux", "Mono (L+R)", "DAC Playback Mux" },
 267        { "Right DAC Mode Mux", "Mono Right Channel (L+R)", "DAC Playback Mux" },
 268
 269        { "Capture Mux", "DSP", "DSP" },
 270        { "Capture Mux", "Decimator", "Left Decimator" },
 271        { "Capture Mux", "Decimator", "Right Decimator" },
 272
 273        { "Capture", NULL, "Capture Mux" },
 274
 275        { "DSP", NULL, "DSP Siggen" },
 276
 277        { "DSP", NULL, "Left Decimator" },
 278        { "DSP", NULL, "Right Decimator" },
 279};
 280
 281static const struct snd_soc_dapm_route adau17x1_no_dsp_dapm_routes[] = {
 282        { "Left DAC Mode Mux", "Stereo", "Playback" },
 283        { "Left DAC Mode Mux", "Mono (L+R)", "Playback" },
 284        { "Left DAC Mode Mux", "Mono Left Channel (L+R)", "Playback" },
 285        { "Right DAC Mode Mux", "Stereo", "Playback" },
 286        { "Right DAC Mode Mux", "Mono (L+R)", "Playback" },
 287        { "Right DAC Mode Mux", "Mono Right Channel (L+R)", "Playback" },
 288        { "Capture", NULL, "Left Decimator" },
 289        { "Capture", NULL, "Right Decimator" },
 290};
 291
 292bool adau17x1_has_dsp(struct adau *adau)
 293{
 294        switch (adau->type) {
 295        case ADAU1761:
 296        case ADAU1381:
 297        case ADAU1781:
 298                return true;
 299        default:
 300                return false;
 301        }
 302}
 303EXPORT_SYMBOL_GPL(adau17x1_has_dsp);
 304
 305static int adau17x1_hw_params(struct snd_pcm_substream *substream,
 306        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 307{
 308        struct snd_soc_codec *codec = dai->codec;
 309        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 310        unsigned int val, div, dsp_div;
 311        unsigned int freq;
 312        int ret;
 313
 314        if (adau->clk_src == ADAU17X1_CLK_SRC_PLL)
 315                freq = adau->pll_freq;
 316        else
 317                freq = adau->sysclk;
 318
 319        if (freq % params_rate(params) != 0)
 320                return -EINVAL;
 321
 322        switch (freq / params_rate(params)) {
 323        case 1024: /* fs */
 324                div = 0;
 325                dsp_div = 1;
 326                break;
 327        case 6144: /* fs / 6 */
 328                div = 1;
 329                dsp_div = 6;
 330                break;
 331        case 4096: /* fs / 4 */
 332                div = 2;
 333                dsp_div = 5;
 334                break;
 335        case 3072: /* fs / 3 */
 336                div = 3;
 337                dsp_div = 4;
 338                break;
 339        case 2048: /* fs / 2 */
 340                div = 4;
 341                dsp_div = 3;
 342                break;
 343        case 1536: /* fs / 1.5 */
 344                div = 5;
 345                dsp_div = 2;
 346                break;
 347        case 512: /* fs / 0.5 */
 348                div = 6;
 349                dsp_div = 0;
 350                break;
 351        default:
 352                return -EINVAL;
 353        }
 354
 355        regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
 356                ADAU17X1_CONVERTER0_CONVSR_MASK, div);
 357        if (adau17x1_has_dsp(adau)) {
 358                regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div);
 359                regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div);
 360        }
 361
 362        if (adau->sigmadsp) {
 363                ret = adau17x1_setup_firmware(adau, params_rate(params));
 364                if (ret < 0)
 365                        return ret;
 366        }
 367
 368        if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
 369                return 0;
 370
 371        switch (params_width(params)) {
 372        case 16:
 373                val = ADAU17X1_SERIAL_PORT1_DELAY16;
 374                break;
 375        case 24:
 376                val = ADAU17X1_SERIAL_PORT1_DELAY8;
 377                break;
 378        case 32:
 379                val = ADAU17X1_SERIAL_PORT1_DELAY0;
 380                break;
 381        default:
 382                return -EINVAL;
 383        }
 384
 385        return regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
 386                        ADAU17X1_SERIAL_PORT1_DELAY_MASK, val);
 387}
 388
 389static int adau17x1_set_dai_pll(struct snd_soc_dai *dai, int pll_id,
 390        int source, unsigned int freq_in, unsigned int freq_out)
 391{
 392        struct snd_soc_codec *codec = dai->codec;
 393        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 394        unsigned int r, n, m, i, j;
 395        unsigned int div;
 396        int ret;
 397
 398        if (freq_in < 8000000 || freq_in > 27000000)
 399                return -EINVAL;
 400
 401        if (!freq_out) {
 402                r = 0;
 403                n = 0;
 404                m = 0;
 405                div = 0;
 406        } else {
 407                if (freq_out % freq_in != 0) {
 408                        div = DIV_ROUND_UP(freq_in, 13500000);
 409                        freq_in /= div;
 410                        r = freq_out / freq_in;
 411                        i = freq_out % freq_in;
 412                        j = gcd(i, freq_in);
 413                        n = i / j;
 414                        m = freq_in / j;
 415                        div--;
 416                } else {
 417                        r = freq_out / freq_in;
 418                        n = 0;
 419                        m = 0;
 420                        div = 0;
 421                }
 422                if (n > 0xffff || m > 0xffff || div > 3 || r > 8 || r < 2)
 423                        return -EINVAL;
 424        }
 425
 426        adau->pll_regs[0] = m >> 8;
 427        adau->pll_regs[1] = m & 0xff;
 428        adau->pll_regs[2] = n >> 8;
 429        adau->pll_regs[3] = n & 0xff;
 430        adau->pll_regs[4] = (r << 3) | (div << 1);
 431        if (m != 0)
 432                adau->pll_regs[4] |= 1; /* Fractional mode */
 433
 434        /* The PLL register is 6 bytes long and can only be written at once. */
 435        ret = regmap_raw_write(adau->regmap, ADAU17X1_PLL_CONTROL,
 436                        adau->pll_regs, ARRAY_SIZE(adau->pll_regs));
 437        if (ret)
 438                return ret;
 439
 440        adau->pll_freq = freq_out;
 441
 442        return 0;
 443}
 444
 445static int adau17x1_set_dai_sysclk(struct snd_soc_dai *dai,
 446                int clk_id, unsigned int freq, int dir)
 447{
 448        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(dai->codec);
 449        struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
 450
 451        switch (clk_id) {
 452        case ADAU17X1_CLK_SRC_MCLK:
 453        case ADAU17X1_CLK_SRC_PLL:
 454                break;
 455        default:
 456                return -EINVAL;
 457        }
 458
 459        adau->sysclk = freq;
 460
 461        if (adau->clk_src != clk_id) {
 462                if (clk_id == ADAU17X1_CLK_SRC_PLL) {
 463                        snd_soc_dapm_add_routes(dapm,
 464                                &adau17x1_dapm_pll_route, 1);
 465                } else {
 466                        snd_soc_dapm_del_routes(dapm,
 467                                &adau17x1_dapm_pll_route, 1);
 468                }
 469        }
 470
 471        adau->clk_src = clk_id;
 472
 473        return 0;
 474}
 475
 476static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai,
 477                unsigned int fmt)
 478{
 479        struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
 480        unsigned int ctrl0, ctrl1;
 481        int lrclk_pol;
 482
 483        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 484        case SND_SOC_DAIFMT_CBM_CFM:
 485                ctrl0 = ADAU17X1_SERIAL_PORT0_MASTER;
 486                adau->master = true;
 487                break;
 488        case SND_SOC_DAIFMT_CBS_CFS:
 489                ctrl0 = 0;
 490                adau->master = false;
 491                break;
 492        default:
 493                return -EINVAL;
 494        }
 495
 496        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 497        case SND_SOC_DAIFMT_I2S:
 498                lrclk_pol = 0;
 499                ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1;
 500                break;
 501        case SND_SOC_DAIFMT_LEFT_J:
 502        case SND_SOC_DAIFMT_RIGHT_J:
 503                lrclk_pol = 1;
 504                ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0;
 505                break;
 506        case SND_SOC_DAIFMT_DSP_A:
 507                lrclk_pol = 1;
 508                ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE;
 509                ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY1;
 510                break;
 511        case SND_SOC_DAIFMT_DSP_B:
 512                lrclk_pol = 1;
 513                ctrl0 |= ADAU17X1_SERIAL_PORT0_PULSE_MODE;
 514                ctrl1 = ADAU17X1_SERIAL_PORT1_DELAY0;
 515                break;
 516        default:
 517                return -EINVAL;
 518        }
 519
 520        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 521        case SND_SOC_DAIFMT_NB_NF:
 522                break;
 523        case SND_SOC_DAIFMT_IB_NF:
 524                ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
 525                break;
 526        case SND_SOC_DAIFMT_NB_IF:
 527                lrclk_pol = !lrclk_pol;
 528                break;
 529        case SND_SOC_DAIFMT_IB_IF:
 530                ctrl0 |= ADAU17X1_SERIAL_PORT0_BCLK_POL;
 531                lrclk_pol = !lrclk_pol;
 532                break;
 533        default:
 534                return -EINVAL;
 535        }
 536
 537        if (lrclk_pol)
 538                ctrl0 |= ADAU17X1_SERIAL_PORT0_LRCLK_POL;
 539
 540        regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT0, ctrl0);
 541        regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT1, ctrl1);
 542
 543        adau->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 544
 545        return 0;
 546}
 547
 548static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai,
 549        unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 550{
 551        struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
 552        unsigned int ser_ctrl0, ser_ctrl1;
 553        unsigned int conv_ctrl0, conv_ctrl1;
 554
 555        /* I2S mode */
 556        if (slots == 0) {
 557                slots = 2;
 558                rx_mask = 3;
 559                tx_mask = 3;
 560                slot_width = 32;
 561        }
 562
 563        switch (slots) {
 564        case 2:
 565                ser_ctrl0 = ADAU17X1_SERIAL_PORT0_STEREO;
 566                break;
 567        case 4:
 568                ser_ctrl0 = ADAU17X1_SERIAL_PORT0_TDM4;
 569                break;
 570        case 8:
 571                if (adau->type == ADAU1361)
 572                        return -EINVAL;
 573
 574                ser_ctrl0 = ADAU17X1_SERIAL_PORT0_TDM8;
 575                break;
 576        default:
 577                return -EINVAL;
 578        }
 579
 580        switch (slot_width * slots) {
 581        case 32:
 582                if (adau->type == ADAU1761)
 583                        return -EINVAL;
 584
 585                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK32;
 586                break;
 587        case 64:
 588                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK64;
 589                break;
 590        case 48:
 591                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK48;
 592                break;
 593        case 128:
 594                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK128;
 595                break;
 596        case 256:
 597                if (adau->type == ADAU1361)
 598                        return -EINVAL;
 599
 600                ser_ctrl1 = ADAU17X1_SERIAL_PORT1_BCLK256;
 601                break;
 602        default:
 603                return -EINVAL;
 604        }
 605
 606        switch (rx_mask) {
 607        case 0x03:
 608                conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(1);
 609                adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 0;
 610                break;
 611        case 0x0c:
 612                conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(2);
 613                adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 1;
 614                break;
 615        case 0x30:
 616                conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(3);
 617                adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 2;
 618                break;
 619        case 0xc0:
 620                conv_ctrl1 = ADAU17X1_CONVERTER1_ADC_PAIR(4);
 621                adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] = 3;
 622                break;
 623        default:
 624                return -EINVAL;
 625        }
 626
 627        switch (tx_mask) {
 628        case 0x03:
 629                conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(1);
 630                adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 0;
 631                break;
 632        case 0x0c:
 633                conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(2);
 634                adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 1;
 635                break;
 636        case 0x30:
 637                conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(3);
 638                adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 2;
 639                break;
 640        case 0xc0:
 641                conv_ctrl0 = ADAU17X1_CONVERTER0_DAC_PAIR(4);
 642                adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] = 3;
 643                break;
 644        default:
 645                return -EINVAL;
 646        }
 647
 648        regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
 649                ADAU17X1_CONVERTER0_DAC_PAIR_MASK, conv_ctrl0);
 650        regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER1,
 651                ADAU17X1_CONVERTER1_ADC_PAIR_MASK, conv_ctrl1);
 652        regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT0,
 653                ADAU17X1_SERIAL_PORT0_TDM_MASK, ser_ctrl0);
 654        regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1,
 655                ADAU17X1_SERIAL_PORT1_BCLK_MASK, ser_ctrl1);
 656
 657        if (!adau17x1_has_dsp(adau))
 658                return 0;
 659
 660        if (adau->dsp_bypass[SNDRV_PCM_STREAM_PLAYBACK]) {
 661                regmap_write(adau->regmap, ADAU17X1_SERIAL_INPUT_ROUTE,
 662                        (adau->tdm_slot[SNDRV_PCM_STREAM_PLAYBACK] * 2) + 1);
 663        }
 664
 665        if (adau->dsp_bypass[SNDRV_PCM_STREAM_CAPTURE]) {
 666                regmap_write(adau->regmap, ADAU17X1_SERIAL_OUTPUT_ROUTE,
 667                        (adau->tdm_slot[SNDRV_PCM_STREAM_CAPTURE] * 2) + 1);
 668        }
 669
 670        return 0;
 671}
 672
 673static int adau17x1_startup(struct snd_pcm_substream *substream,
 674        struct snd_soc_dai *dai)
 675{
 676        struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);
 677
 678        if (adau->sigmadsp)
 679                return sigmadsp_restrict_params(adau->sigmadsp, substream);
 680
 681        return 0;
 682}
 683
 684const struct snd_soc_dai_ops adau17x1_dai_ops = {
 685        .hw_params      = adau17x1_hw_params,
 686        .set_sysclk     = adau17x1_set_dai_sysclk,
 687        .set_fmt        = adau17x1_set_dai_fmt,
 688        .set_pll        = adau17x1_set_dai_pll,
 689        .set_tdm_slot   = adau17x1_set_dai_tdm_slot,
 690        .startup        = adau17x1_startup,
 691};
 692EXPORT_SYMBOL_GPL(adau17x1_dai_ops);
 693
 694int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
 695        enum adau17x1_micbias_voltage micbias)
 696{
 697        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 698
 699        switch (micbias) {
 700        case ADAU17X1_MICBIAS_0_90_AVDD:
 701        case ADAU17X1_MICBIAS_0_65_AVDD:
 702                break;
 703        default:
 704                return -EINVAL;
 705        }
 706
 707        return regmap_write(adau->regmap, ADAU17X1_MICBIAS, micbias << 2);
 708}
 709EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage);
 710
 711bool adau17x1_precious_register(struct device *dev, unsigned int reg)
 712{
 713        /* SigmaDSP parameter memory */
 714        if (reg < 0x400)
 715                return true;
 716
 717        return false;
 718}
 719EXPORT_SYMBOL_GPL(adau17x1_precious_register);
 720
 721bool adau17x1_readable_register(struct device *dev, unsigned int reg)
 722{
 723        /* SigmaDSP parameter memory */
 724        if (reg < 0x400)
 725                return true;
 726
 727        switch (reg) {
 728        case ADAU17X1_CLOCK_CONTROL:
 729        case ADAU17X1_PLL_CONTROL:
 730        case ADAU17X1_REC_POWER_MGMT:
 731        case ADAU17X1_MICBIAS:
 732        case ADAU17X1_SERIAL_PORT0:
 733        case ADAU17X1_SERIAL_PORT1:
 734        case ADAU17X1_CONVERTER0:
 735        case ADAU17X1_CONVERTER1:
 736        case ADAU17X1_LEFT_INPUT_DIGITAL_VOL:
 737        case ADAU17X1_RIGHT_INPUT_DIGITAL_VOL:
 738        case ADAU17X1_ADC_CONTROL:
 739        case ADAU17X1_PLAY_POWER_MGMT:
 740        case ADAU17X1_DAC_CONTROL0:
 741        case ADAU17X1_DAC_CONTROL1:
 742        case ADAU17X1_DAC_CONTROL2:
 743        case ADAU17X1_SERIAL_PORT_PAD:
 744        case ADAU17X1_CONTROL_PORT_PAD0:
 745        case ADAU17X1_CONTROL_PORT_PAD1:
 746        case ADAU17X1_DSP_SAMPLING_RATE:
 747        case ADAU17X1_SERIAL_INPUT_ROUTE:
 748        case ADAU17X1_SERIAL_OUTPUT_ROUTE:
 749        case ADAU17X1_DSP_ENABLE:
 750        case ADAU17X1_DSP_RUN:
 751        case ADAU17X1_SERIAL_SAMPLING_RATE:
 752                return true;
 753        default:
 754                break;
 755        }
 756        return false;
 757}
 758EXPORT_SYMBOL_GPL(adau17x1_readable_register);
 759
 760bool adau17x1_volatile_register(struct device *dev, unsigned int reg)
 761{
 762        /* SigmaDSP parameter and program memory */
 763        if (reg < 0x4000)
 764                return true;
 765
 766        switch (reg) {
 767        /* The PLL register is 6 bytes long */
 768        case ADAU17X1_PLL_CONTROL:
 769        case ADAU17X1_PLL_CONTROL + 1:
 770        case ADAU17X1_PLL_CONTROL + 2:
 771        case ADAU17X1_PLL_CONTROL + 3:
 772        case ADAU17X1_PLL_CONTROL + 4:
 773        case ADAU17X1_PLL_CONTROL + 5:
 774                return true;
 775        default:
 776                break;
 777        }
 778
 779        return false;
 780}
 781EXPORT_SYMBOL_GPL(adau17x1_volatile_register);
 782
 783int adau17x1_setup_firmware(struct adau *adau, unsigned int rate)
 784{
 785        int ret;
 786        int dspsr;
 787
 788        ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr);
 789        if (ret)
 790                return ret;
 791
 792        regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
 793        regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);
 794
 795        ret = sigmadsp_setup(adau->sigmadsp, rate);
 796        if (ret) {
 797                regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
 798                return ret;
 799        }
 800        regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr);
 801
 802        return 0;
 803}
 804EXPORT_SYMBOL_GPL(adau17x1_setup_firmware);
 805
 806int adau17x1_add_widgets(struct snd_soc_codec *codec)
 807{
 808        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 809        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 810        int ret;
 811
 812        ret = snd_soc_add_codec_controls(codec, adau17x1_controls,
 813                ARRAY_SIZE(adau17x1_controls));
 814        if (ret)
 815                return ret;
 816        ret = snd_soc_dapm_new_controls(dapm, adau17x1_dapm_widgets,
 817                ARRAY_SIZE(adau17x1_dapm_widgets));
 818        if (ret)
 819                return ret;
 820
 821        if (adau17x1_has_dsp(adau)) {
 822                ret = snd_soc_dapm_new_controls(dapm, adau17x1_dsp_dapm_widgets,
 823                        ARRAY_SIZE(adau17x1_dsp_dapm_widgets));
 824                if (ret)
 825                        return ret;
 826
 827                if (!adau->sigmadsp)
 828                        return 0;
 829
 830                ret = sigmadsp_attach(adau->sigmadsp, &codec->component);
 831                if (ret) {
 832                        dev_err(codec->dev, "Failed to attach firmware: %d\n",
 833                                ret);
 834                        return ret;
 835                }
 836        }
 837
 838        return 0;
 839}
 840EXPORT_SYMBOL_GPL(adau17x1_add_widgets);
 841
 842int adau17x1_add_routes(struct snd_soc_codec *codec)
 843{
 844        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 845        struct adau *adau = snd_soc_codec_get_drvdata(codec);
 846        int ret;
 847
 848        ret = snd_soc_dapm_add_routes(dapm, adau17x1_dapm_routes,
 849                ARRAY_SIZE(adau17x1_dapm_routes));
 850        if (ret)
 851                return ret;
 852
 853        if (adau17x1_has_dsp(adau)) {
 854                ret = snd_soc_dapm_add_routes(dapm, adau17x1_dsp_dapm_routes,
 855                        ARRAY_SIZE(adau17x1_dsp_dapm_routes));
 856        } else {
 857                ret = snd_soc_dapm_add_routes(dapm, 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