linux/sound/soc/soc-dapm.c
<<
>>
Prefs
   1/*
   2 * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
   3 *
   4 * Copyright 2005 Wolfson Microelectronics PLC.
   5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
   6 *
   7 *  This program is free software; you can redistribute  it and/or modify it
   8 *  under  the terms of  the GNU General  Public License as published by the
   9 *  Free Software Foundation;  either version 2 of the  License, or (at your
  10 *  option) any later version.
  11 *
  12 *  Features:
  13 *    o Changes power status of internal codec blocks depending on the
  14 *      dynamic configuration of codec internal audio paths and active
  15 *      DAC's/ADC's.
  16 *    o Platform power domain - can support external components i.e. amps and
  17 *      mic/meadphone insertion events.
  18 *    o Automatic Mic Bias support
  19 *    o Jack insertion power event initiation - e.g. hp insertion will enable
  20 *      sinks, dacs, etc
  21 *    o Delayed powerdown of audio susbsystem to reduce pops between a quick
  22 *      device reopen.
  23 *
  24 *  Todo:
  25 *    o DAPM power change sequencing - allow for configurable per
  26 *      codec sequences.
  27 *    o Support for analogue bias optimisation.
  28 *    o Support for reduced codec oversampling rates.
  29 *    o Support for reduced codec bias currents.
  30 */
  31
  32#include <linux/module.h>
  33#include <linux/moduleparam.h>
  34#include <linux/init.h>
  35#include <linux/delay.h>
  36#include <linux/pm.h>
  37#include <linux/bitops.h>
  38#include <linux/platform_device.h>
  39#include <linux/jiffies.h>
  40#include <sound/core.h>
  41#include <sound/pcm.h>
  42#include <sound/pcm_params.h>
  43#include <sound/soc-dapm.h>
  44#include <sound/initval.h>
  45
  46/* debug */
  47#ifdef DEBUG
  48#define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
  49#else
  50#define dump_dapm(codec, action)
  51#endif
  52
  53/* dapm power sequences - make this per codec in the future */
  54static int dapm_up_seq[] = {
  55        snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
  56        snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac,
  57        snd_soc_dapm_mixer, snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp,
  58        snd_soc_dapm_spk, snd_soc_dapm_post
  59};
  60static int dapm_down_seq[] = {
  61        snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
  62        snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
  63        snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
  64        snd_soc_dapm_post
  65};
  66
  67static int dapm_status = 1;
  68module_param(dapm_status, int, 0);
  69MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
  70
  71static void pop_wait(u32 pop_time)
  72{
  73        if (pop_time)
  74                schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
  75}
  76
  77static void pop_dbg(u32 pop_time, const char *fmt, ...)
  78{
  79        va_list args;
  80
  81        va_start(args, fmt);
  82
  83        if (pop_time) {
  84                vprintk(fmt, args);
  85                pop_wait(pop_time);
  86        }
  87
  88        va_end(args);
  89}
  90
  91/* create a new dapm widget */
  92static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
  93        const struct snd_soc_dapm_widget *_widget)
  94{
  95        return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
  96}
  97
  98/* set up initial codec paths */
  99static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 100        struct snd_soc_dapm_path *p, int i)
 101{
 102        switch (w->id) {
 103        case snd_soc_dapm_switch:
 104        case snd_soc_dapm_mixer: {
 105                int val;
 106                struct soc_mixer_control *mc = (struct soc_mixer_control *)
 107                        w->kcontrols[i].private_value;
 108                unsigned int reg = mc->reg;
 109                unsigned int shift = mc->shift;
 110                int max = mc->max;
 111                unsigned int mask = (1 << fls(max)) - 1;
 112                unsigned int invert = mc->invert;
 113
 114                val = snd_soc_read(w->codec, reg);
 115                val = (val >> shift) & mask;
 116
 117                if ((invert && !val) || (!invert && val))
 118                        p->connect = 1;
 119                else
 120                        p->connect = 0;
 121        }
 122        break;
 123        case snd_soc_dapm_mux: {
 124                struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
 125                int val, item, bitmask;
 126
 127                for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
 128                ;
 129                val = snd_soc_read(w->codec, e->reg);
 130                item = (val >> e->shift_l) & (bitmask - 1);
 131
 132                p->connect = 0;
 133                for (i = 0; i < e->max; i++) {
 134                        if (!(strcmp(p->name, e->texts[i])) && item == i)
 135                                p->connect = 1;
 136                }
 137        }
 138        break;
 139        case snd_soc_dapm_value_mux: {
 140                struct soc_enum *e = (struct soc_enum *)
 141                        w->kcontrols[i].private_value;
 142                int val, item;
 143
 144                val = snd_soc_read(w->codec, e->reg);
 145                val = (val >> e->shift_l) & e->mask;
 146                for (item = 0; item < e->max; item++) {
 147                        if (val == e->values[item])
 148                                break;
 149                }
 150
 151                p->connect = 0;
 152                for (i = 0; i < e->max; i++) {
 153                        if (!(strcmp(p->name, e->texts[i])) && item == i)
 154                                p->connect = 1;
 155                }
 156        }
 157        break;
 158        /* does not effect routing - always connected */
 159        case snd_soc_dapm_pga:
 160        case snd_soc_dapm_output:
 161        case snd_soc_dapm_adc:
 162        case snd_soc_dapm_input:
 163        case snd_soc_dapm_dac:
 164        case snd_soc_dapm_micbias:
 165        case snd_soc_dapm_vmid:
 166                p->connect = 1;
 167        break;
 168        /* does effect routing - dynamically connected */
 169        case snd_soc_dapm_hp:
 170        case snd_soc_dapm_mic:
 171        case snd_soc_dapm_spk:
 172        case snd_soc_dapm_line:
 173        case snd_soc_dapm_pre:
 174        case snd_soc_dapm_post:
 175                p->connect = 0;
 176        break;
 177        }
 178}
 179
 180/* connect mux widget to it's interconnecting audio paths */
 181static int dapm_connect_mux(struct snd_soc_codec *codec,
 182        struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
 183        struct snd_soc_dapm_path *path, const char *control_name,
 184        const struct snd_kcontrol_new *kcontrol)
 185{
 186        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 187        int i;
 188
 189        for (i = 0; i < e->max; i++) {
 190                if (!(strcmp(control_name, e->texts[i]))) {
 191                        list_add(&path->list, &codec->dapm_paths);
 192                        list_add(&path->list_sink, &dest->sources);
 193                        list_add(&path->list_source, &src->sinks);
 194                        path->name = (char*)e->texts[i];
 195                        dapm_set_path_status(dest, path, 0);
 196                        return 0;
 197                }
 198        }
 199
 200        return -ENODEV;
 201}
 202
 203/* connect mixer widget to it's interconnecting audio paths */
 204static int dapm_connect_mixer(struct snd_soc_codec *codec,
 205        struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
 206        struct snd_soc_dapm_path *path, const char *control_name)
 207{
 208        int i;
 209
 210        /* search for mixer kcontrol */
 211        for (i = 0; i < dest->num_kcontrols; i++) {
 212                if (!strcmp(control_name, dest->kcontrols[i].name)) {
 213                        list_add(&path->list, &codec->dapm_paths);
 214                        list_add(&path->list_sink, &dest->sources);
 215                        list_add(&path->list_source, &src->sinks);
 216                        path->name = dest->kcontrols[i].name;
 217                        dapm_set_path_status(dest, path, i);
 218                        return 0;
 219                }
 220        }
 221        return -ENODEV;
 222}
 223
 224/* update dapm codec register bits */
 225static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
 226{
 227        int change, power;
 228        unsigned short old, new;
 229        struct snd_soc_codec *codec = widget->codec;
 230
 231        /* check for valid widgets */
 232        if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
 233                widget->id == snd_soc_dapm_output ||
 234                widget->id == snd_soc_dapm_hp ||
 235                widget->id == snd_soc_dapm_mic ||
 236                widget->id == snd_soc_dapm_line ||
 237                widget->id == snd_soc_dapm_spk)
 238                return 0;
 239
 240        power = widget->power;
 241        if (widget->invert)
 242                power = (power ? 0:1);
 243
 244        old = snd_soc_read(codec, widget->reg);
 245        new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
 246
 247        change = old != new;
 248        if (change) {
 249                pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n",
 250                        widget->name, widget->power ? "on" : "off",
 251                        codec->pop_time);
 252                snd_soc_write(codec, widget->reg, new);
 253                pop_wait(codec->pop_time);
 254        }
 255        pr_debug("reg %x old %x new %x change %d\n", widget->reg,
 256                 old, new, change);
 257        return change;
 258}
 259
 260/* ramps the volume up or down to minimise pops before or after a
 261 * DAPM power event */
 262static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
 263{
 264        const struct snd_kcontrol_new *k = widget->kcontrols;
 265
 266        if (widget->muted && !power)
 267                return 0;
 268        if (!widget->muted && power)
 269                return 0;
 270
 271        if (widget->num_kcontrols && k) {
 272                struct soc_mixer_control *mc =
 273                        (struct soc_mixer_control *)k->private_value;
 274                unsigned int reg = mc->reg;
 275                unsigned int shift = mc->shift;
 276                int max = mc->max;
 277                unsigned int mask = (1 << fls(max)) - 1;
 278                unsigned int invert = mc->invert;
 279
 280                if (power) {
 281                        int i;
 282                        /* power up has happended, increase volume to last level */
 283                        if (invert) {
 284                                for (i = max; i > widget->saved_value; i--)
 285                                        snd_soc_update_bits(widget->codec, reg, mask, i);
 286                        } else {
 287                                for (i = 0; i < widget->saved_value; i++)
 288                                        snd_soc_update_bits(widget->codec, reg, mask, i);
 289                        }
 290                        widget->muted = 0;
 291                } else {
 292                        /* power down is about to occur, decrease volume to mute */
 293                        int val = snd_soc_read(widget->codec, reg);
 294                        int i = widget->saved_value = (val >> shift) & mask;
 295                        if (invert) {
 296                                for (; i < mask; i++)
 297                                        snd_soc_update_bits(widget->codec, reg, mask, i);
 298                        } else {
 299                                for (; i > 0; i--)
 300                                        snd_soc_update_bits(widget->codec, reg, mask, i);
 301                        }
 302                        widget->muted = 1;
 303                }
 304        }
 305        return 0;
 306}
 307
 308/* create new dapm mixer control */
 309static int dapm_new_mixer(struct snd_soc_codec *codec,
 310        struct snd_soc_dapm_widget *w)
 311{
 312        int i, ret = 0;
 313        size_t name_len;
 314        struct snd_soc_dapm_path *path;
 315
 316        /* add kcontrol */
 317        for (i = 0; i < w->num_kcontrols; i++) {
 318
 319                /* match name */
 320                list_for_each_entry(path, &w->sources, list_sink) {
 321
 322                        /* mixer/mux paths name must match control name */
 323                        if (path->name != (char*)w->kcontrols[i].name)
 324                                continue;
 325
 326                        /* add dapm control with long name */
 327                        name_len = 2 + strlen(w->name)
 328                                + strlen(w->kcontrols[i].name);
 329                        path->long_name = kmalloc(name_len, GFP_KERNEL);
 330                        if (path->long_name == NULL)
 331                                return -ENOMEM;
 332
 333                        snprintf(path->long_name, name_len, "%s %s",
 334                                 w->name, w->kcontrols[i].name);
 335                        path->long_name[name_len - 1] = '\0';
 336
 337                        path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
 338                                path->long_name);
 339                        ret = snd_ctl_add(codec->card, path->kcontrol);
 340                        if (ret < 0) {
 341                                printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n",
 342                                                path->long_name);
 343                                kfree(path->long_name);
 344                                path->long_name = NULL;
 345                                return ret;
 346                        }
 347                }
 348        }
 349        return ret;
 350}
 351
 352/* create new dapm mux control */
 353static int dapm_new_mux(struct snd_soc_codec *codec,
 354        struct snd_soc_dapm_widget *w)
 355{
 356        struct snd_soc_dapm_path *path = NULL;
 357        struct snd_kcontrol *kcontrol;
 358        int ret = 0;
 359
 360        if (!w->num_kcontrols) {
 361                printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
 362                return -EINVAL;
 363        }
 364
 365        kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
 366        ret = snd_ctl_add(codec->card, kcontrol);
 367        if (ret < 0)
 368                goto err;
 369
 370        list_for_each_entry(path, &w->sources, list_sink)
 371                path->kcontrol = kcontrol;
 372
 373        return ret;
 374
 375err:
 376        printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
 377        return ret;
 378}
 379
 380/* create new dapm volume control */
 381static int dapm_new_pga(struct snd_soc_codec *codec,
 382        struct snd_soc_dapm_widget *w)
 383{
 384        struct snd_kcontrol *kcontrol;
 385        int ret = 0;
 386
 387        if (!w->num_kcontrols)
 388                return -EINVAL;
 389
 390        kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
 391        ret = snd_ctl_add(codec->card, kcontrol);
 392        if (ret < 0) {
 393                printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
 394                return ret;
 395        }
 396
 397        return ret;
 398}
 399
 400/* reset 'walked' bit for each dapm path */
 401static inline void dapm_clear_walk(struct snd_soc_codec *codec)
 402{
 403        struct snd_soc_dapm_path *p;
 404
 405        list_for_each_entry(p, &codec->dapm_paths, list)
 406                p->walked = 0;
 407}
 408
 409/*
 410 * Recursively check for a completed path to an active or physically connected
 411 * output widget. Returns number of complete paths.
 412 */
 413static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
 414{
 415        struct snd_soc_dapm_path *path;
 416        int con = 0;
 417
 418        if (widget->id == snd_soc_dapm_adc && widget->active)
 419                return 1;
 420
 421        if (widget->connected) {
 422                /* connected pin ? */
 423                if (widget->id == snd_soc_dapm_output && !widget->ext)
 424                        return 1;
 425
 426                /* connected jack or spk ? */
 427                if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
 428                        widget->id == snd_soc_dapm_line)
 429                        return 1;
 430        }
 431
 432        list_for_each_entry(path, &widget->sinks, list_source) {
 433                if (path->walked)
 434                        continue;
 435
 436                if (path->sink && path->connect) {
 437                        path->walked = 1;
 438                        con += is_connected_output_ep(path->sink);
 439                }
 440        }
 441
 442        return con;
 443}
 444
 445/*
 446 * Recursively check for a completed path to an active or physically connected
 447 * input widget. Returns number of complete paths.
 448 */
 449static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
 450{
 451        struct snd_soc_dapm_path *path;
 452        int con = 0;
 453
 454        /* active stream ? */
 455        if (widget->id == snd_soc_dapm_dac && widget->active)
 456                return 1;
 457
 458        if (widget->connected) {
 459                /* connected pin ? */
 460                if (widget->id == snd_soc_dapm_input && !widget->ext)
 461                        return 1;
 462
 463                /* connected VMID/Bias for lower pops */
 464                if (widget->id == snd_soc_dapm_vmid)
 465                        return 1;
 466
 467                /* connected jack ? */
 468                if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line)
 469                        return 1;
 470        }
 471
 472        list_for_each_entry(path, &widget->sources, list_sink) {
 473                if (path->walked)
 474                        continue;
 475
 476                if (path->source && path->connect) {
 477                        path->walked = 1;
 478                        con += is_connected_input_ep(path->source);
 479                }
 480        }
 481
 482        return con;
 483}
 484
 485/*
 486 * Handler for generic register modifier widget.
 487 */
 488int dapm_reg_event(struct snd_soc_dapm_widget *w,
 489                   struct snd_kcontrol *kcontrol, int event)
 490{
 491        unsigned int val;
 492
 493        if (SND_SOC_DAPM_EVENT_ON(event))
 494                val = w->on_val;
 495        else
 496                val = w->off_val;
 497
 498        snd_soc_update_bits(w->codec, -(w->reg + 1),
 499                            w->mask << w->shift, val << w->shift);
 500
 501        return 0;
 502}
 503EXPORT_SYMBOL_GPL(dapm_reg_event);
 504
 505/*
 506 * Scan each dapm widget for complete audio path.
 507 * A complete path is a route that has valid endpoints i.e.:-
 508 *
 509 *  o DAC to output pin.
 510 *  o Input Pin to ADC.
 511 *  o Input pin to Output pin (bypass, sidetone)
 512 *  o DAC to ADC (loopback).
 513 */
 514static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
 515{
 516        struct snd_soc_dapm_widget *w;
 517        int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;
 518
 519        /* do we have a sequenced stream event */
 520        if (event == SND_SOC_DAPM_STREAM_START) {
 521                c = ARRAY_SIZE(dapm_up_seq);
 522                seq = dapm_up_seq;
 523        } else if (event == SND_SOC_DAPM_STREAM_STOP) {
 524                c = ARRAY_SIZE(dapm_down_seq);
 525                seq = dapm_down_seq;
 526        }
 527
 528        for(i = 0; i < c; i++) {
 529                list_for_each_entry(w, &codec->dapm_widgets, list) {
 530
 531                        /* is widget in stream order */
 532                        if (seq && seq[i] && w->id != seq[i])
 533                                continue;
 534
 535                        /* vmid - no action */
 536                        if (w->id == snd_soc_dapm_vmid)
 537                                continue;
 538
 539                        /* active ADC */
 540                        if (w->id == snd_soc_dapm_adc && w->active) {
 541                                in = is_connected_input_ep(w);
 542                                dapm_clear_walk(w->codec);
 543                                w->power = (in != 0) ? 1 : 0;
 544                                dapm_update_bits(w);
 545                                continue;
 546                        }
 547
 548                        /* active DAC */
 549                        if (w->id == snd_soc_dapm_dac && w->active) {
 550                                out = is_connected_output_ep(w);
 551                                dapm_clear_walk(w->codec);
 552                                w->power = (out != 0) ? 1 : 0;
 553                                dapm_update_bits(w);
 554                                continue;
 555                        }
 556
 557                        /* pre and post event widgets */
 558                        if (w->id == snd_soc_dapm_pre) {
 559                                if (!w->event)
 560                                        continue;
 561
 562                                if (event == SND_SOC_DAPM_STREAM_START) {
 563                                        ret = w->event(w,
 564                                                NULL, SND_SOC_DAPM_PRE_PMU);
 565                                        if (ret < 0)
 566                                                return ret;
 567                                } else if (event == SND_SOC_DAPM_STREAM_STOP) {
 568                                        ret = w->event(w,
 569                                                NULL, SND_SOC_DAPM_PRE_PMD);
 570                                        if (ret < 0)
 571                                                return ret;
 572                                }
 573                                continue;
 574                        }
 575                        if (w->id == snd_soc_dapm_post) {
 576                                if (!w->event)
 577                                        continue;
 578
 579                                if (event == SND_SOC_DAPM_STREAM_START) {
 580                                        ret = w->event(w,
 581                                                NULL, SND_SOC_DAPM_POST_PMU);
 582                                        if (ret < 0)
 583                                                return ret;
 584                                } else if (event == SND_SOC_DAPM_STREAM_STOP) {
 585                                        ret = w->event(w,
 586                                                NULL, SND_SOC_DAPM_POST_PMD);
 587                                        if (ret < 0)
 588                                                return ret;
 589                                }
 590                                continue;
 591                        }
 592
 593                        /* all other widgets */
 594                        in = is_connected_input_ep(w);
 595                        dapm_clear_walk(w->codec);
 596                        out = is_connected_output_ep(w);
 597                        dapm_clear_walk(w->codec);
 598                        power = (out != 0 && in != 0) ? 1 : 0;
 599                        power_change = (w->power == power) ? 0: 1;
 600                        w->power = power;
 601
 602                        if (!power_change)
 603                                continue;
 604
 605                        /* call any power change event handlers */
 606                        if (w->event)
 607                                pr_debug("power %s event for %s flags %x\n",
 608                                         w->power ? "on" : "off",
 609                                         w->name, w->event_flags);
 610
 611                        /* power up pre event */
 612                        if (power && w->event &&
 613                            (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
 614                                ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
 615                                if (ret < 0)
 616                                        return ret;
 617                        }
 618
 619                        /* power down pre event */
 620                        if (!power && w->event &&
 621                            (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
 622                                ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
 623                                if (ret < 0)
 624                                        return ret;
 625                        }
 626
 627                        /* Lower PGA volume to reduce pops */
 628                        if (w->id == snd_soc_dapm_pga && !power)
 629                                dapm_set_pga(w, power);
 630
 631                        dapm_update_bits(w);
 632
 633                        /* Raise PGA volume to reduce pops */
 634                        if (w->id == snd_soc_dapm_pga && power)
 635                                dapm_set_pga(w, power);
 636
 637                        /* power up post event */
 638                        if (power && w->event &&
 639                            (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
 640                                ret = w->event(w,
 641                                               NULL, SND_SOC_DAPM_POST_PMU);
 642                                if (ret < 0)
 643                                        return ret;
 644                        }
 645
 646                        /* power down post event */
 647                        if (!power && w->event &&
 648                            (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
 649                                ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
 650                                if (ret < 0)
 651                                        return ret;
 652                        }
 653                }
 654        }
 655
 656        return ret;
 657}
 658
 659#ifdef DEBUG
 660static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
 661{
 662        struct snd_soc_dapm_widget *w;
 663        struct snd_soc_dapm_path *p = NULL;
 664        int in, out;
 665
 666        printk("DAPM %s %s\n", codec->name, action);
 667
 668        list_for_each_entry(w, &codec->dapm_widgets, list) {
 669
 670                /* only display widgets that effect routing */
 671                switch (w->id) {
 672                case snd_soc_dapm_pre:
 673                case snd_soc_dapm_post:
 674                case snd_soc_dapm_vmid:
 675                        continue;
 676                case snd_soc_dapm_mux:
 677                case snd_soc_dapm_value_mux:
 678                case snd_soc_dapm_output:
 679                case snd_soc_dapm_input:
 680                case snd_soc_dapm_switch:
 681                case snd_soc_dapm_hp:
 682                case snd_soc_dapm_mic:
 683                case snd_soc_dapm_spk:
 684                case snd_soc_dapm_line:
 685                case snd_soc_dapm_micbias:
 686                case snd_soc_dapm_dac:
 687                case snd_soc_dapm_adc:
 688                case snd_soc_dapm_pga:
 689                case snd_soc_dapm_mixer:
 690                        if (w->name) {
 691                                in = is_connected_input_ep(w);
 692                                dapm_clear_walk(w->codec);
 693                                out = is_connected_output_ep(w);
 694                                dapm_clear_walk(w->codec);
 695                                printk("%s: %s  in %d out %d\n", w->name,
 696                                        w->power ? "On":"Off",in, out);
 697
 698                                list_for_each_entry(p, &w->sources, list_sink) {
 699                                        if (p->connect)
 700                                                printk(" in  %s %s\n", p->name ? p->name : "static",
 701                                                        p->source->name);
 702                                }
 703                                list_for_each_entry(p, &w->sinks, list_source) {
 704                                        if (p->connect)
 705                                                printk(" out %s %s\n", p->name ? p->name : "static",
 706                                                        p->sink->name);
 707                                }
 708                        }
 709                break;
 710                }
 711        }
 712}
 713#endif
 714
 715/* test and update the power status of a mux widget */
 716static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 717                                 struct snd_kcontrol *kcontrol, int mask,
 718                                 int mux, int val, struct soc_enum *e)
 719{
 720        struct snd_soc_dapm_path *path;
 721        int found = 0;
 722
 723        if (widget->id != snd_soc_dapm_mux &&
 724            widget->id != snd_soc_dapm_value_mux)
 725                return -ENODEV;
 726
 727        if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
 728                return 0;
 729
 730        /* find dapm widget path assoc with kcontrol */
 731        list_for_each_entry(path, &widget->codec->dapm_paths, list) {
 732                if (path->kcontrol != kcontrol)
 733                        continue;
 734
 735                if (!path->name || !e->texts[mux])
 736                        continue;
 737
 738                found = 1;
 739                /* we now need to match the string in the enum to the path */
 740                if (!(strcmp(path->name, e->texts[mux])))
 741                        path->connect = 1; /* new connection */
 742                else
 743                        path->connect = 0; /* old connection must be powered down */
 744        }
 745
 746        if (found) {
 747                dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
 748                dump_dapm(widget->codec, "mux power update");
 749        }
 750
 751        return 0;
 752}
 753
 754/* test and update the power status of a mixer or switch widget */
 755static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
 756                                   struct snd_kcontrol *kcontrol, int reg,
 757                                   int val_mask, int val, int invert)
 758{
 759        struct snd_soc_dapm_path *path;
 760        int found = 0;
 761
 762        if (widget->id != snd_soc_dapm_mixer &&
 763            widget->id != snd_soc_dapm_switch)
 764                return -ENODEV;
 765
 766        if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
 767                return 0;
 768
 769        /* find dapm widget path assoc with kcontrol */
 770        list_for_each_entry(path, &widget->codec->dapm_paths, list) {
 771                if (path->kcontrol != kcontrol)
 772                        continue;
 773
 774                /* found, now check type */
 775                found = 1;
 776                if (val)
 777                        /* new connection */
 778                        path->connect = invert ? 0:1;
 779                else
 780                        /* old connection must be powered down */
 781                        path->connect = invert ? 1:0;
 782                break;
 783        }
 784
 785        if (found) {
 786                dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
 787                dump_dapm(widget->codec, "mixer power update");
 788        }
 789
 790        return 0;
 791}
 792
 793/* show dapm widget status in sys fs */
 794static ssize_t dapm_widget_show(struct device *dev,
 795        struct device_attribute *attr, char *buf)
 796{
 797        struct snd_soc_device *devdata = dev_get_drvdata(dev);
 798        struct snd_soc_codec *codec = devdata->codec;
 799        struct snd_soc_dapm_widget *w;
 800        int count = 0;
 801        char *state = "not set";
 802
 803        list_for_each_entry(w, &codec->dapm_widgets, list) {
 804
 805                /* only display widgets that burnm power */
 806                switch (w->id) {
 807                case snd_soc_dapm_hp:
 808                case snd_soc_dapm_mic:
 809                case snd_soc_dapm_spk:
 810                case snd_soc_dapm_line:
 811                case snd_soc_dapm_micbias:
 812                case snd_soc_dapm_dac:
 813                case snd_soc_dapm_adc:
 814                case snd_soc_dapm_pga:
 815                case snd_soc_dapm_mixer:
 816                        if (w->name)
 817                                count += sprintf(buf + count, "%s: %s\n",
 818                                        w->name, w->power ? "On":"Off");
 819                break;
 820                default:
 821                break;
 822                }
 823        }
 824
 825        switch (codec->bias_level) {
 826        case SND_SOC_BIAS_ON:
 827                state = "On";
 828                break;
 829        case SND_SOC_BIAS_PREPARE:
 830                state = "Prepare";
 831                break;
 832        case SND_SOC_BIAS_STANDBY:
 833                state = "Standby";
 834                break;
 835        case SND_SOC_BIAS_OFF:
 836                state = "Off";
 837                break;
 838        }
 839        count += sprintf(buf + count, "PM State: %s\n", state);
 840
 841        return count;
 842}
 843
 844static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
 845
 846int snd_soc_dapm_sys_add(struct device *dev)
 847{
 848        if (!dapm_status)
 849                return 0;
 850        return device_create_file(dev, &dev_attr_dapm_widget);
 851}
 852
 853static void snd_soc_dapm_sys_remove(struct device *dev)
 854{
 855        if (dapm_status) {
 856                device_remove_file(dev, &dev_attr_dapm_widget);
 857        }
 858}
 859
 860/* free all dapm widgets and resources */
 861static void dapm_free_widgets(struct snd_soc_codec *codec)
 862{
 863        struct snd_soc_dapm_widget *w, *next_w;
 864        struct snd_soc_dapm_path *p, *next_p;
 865
 866        list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {
 867                list_del(&w->list);
 868                kfree(w);
 869        }
 870
 871        list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {
 872                list_del(&p->list);
 873                kfree(p->long_name);
 874                kfree(p);
 875        }
 876}
 877
 878static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
 879        char *pin, int status)
 880{
 881        struct snd_soc_dapm_widget *w;
 882
 883        list_for_each_entry(w, &codec->dapm_widgets, list) {
 884                if (!strcmp(w->name, pin)) {
 885                        pr_debug("dapm: %s: pin %s\n", codec->name, pin);
 886                        w->connected = status;
 887                        return 0;
 888                }
 889        }
 890
 891        pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin);
 892        return -EINVAL;
 893}
 894
 895/**
 896 * snd_soc_dapm_sync - scan and power dapm paths
 897 * @codec: audio codec
 898 *
 899 * Walks all dapm audio paths and powers widgets according to their
 900 * stream or path usage.
 901 *
 902 * Returns 0 for success.
 903 */
 904int snd_soc_dapm_sync(struct snd_soc_codec *codec)
 905{
 906        int ret = dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
 907        dump_dapm(codec, "sync");
 908        return ret;
 909}
 910EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
 911
 912static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
 913        const char *sink, const char *control, const char *source)
 914{
 915        struct snd_soc_dapm_path *path;
 916        struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
 917        int ret = 0;
 918
 919        /* find src and dest widgets */
 920        list_for_each_entry(w, &codec->dapm_widgets, list) {
 921
 922                if (!wsink && !(strcmp(w->name, sink))) {
 923                        wsink = w;
 924                        continue;
 925                }
 926                if (!wsource && !(strcmp(w->name, source))) {
 927                        wsource = w;
 928                }
 929        }
 930
 931        if (wsource == NULL || wsink == NULL)
 932                return -ENODEV;
 933
 934        path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
 935        if (!path)
 936                return -ENOMEM;
 937
 938        path->source = wsource;
 939        path->sink = wsink;
 940        INIT_LIST_HEAD(&path->list);
 941        INIT_LIST_HEAD(&path->list_source);
 942        INIT_LIST_HEAD(&path->list_sink);
 943
 944        /* check for external widgets */
 945        if (wsink->id == snd_soc_dapm_input) {
 946                if (wsource->id == snd_soc_dapm_micbias ||
 947                        wsource->id == snd_soc_dapm_mic ||
 948                        wsink->id == snd_soc_dapm_line ||
 949                        wsink->id == snd_soc_dapm_output)
 950                        wsink->ext = 1;
 951        }
 952        if (wsource->id == snd_soc_dapm_output) {
 953                if (wsink->id == snd_soc_dapm_spk ||
 954                        wsink->id == snd_soc_dapm_hp ||
 955                        wsink->id == snd_soc_dapm_line ||
 956                        wsink->id == snd_soc_dapm_input)
 957                        wsource->ext = 1;
 958        }
 959
 960        /* connect static paths */
 961        if (control == NULL) {
 962                list_add(&path->list, &codec->dapm_paths);
 963                list_add(&path->list_sink, &wsink->sources);
 964                list_add(&path->list_source, &wsource->sinks);
 965                path->connect = 1;
 966                return 0;
 967        }
 968
 969        /* connect dynamic paths */
 970        switch(wsink->id) {
 971        case snd_soc_dapm_adc:
 972        case snd_soc_dapm_dac:
 973        case snd_soc_dapm_pga:
 974        case snd_soc_dapm_input:
 975        case snd_soc_dapm_output:
 976        case snd_soc_dapm_micbias:
 977        case snd_soc_dapm_vmid:
 978        case snd_soc_dapm_pre:
 979        case snd_soc_dapm_post:
 980                list_add(&path->list, &codec->dapm_paths);
 981                list_add(&path->list_sink, &wsink->sources);
 982                list_add(&path->list_source, &wsource->sinks);
 983                path->connect = 1;
 984                return 0;
 985        case snd_soc_dapm_mux:
 986        case snd_soc_dapm_value_mux:
 987                ret = dapm_connect_mux(codec, wsource, wsink, path, control,
 988                        &wsink->kcontrols[0]);
 989                if (ret != 0)
 990                        goto err;
 991                break;
 992        case snd_soc_dapm_switch:
 993        case snd_soc_dapm_mixer:
 994                ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
 995                if (ret != 0)
 996                        goto err;
 997                break;
 998        case snd_soc_dapm_hp:
 999        case snd_soc_dapm_mic:
1000        case snd_soc_dapm_line:
1001        case snd_soc_dapm_spk:
1002                list_add(&path->list, &codec->dapm_paths);
1003                list_add(&path->list_sink, &wsink->sources);
1004                list_add(&path->list_source, &wsource->sinks);
1005                path->connect = 0;
1006                return 0;
1007        }
1008        return 0;
1009
1010err:
1011        printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
1012                control, sink);
1013        kfree(path);
1014        return ret;
1015}
1016
1017/**
1018 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
1019 * @codec: codec
1020 * @route: audio routes
1021 * @num: number of routes
1022 *
1023 * Connects 2 dapm widgets together via a named audio path. The sink is
1024 * the widget receiving the audio signal, whilst the source is the sender
1025 * of the audio signal.
1026 *
1027 * Returns 0 for success else error. On error all resources can be freed
1028 * with a call to snd_soc_card_free().
1029 */
1030int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1031                            const struct snd_soc_dapm_route *route, int num)
1032{
1033        int i, ret;
1034
1035        for (i = 0; i < num; i++) {
1036                ret = snd_soc_dapm_add_route(codec, route->sink,
1037                                             route->control, route->source);
1038                if (ret < 0) {
1039                        printk(KERN_ERR "Failed to add route %s->%s\n",
1040                               route->source,
1041                               route->sink);
1042                        return ret;
1043                }
1044                route++;
1045        }
1046
1047        return 0;
1048}
1049EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
1050
1051/**
1052 * snd_soc_dapm_new_widgets - add new dapm widgets
1053 * @codec: audio codec
1054 *
1055 * Checks the codec for any new dapm widgets and creates them if found.
1056 *
1057 * Returns 0 for success.
1058 */
1059int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1060{
1061        struct snd_soc_dapm_widget *w;
1062
1063        list_for_each_entry(w, &codec->dapm_widgets, list)
1064        {
1065                if (w->new)
1066                        continue;
1067
1068                switch(w->id) {
1069                case snd_soc_dapm_switch:
1070                case snd_soc_dapm_mixer:
1071                        dapm_new_mixer(codec, w);
1072                        break;
1073                case snd_soc_dapm_mux:
1074                case snd_soc_dapm_value_mux:
1075                        dapm_new_mux(codec, w);
1076                        break;
1077                case snd_soc_dapm_adc:
1078                case snd_soc_dapm_dac:
1079                case snd_soc_dapm_pga:
1080                        dapm_new_pga(codec, w);
1081                        break;
1082                case snd_soc_dapm_input:
1083                case snd_soc_dapm_output:
1084                case snd_soc_dapm_micbias:
1085                case snd_soc_dapm_spk:
1086                case snd_soc_dapm_hp:
1087                case snd_soc_dapm_mic:
1088                case snd_soc_dapm_line:
1089                case snd_soc_dapm_vmid:
1090                case snd_soc_dapm_pre:
1091                case snd_soc_dapm_post:
1092                        break;
1093                }
1094                w->new = 1;
1095        }
1096
1097        dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
1098        return 0;
1099}
1100EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
1101
1102/**
1103 * snd_soc_dapm_get_volsw - dapm mixer get callback
1104 * @kcontrol: mixer control
1105 * @ucontrol: control element information
1106 *
1107 * Callback to get the value of a dapm mixer control.
1108 *
1109 * Returns 0 for success.
1110 */
1111int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
1112        struct snd_ctl_elem_value *ucontrol)
1113{
1114        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1115        struct soc_mixer_control *mc =
1116                (struct soc_mixer_control *)kcontrol->private_value;
1117        unsigned int reg = mc->reg;
1118        unsigned int shift = mc->shift;
1119        unsigned int rshift = mc->rshift;
1120        int max = mc->max;
1121        unsigned int invert = mc->invert;
1122        unsigned int mask = (1 << fls(max)) - 1;
1123
1124        /* return the saved value if we are powered down */
1125        if (widget->id == snd_soc_dapm_pga && !widget->power) {
1126                ucontrol->value.integer.value[0] = widget->saved_value;
1127                return 0;
1128        }
1129
1130        ucontrol->value.integer.value[0] =
1131                (snd_soc_read(widget->codec, reg) >> shift) & mask;
1132        if (shift != rshift)
1133                ucontrol->value.integer.value[1] =
1134                        (snd_soc_read(widget->codec, reg) >> rshift) & mask;
1135        if (invert) {
1136                ucontrol->value.integer.value[0] =
1137                        max - ucontrol->value.integer.value[0];
1138                if (shift != rshift)
1139                        ucontrol->value.integer.value[1] =
1140                                max - ucontrol->value.integer.value[1];
1141        }
1142
1143        return 0;
1144}
1145EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
1146
1147/**
1148 * snd_soc_dapm_put_volsw - dapm mixer set callback
1149 * @kcontrol: mixer control
1150 * @ucontrol: control element information
1151 *
1152 * Callback to set the value of a dapm mixer control.
1153 *
1154 * Returns 0 for success.
1155 */
1156int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1157        struct snd_ctl_elem_value *ucontrol)
1158{
1159        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1160        struct soc_mixer_control *mc =
1161                (struct soc_mixer_control *)kcontrol->private_value;
1162        unsigned int reg = mc->reg;
1163        unsigned int shift = mc->shift;
1164        unsigned int rshift = mc->rshift;
1165        int max = mc->max;
1166        unsigned int mask = (1 << fls(max)) - 1;
1167        unsigned int invert = mc->invert;
1168        unsigned short val, val2, val_mask;
1169        int ret;
1170
1171        val = (ucontrol->value.integer.value[0] & mask);
1172
1173        if (invert)
1174                val = max - val;
1175        val_mask = mask << shift;
1176        val = val << shift;
1177        if (shift != rshift) {
1178                val2 = (ucontrol->value.integer.value[1] & mask);
1179                if (invert)
1180                        val2 = max - val2;
1181                val_mask |= mask << rshift;
1182                val |= val2 << rshift;
1183        }
1184
1185        mutex_lock(&widget->codec->mutex);
1186        widget->value = val;
1187
1188        /* save volume value if the widget is powered down */
1189        if (widget->id == snd_soc_dapm_pga && !widget->power) {
1190                widget->saved_value = val;
1191                mutex_unlock(&widget->codec->mutex);
1192                return 1;
1193        }
1194
1195        dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
1196        if (widget->event) {
1197                if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1198                        ret = widget->event(widget, kcontrol,
1199                                                SND_SOC_DAPM_PRE_REG);
1200                        if (ret < 0) {
1201                                ret = 1;
1202                                goto out;
1203                        }
1204                }
1205                ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
1206                if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1207                        ret = widget->event(widget, kcontrol,
1208                                                SND_SOC_DAPM_POST_REG);
1209        } else
1210                ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
1211
1212out:
1213        mutex_unlock(&widget->codec->mutex);
1214        return ret;
1215}
1216EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
1217
1218/**
1219 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
1220 * @kcontrol: mixer control
1221 * @ucontrol: control element information
1222 *
1223 * Callback to get the value of a dapm enumerated double mixer control.
1224 *
1225 * Returns 0 for success.
1226 */
1227int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
1228        struct snd_ctl_elem_value *ucontrol)
1229{
1230        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1231        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1232        unsigned short val, bitmask;
1233
1234        for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1235                ;
1236        val = snd_soc_read(widget->codec, e->reg);
1237        ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
1238        if (e->shift_l != e->shift_r)
1239                ucontrol->value.enumerated.item[1] =
1240                        (val >> e->shift_r) & (bitmask - 1);
1241
1242        return 0;
1243}
1244EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
1245
1246/**
1247 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
1248 * @kcontrol: mixer control
1249 * @ucontrol: control element information
1250 *
1251 * Callback to set the value of a dapm enumerated double mixer control.
1252 *
1253 * Returns 0 for success.
1254 */
1255int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1256        struct snd_ctl_elem_value *ucontrol)
1257{
1258        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1259        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1260        unsigned short val, mux;
1261        unsigned short mask, bitmask;
1262        int ret = 0;
1263
1264        for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1265                ;
1266        if (ucontrol->value.enumerated.item[0] > e->max - 1)
1267                return -EINVAL;
1268        mux = ucontrol->value.enumerated.item[0];
1269        val = mux << e->shift_l;
1270        mask = (bitmask - 1) << e->shift_l;
1271        if (e->shift_l != e->shift_r) {
1272                if (ucontrol->value.enumerated.item[1] > e->max - 1)
1273                        return -EINVAL;
1274                val |= ucontrol->value.enumerated.item[1] << e->shift_r;
1275                mask |= (bitmask - 1) << e->shift_r;
1276        }
1277
1278        mutex_lock(&widget->codec->mutex);
1279        widget->value = val;
1280        dapm_mux_update_power(widget, kcontrol, mask, mux, val, e);
1281        if (widget->event) {
1282                if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1283                        ret = widget->event(widget,
1284                                kcontrol, SND_SOC_DAPM_PRE_REG);
1285                        if (ret < 0)
1286                                goto out;
1287                }
1288                ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1289                if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1290                        ret = widget->event(widget,
1291                                kcontrol, SND_SOC_DAPM_POST_REG);
1292        } else
1293                ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1294
1295out:
1296        mutex_unlock(&widget->codec->mutex);
1297        return ret;
1298}
1299EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1300
1301/**
1302 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
1303 *                                      callback
1304 * @kcontrol: mixer control
1305 * @ucontrol: control element information
1306 *
1307 * Callback to get the value of a dapm semi enumerated double mixer control.
1308 *
1309 * Semi enumerated mixer: the enumerated items are referred as values. Can be
1310 * used for handling bitfield coded enumeration for example.
1311 *
1312 * Returns 0 for success.
1313 */
1314int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
1315        struct snd_ctl_elem_value *ucontrol)
1316{
1317        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1318        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1319        unsigned short reg_val, val, mux;
1320
1321        reg_val = snd_soc_read(widget->codec, e->reg);
1322        val = (reg_val >> e->shift_l) & e->mask;
1323        for (mux = 0; mux < e->max; mux++) {
1324                if (val == e->values[mux])
1325                        break;
1326        }
1327        ucontrol->value.enumerated.item[0] = mux;
1328        if (e->shift_l != e->shift_r) {
1329                val = (reg_val >> e->shift_r) & e->mask;
1330                for (mux = 0; mux < e->max; mux++) {
1331                        if (val == e->values[mux])
1332                                break;
1333                }
1334                ucontrol->value.enumerated.item[1] = mux;
1335        }
1336
1337        return 0;
1338}
1339EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
1340
1341/**
1342 * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set
1343 *                                      callback
1344 * @kcontrol: mixer control
1345 * @ucontrol: control element information
1346 *
1347 * Callback to set the value of a dapm semi enumerated double mixer control.
1348 *
1349 * Semi enumerated mixer: the enumerated items are referred as values. Can be
1350 * used for handling bitfield coded enumeration for example.
1351 *
1352 * Returns 0 for success.
1353 */
1354int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1355        struct snd_ctl_elem_value *ucontrol)
1356{
1357        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1358        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1359        unsigned short val, mux;
1360        unsigned short mask;
1361        int ret = 0;
1362
1363        if (ucontrol->value.enumerated.item[0] > e->max - 1)
1364                return -EINVAL;
1365        mux = ucontrol->value.enumerated.item[0];
1366        val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
1367        mask = e->mask << e->shift_l;
1368        if (e->shift_l != e->shift_r) {
1369                if (ucontrol->value.enumerated.item[1] > e->max - 1)
1370                        return -EINVAL;
1371                val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
1372                mask |= e->mask << e->shift_r;
1373        }
1374
1375        mutex_lock(&widget->codec->mutex);
1376        widget->value = val;
1377        dapm_mux_update_power(widget, kcontrol, mask, mux, val, e);
1378        if (widget->event) {
1379                if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1380                        ret = widget->event(widget,
1381                                kcontrol, SND_SOC_DAPM_PRE_REG);
1382                        if (ret < 0)
1383                                goto out;
1384                }
1385                ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1386                if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1387                        ret = widget->event(widget,
1388                                kcontrol, SND_SOC_DAPM_POST_REG);
1389        } else
1390                ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1391
1392out:
1393        mutex_unlock(&widget->codec->mutex);
1394        return ret;
1395}
1396EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
1397
1398/**
1399 * snd_soc_dapm_new_control - create new dapm control
1400 * @codec: audio codec
1401 * @widget: widget template
1402 *
1403 * Creates a new dapm control based upon the template.
1404 *
1405 * Returns 0 for success else error.
1406 */
1407int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
1408        const struct snd_soc_dapm_widget *widget)
1409{
1410        struct snd_soc_dapm_widget *w;
1411
1412        if ((w = dapm_cnew_widget(widget)) == NULL)
1413                return -ENOMEM;
1414
1415        w->codec = codec;
1416        INIT_LIST_HEAD(&w->sources);
1417        INIT_LIST_HEAD(&w->sinks);
1418        INIT_LIST_HEAD(&w->list);
1419        list_add(&w->list, &codec->dapm_widgets);
1420
1421        /* machine layer set ups unconnected pins and insertions */
1422        w->connected = 1;
1423        return 0;
1424}
1425EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
1426
1427/**
1428 * snd_soc_dapm_new_controls - create new dapm controls
1429 * @codec: audio codec
1430 * @widget: widget array
1431 * @num: number of widgets
1432 *
1433 * Creates new DAPM controls based upon the templates.
1434 *
1435 * Returns 0 for success else error.
1436 */
1437int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
1438        const struct snd_soc_dapm_widget *widget,
1439        int num)
1440{
1441        int i, ret;
1442
1443        for (i = 0; i < num; i++) {
1444                ret = snd_soc_dapm_new_control(codec, widget);
1445                if (ret < 0) {
1446                        printk(KERN_ERR
1447                               "ASoC: Failed to create DAPM control %s: %d\n",
1448                               widget->name, ret);
1449                        return ret;
1450                }
1451                widget++;
1452        }
1453        return 0;
1454}
1455EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
1456
1457
1458/**
1459 * snd_soc_dapm_stream_event - send a stream event to the dapm core
1460 * @codec: audio codec
1461 * @stream: stream name
1462 * @event: stream event
1463 *
1464 * Sends a stream event to the dapm core. The core then makes any
1465 * necessary widget power changes.
1466 *
1467 * Returns 0 for success else error.
1468 */
1469int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1470        char *stream, int event)
1471{
1472        struct snd_soc_dapm_widget *w;
1473
1474        if (stream == NULL)
1475                return 0;
1476
1477        mutex_lock(&codec->mutex);
1478        list_for_each_entry(w, &codec->dapm_widgets, list)
1479        {
1480                if (!w->sname)
1481                        continue;
1482                pr_debug("widget %s\n %s stream %s event %d\n",
1483                         w->name, w->sname, stream, event);
1484                if (strstr(w->sname, stream)) {
1485                        switch(event) {
1486                        case SND_SOC_DAPM_STREAM_START:
1487                                w->active = 1;
1488                                break;
1489                        case SND_SOC_DAPM_STREAM_STOP:
1490                                w->active = 0;
1491                                break;
1492                        case SND_SOC_DAPM_STREAM_SUSPEND:
1493                                if (w->active)
1494                                        w->suspend = 1;
1495                                w->active = 0;
1496                                break;
1497                        case SND_SOC_DAPM_STREAM_RESUME:
1498                                if (w->suspend) {
1499                                        w->active = 1;
1500                                        w->suspend = 0;
1501                                }
1502                                break;
1503                        case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
1504                                break;
1505                        case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
1506                                break;
1507                        }
1508                }
1509        }
1510        mutex_unlock(&codec->mutex);
1511
1512        dapm_power_widgets(codec, event);
1513        dump_dapm(codec, __func__);
1514        return 0;
1515}
1516EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
1517
1518/**
1519 * snd_soc_dapm_set_bias_level - set the bias level for the system
1520 * @socdev: audio device
1521 * @level: level to configure
1522 *
1523 * Configure the bias (power) levels for the SoC audio device.
1524 *
1525 * Returns 0 for success else error.
1526 */
1527int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
1528                                enum snd_soc_bias_level level)
1529{
1530        struct snd_soc_codec *codec = socdev->codec;
1531        struct snd_soc_card *card = socdev->card;
1532        int ret = 0;
1533
1534        if (card->set_bias_level)
1535                ret = card->set_bias_level(card, level);
1536        if (ret == 0 && codec->set_bias_level)
1537                ret = codec->set_bias_level(codec, level);
1538
1539        return ret;
1540}
1541
1542/**
1543 * snd_soc_dapm_enable_pin - enable pin.
1544 * @codec: SoC codec
1545 * @pin: pin name
1546 *
1547 * Enables input/output pin and it's parents or children widgets iff there is
1548 * a valid audio route and active audio stream.
1549 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1550 * do any widget power switching.
1551 */
1552int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin)
1553{
1554        return snd_soc_dapm_set_pin(codec, pin, 1);
1555}
1556EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
1557
1558/**
1559 * snd_soc_dapm_disable_pin - disable pin.
1560 * @codec: SoC codec
1561 * @pin: pin name
1562 *
1563 * Disables input/output pin and it's parents or children widgets.
1564 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1565 * do any widget power switching.
1566 */
1567int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
1568{
1569        return snd_soc_dapm_set_pin(codec, pin, 0);
1570}
1571EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
1572
1573/**
1574 * snd_soc_dapm_nc_pin - permanently disable pin.
1575 * @codec: SoC codec
1576 * @pin: pin name
1577 *
1578 * Marks the specified pin as being not connected, disabling it along
1579 * any parent or child widgets.  At present this is identical to
1580 * snd_soc_dapm_disable_pin() but in future it will be extended to do
1581 * additional things such as disabling controls which only affect
1582 * paths through the pin.
1583 *
1584 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1585 * do any widget power switching.
1586 */
1587int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
1588{
1589        return snd_soc_dapm_set_pin(codec, pin, 0);
1590}
1591EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
1592
1593/**
1594 * snd_soc_dapm_get_pin_status - get audio pin status
1595 * @codec: audio codec
1596 * @pin: audio signal pin endpoint (or start point)
1597 *
1598 * Get audio pin status - connected or disconnected.
1599 *
1600 * Returns 1 for connected otherwise 0.
1601 */
1602int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin)
1603{
1604        struct snd_soc_dapm_widget *w;
1605
1606        list_for_each_entry(w, &codec->dapm_widgets, list) {
1607                if (!strcmp(w->name, pin))
1608                        return w->connected;
1609        }
1610
1611        return 0;
1612}
1613EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
1614
1615/**
1616 * snd_soc_dapm_free - free dapm resources
1617 * @socdev: SoC device
1618 *
1619 * Free all dapm widgets and resources.
1620 */
1621void snd_soc_dapm_free(struct snd_soc_device *socdev)
1622{
1623        struct snd_soc_codec *codec = socdev->codec;
1624
1625        snd_soc_dapm_sys_remove(socdev->dev);
1626        dapm_free_widgets(codec);
1627}
1628EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
1629
1630/* Module information */
1631MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1632MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
1633MODULE_LICENSE("GPL");
1634