linux/sound/soc/codecs/uda134x.c
<<
>>
Prefs
   1/*
   2 * uda134x.c  --  UDA134X ALSA SoC Codec driver
   3 *
   4 * Modifications by Christian Pellegrin <chripell@evolware.org>
   5 *
   6 * Copyright 2007 Dension Audio Systems Ltd.
   7 * Author: Zoltan Devai
   8 *
   9 * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License version 2 as
  13 * published by the Free Software Foundation.
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/delay.h>
  18#include <linux/slab.h>
  19#include <sound/pcm.h>
  20#include <sound/pcm_params.h>
  21#include <sound/soc.h>
  22#include <sound/initval.h>
  23
  24#include <sound/uda134x.h>
  25#include <sound/l3.h>
  26
  27#include "uda134x.h"
  28
  29
  30#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
  31#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
  32                SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
  33
  34struct uda134x_priv {
  35        int sysclk;
  36        int dai_fmt;
  37
  38        struct snd_pcm_substream *master_substream;
  39        struct snd_pcm_substream *slave_substream;
  40
  41        struct regmap *regmap;
  42        struct uda134x_platform_data *pd;
  43};
  44
  45static const struct reg_default uda134x_reg_defaults[] = {
  46        { UDA134X_EA000, 0x04 },
  47        { UDA134X_EA001, 0x04 },
  48        { UDA134X_EA010, 0x04 },
  49        { UDA134X_EA011, 0x00 },
  50        { UDA134X_EA100, 0x00 },
  51        { UDA134X_EA101, 0x00 },
  52        { UDA134X_EA110, 0x00 },
  53        { UDA134X_EA111, 0x00 },
  54        { UDA134X_STATUS0, 0x00 },
  55        { UDA134X_STATUS1, 0x03 },
  56        { UDA134X_DATA000, 0x00 },
  57        { UDA134X_DATA001, 0x00 },
  58        { UDA134X_DATA010, 0x00 },
  59        { UDA134X_DATA011, 0x00 },
  60        { UDA134X_DATA1, 0x00 },
  61};
  62
  63/*
  64 * Write to the uda134x registers
  65 *
  66 */
  67static int uda134x_regmap_write(void *context, unsigned int reg,
  68        unsigned int value)
  69{
  70        struct uda134x_platform_data *pd = context;
  71        int ret;
  72        u8 addr;
  73        u8 data = value;
  74
  75        switch (reg) {
  76        case UDA134X_STATUS0:
  77        case UDA134X_STATUS1:
  78                addr = UDA134X_STATUS_ADDR;
  79                data |= (reg - UDA134X_STATUS0) << 7;
  80                break;
  81        case UDA134X_DATA000:
  82        case UDA134X_DATA001:
  83        case UDA134X_DATA010:
  84        case UDA134X_DATA011:
  85                addr = UDA134X_DATA0_ADDR;
  86                data |= (reg - UDA134X_DATA000) << 6;
  87                break;
  88        case UDA134X_DATA1:
  89                addr = UDA134X_DATA1_ADDR;
  90                break;
  91        default:
  92                /* It's an extended address register */
  93                addr =  (reg | UDA134X_EXTADDR_PREFIX);
  94
  95                ret = l3_write(&pd->l3,
  96                               UDA134X_DATA0_ADDR, &addr, 1);
  97                if (ret != 1)
  98                        return -EIO;
  99
 100                addr = UDA134X_DATA0_ADDR;
 101                data = (value | UDA134X_EXTDATA_PREFIX);
 102                break;
 103        }
 104
 105        ret = l3_write(&pd->l3,
 106                       addr, &data, 1);
 107        if (ret != 1)
 108                return -EIO;
 109
 110        return 0;
 111}
 112
 113static inline void uda134x_reset(struct snd_soc_codec *codec)
 114{
 115        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 116        unsigned int mask = 1<<6;
 117
 118        regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, mask);
 119        msleep(1);
 120        regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, 0);
 121}
 122
 123static int uda134x_mute(struct snd_soc_dai *dai, int mute)
 124{
 125        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(dai->codec);
 126        unsigned int mask = 1<<2;
 127        unsigned int val;
 128
 129        pr_debug("%s mute: %d\n", __func__, mute);
 130
 131        if (mute)
 132                val = mask;
 133        else
 134                val = 0;
 135
 136        return regmap_update_bits(uda134x->regmap, UDA134X_DATA010, mask, val);
 137}
 138
 139static int uda134x_startup(struct snd_pcm_substream *substream,
 140        struct snd_soc_dai *dai)
 141{
 142        struct snd_soc_codec *codec = dai->codec;
 143        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 144        struct snd_pcm_runtime *master_runtime;
 145
 146        if (uda134x->master_substream) {
 147                master_runtime = uda134x->master_substream->runtime;
 148
 149                pr_debug("%s constraining to %d bits at %d\n", __func__,
 150                         master_runtime->sample_bits,
 151                         master_runtime->rate);
 152
 153                snd_pcm_hw_constraint_single(substream->runtime,
 154                                             SNDRV_PCM_HW_PARAM_RATE,
 155                                             master_runtime->rate);
 156
 157                snd_pcm_hw_constraint_single(substream->runtime,
 158                                             SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
 159                                             master_runtime->sample_bits);
 160
 161                uda134x->slave_substream = substream;
 162        } else
 163                uda134x->master_substream = substream;
 164
 165        return 0;
 166}
 167
 168static void uda134x_shutdown(struct snd_pcm_substream *substream,
 169        struct snd_soc_dai *dai)
 170{
 171        struct snd_soc_codec *codec = dai->codec;
 172        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 173
 174        if (uda134x->master_substream == substream)
 175                uda134x->master_substream = uda134x->slave_substream;
 176
 177        uda134x->slave_substream = NULL;
 178}
 179
 180static int uda134x_hw_params(struct snd_pcm_substream *substream,
 181        struct snd_pcm_hw_params *params,
 182        struct snd_soc_dai *dai)
 183{
 184        struct snd_soc_codec *codec = dai->codec;
 185        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 186        unsigned int hw_params = 0;
 187
 188        if (substream == uda134x->slave_substream) {
 189                pr_debug("%s ignoring hw_params for slave substream\n",
 190                         __func__);
 191                return 0;
 192        }
 193
 194        pr_debug("%s sysclk: %d, rate:%d\n", __func__,
 195                 uda134x->sysclk, params_rate(params));
 196
 197        /* set SYSCLK / fs ratio */
 198        switch (uda134x->sysclk / params_rate(params)) {
 199        case 512:
 200                break;
 201        case 384:
 202                hw_params |= (1<<4);
 203                break;
 204        case 256:
 205                hw_params |= (1<<5);
 206                break;
 207        default:
 208                printk(KERN_ERR "%s unsupported fs\n", __func__);
 209                return -EINVAL;
 210        }
 211
 212        pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
 213                 uda134x->dai_fmt, params_format(params));
 214
 215        /* set DAI format and word length */
 216        switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 217        case SND_SOC_DAIFMT_I2S:
 218                break;
 219        case SND_SOC_DAIFMT_RIGHT_J:
 220                switch (params_width(params)) {
 221                case 16:
 222                        hw_params |= (1<<1);
 223                        break;
 224                case 18:
 225                        hw_params |= (1<<2);
 226                        break;
 227                case 20:
 228                        hw_params |= ((1<<2) | (1<<1));
 229                        break;
 230                default:
 231                        printk(KERN_ERR "%s unsupported format (right)\n",
 232                               __func__);
 233                        return -EINVAL;
 234                }
 235                break;
 236        case SND_SOC_DAIFMT_LEFT_J:
 237                hw_params |= (1<<3);
 238                break;
 239        default:
 240                printk(KERN_ERR "%s unsupported format\n", __func__);
 241                return -EINVAL;
 242        }
 243
 244        return regmap_update_bits(uda134x->regmap, UDA134X_STATUS0,
 245                STATUS0_SYSCLK_MASK | STATUS0_DAIFMT_MASK, hw_params);
 246}
 247
 248static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 249                                  int clk_id, unsigned int freq, int dir)
 250{
 251        struct snd_soc_codec *codec = codec_dai->codec;
 252        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 253
 254        pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
 255                 clk_id, freq, dir);
 256
 257        /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
 258           because the codec is slave. Of course limitations of the clock
 259           master (the IIS controller) apply.
 260           We'll error out on set_hw_params if it's not OK */
 261        if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
 262                uda134x->sysclk = freq;
 263                return 0;
 264        }
 265
 266        printk(KERN_ERR "%s unsupported sysclk\n", __func__);
 267        return -EINVAL;
 268}
 269
 270static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
 271                               unsigned int fmt)
 272{
 273        struct snd_soc_codec *codec = codec_dai->codec;
 274        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 275
 276        pr_debug("%s fmt: %08X\n", __func__, fmt);
 277
 278        /* codec supports only full slave mode */
 279        if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
 280                printk(KERN_ERR "%s unsupported slave mode\n", __func__);
 281                return -EINVAL;
 282        }
 283
 284        /* no support for clock inversion */
 285        if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
 286                printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
 287                return -EINVAL;
 288        }
 289
 290        /* We can't setup DAI format here as it depends on the word bit num */
 291        /* so let's just store the value for later */
 292        uda134x->dai_fmt = fmt;
 293
 294        return 0;
 295}
 296
 297static int uda134x_set_bias_level(struct snd_soc_codec *codec,
 298                                  enum snd_soc_bias_level level)
 299{
 300        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 301        struct uda134x_platform_data *pd = uda134x->pd;
 302        pr_debug("%s bias level %d\n", __func__, level);
 303
 304        switch (level) {
 305        case SND_SOC_BIAS_ON:
 306                break;
 307        case SND_SOC_BIAS_PREPARE:
 308                /* power on */
 309                if (pd->power) {
 310                        pd->power(1);
 311                        regcache_sync(uda134x->regmap);
 312                }
 313                break;
 314        case SND_SOC_BIAS_STANDBY:
 315                break;
 316        case SND_SOC_BIAS_OFF:
 317                /* power off */
 318                if (pd->power) {
 319                        pd->power(0);
 320                        regcache_mark_dirty(uda134x->regmap);
 321                }
 322                break;
 323        }
 324        return 0;
 325}
 326
 327static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
 328                                            "Minimum2", "Maximum"};
 329static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
 330static const char *uda134x_mixmode[] = {"Differential", "Analog1",
 331                                        "Analog2", "Both"};
 332
 333static const struct soc_enum uda134x_mixer_enum[] = {
 334SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
 335SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
 336SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
 337};
 338
 339static const struct snd_kcontrol_new uda1341_snd_controls[] = {
 340SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
 341SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
 342SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
 343SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),
 344
 345SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
 346SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),
 347
 348SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
 349SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
 350
 351SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
 352SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
 353SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),
 354
 355SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
 356SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
 357SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),
 358
 359SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
 360SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
 361SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
 362SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
 363SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
 364SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
 365};
 366
 367static const struct snd_kcontrol_new uda1340_snd_controls[] = {
 368SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
 369
 370SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
 371SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
 372
 373SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
 374SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
 375
 376SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
 377};
 378
 379static const struct snd_kcontrol_new uda1345_snd_controls[] = {
 380SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
 381
 382SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
 383
 384SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
 385};
 386
 387/* UDA1341 has the DAC/ADC power down in STATUS1 */
 388static const struct snd_soc_dapm_widget uda1341_dapm_widgets[] = {
 389        SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_STATUS1, 0, 0),
 390        SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_STATUS1, 1, 0),
 391};
 392
 393/* UDA1340/4/5 has the DAC/ADC pwoer down in DATA0 11 */
 394static const struct snd_soc_dapm_widget uda1340_dapm_widgets[] = {
 395        SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_DATA011, 0, 0),
 396        SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_DATA011, 1, 0),
 397};
 398
 399/* Common DAPM widgets */
 400static const struct snd_soc_dapm_widget uda134x_dapm_widgets[] = {
 401        SND_SOC_DAPM_INPUT("VINL1"),
 402        SND_SOC_DAPM_INPUT("VINR1"),
 403        SND_SOC_DAPM_INPUT("VINL2"),
 404        SND_SOC_DAPM_INPUT("VINR2"),
 405        SND_SOC_DAPM_OUTPUT("VOUTL"),
 406        SND_SOC_DAPM_OUTPUT("VOUTR"),
 407};
 408
 409static const struct snd_soc_dapm_route uda134x_dapm_routes[] = {
 410        { "ADC", NULL, "VINL1" },
 411        { "ADC", NULL, "VINR1" },
 412        { "ADC", NULL, "VINL2" },
 413        { "ADC", NULL, "VINR2" },
 414        { "VOUTL", NULL, "DAC" },
 415        { "VOUTR", NULL, "DAC" },
 416};
 417
 418static const struct snd_soc_dai_ops uda134x_dai_ops = {
 419        .startup        = uda134x_startup,
 420        .shutdown       = uda134x_shutdown,
 421        .hw_params      = uda134x_hw_params,
 422        .digital_mute   = uda134x_mute,
 423        .set_sysclk     = uda134x_set_dai_sysclk,
 424        .set_fmt        = uda134x_set_dai_fmt,
 425};
 426
 427static struct snd_soc_dai_driver uda134x_dai = {
 428        .name = "uda134x-hifi",
 429        /* playback capabilities */
 430        .playback = {
 431                .stream_name = "Playback",
 432                .channels_min = 1,
 433                .channels_max = 2,
 434                .rates = UDA134X_RATES,
 435                .formats = UDA134X_FORMATS,
 436        },
 437        /* capture capabilities */
 438        .capture = {
 439                .stream_name = "Capture",
 440                .channels_min = 1,
 441                .channels_max = 2,
 442                .rates = UDA134X_RATES,
 443                .formats = UDA134X_FORMATS,
 444        },
 445        /* pcm operations */
 446        .ops = &uda134x_dai_ops,
 447};
 448
 449static int uda134x_soc_probe(struct snd_soc_codec *codec)
 450{
 451        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 452        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 453        struct uda134x_platform_data *pd = uda134x->pd;
 454        const struct snd_soc_dapm_widget *widgets;
 455        unsigned num_widgets;
 456        int ret;
 457
 458        printk(KERN_INFO "UDA134X SoC Audio Codec\n");
 459
 460        switch (pd->model) {
 461        case UDA134X_UDA1340:
 462        case UDA134X_UDA1341:
 463        case UDA134X_UDA1344:
 464        case UDA134X_UDA1345:
 465                break;
 466        default:
 467                printk(KERN_ERR "UDA134X SoC codec: "
 468                       "unsupported model %d\n",
 469                        pd->model);
 470                return -EINVAL;
 471        }
 472
 473        if (pd->power)
 474                pd->power(1);
 475
 476        uda134x_reset(codec);
 477
 478        if (pd->model == UDA134X_UDA1341) {
 479                widgets = uda1341_dapm_widgets;
 480                num_widgets = ARRAY_SIZE(uda1341_dapm_widgets);
 481        } else {
 482                widgets = uda1340_dapm_widgets;
 483                num_widgets = ARRAY_SIZE(uda1340_dapm_widgets);
 484        }
 485
 486        ret = snd_soc_dapm_new_controls(dapm, widgets, num_widgets);
 487        if (ret) {
 488                printk(KERN_ERR "%s failed to register dapm controls: %d",
 489                        __func__, ret);
 490                return ret;
 491        }
 492
 493        switch (pd->model) {
 494        case UDA134X_UDA1340:
 495        case UDA134X_UDA1344:
 496                ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
 497                                        ARRAY_SIZE(uda1340_snd_controls));
 498        break;
 499        case UDA134X_UDA1341:
 500                ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
 501                                        ARRAY_SIZE(uda1341_snd_controls));
 502        break;
 503        case UDA134X_UDA1345:
 504                ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
 505                                        ARRAY_SIZE(uda1345_snd_controls));
 506        break;
 507        default:
 508                printk(KERN_ERR "%s unknown codec type: %d",
 509                        __func__, pd->model);
 510                return -EINVAL;
 511        }
 512
 513        if (ret < 0) {
 514                printk(KERN_ERR "UDA134X: failed to register controls\n");
 515                return ret;
 516        }
 517
 518        return 0;
 519}
 520
 521static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
 522        .probe =        uda134x_soc_probe,
 523        .set_bias_level = uda134x_set_bias_level,
 524        .suspend_bias_off = true,
 525
 526        .dapm_widgets = uda134x_dapm_widgets,
 527        .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets),
 528        .dapm_routes = uda134x_dapm_routes,
 529        .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
 530};
 531
 532static const struct regmap_config uda134x_regmap_config = {
 533        .reg_bits = 8,
 534        .val_bits = 8,
 535        .max_register = UDA134X_DATA1,
 536        .reg_defaults = uda134x_reg_defaults,
 537        .num_reg_defaults = ARRAY_SIZE(uda134x_reg_defaults),
 538        .cache_type = REGCACHE_RBTREE,
 539
 540        .reg_write = uda134x_regmap_write,
 541};
 542
 543static int uda134x_codec_probe(struct platform_device *pdev)
 544{
 545        struct uda134x_platform_data *pd = pdev->dev.platform_data;
 546        struct uda134x_priv *uda134x;
 547
 548        if (!pd) {
 549                dev_err(&pdev->dev, "Missing L3 bitbang function\n");
 550                return -ENODEV;
 551        }
 552
 553        uda134x = devm_kzalloc(&pdev->dev, sizeof(*uda134x), GFP_KERNEL);
 554        if (!uda134x)
 555                return -ENOMEM;
 556
 557        uda134x->pd = pd;
 558        platform_set_drvdata(pdev, uda134x);
 559
 560        uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd,
 561                &uda134x_regmap_config);
 562        if (IS_ERR(uda134x->regmap))
 563                return PTR_ERR(uda134x->regmap);
 564
 565        return snd_soc_register_codec(&pdev->dev,
 566                        &soc_codec_dev_uda134x, &uda134x_dai, 1);
 567}
 568
 569static int uda134x_codec_remove(struct platform_device *pdev)
 570{
 571        snd_soc_unregister_codec(&pdev->dev);
 572        return 0;
 573}
 574
 575static struct platform_driver uda134x_codec_driver = {
 576        .driver = {
 577                .name = "uda134x-codec",
 578        },
 579        .probe = uda134x_codec_probe,
 580        .remove = uda134x_codec_remove,
 581};
 582
 583module_platform_driver(uda134x_codec_driver);
 584
 585MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
 586MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
 587MODULE_LICENSE("GPL");
 588