2  * soc-dapm.c  --  ALSA SoC Dynamic Audio Power Management
 
   4  * Copyright 2005 Wolfson Microelectronics PLC.
 
   5  * Author: Liam Girdwood
 
   6  *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
 
   8  *  This program is free software; you can redistribute  it and/or modify it
 
   9  *  under  the terms of  the GNU General  Public License as published by the
 
  10  *  Free Software Foundation;  either version 2 of the  License, or (at your
 
  11  *  option) any later version.
 
  14  *    o Changes power status of internal codec blocks depending on the
 
  15  *      dynamic configuration of codec internal audio paths and active
 
  17  *    o Platform power domain - can support external components i.e. amps and
 
  18  *      mic/meadphone insertion events.
 
  19  *    o Automatic Mic Bias support
 
  20  *    o Jack insertion power event initiation - e.g. hp insertion will enable
 
  22  *    o Delayed powerdown of audio susbsystem to reduce pops between a quick
 
  26  *    o DAPM power change sequencing - allow for configurable per
 
  28  *    o Support for analogue bias optimisation.
 
  29  *    o Support for reduced codec oversampling rates.
 
  30  *    o Support for reduced codec bias currents.
 
  33 #include <linux/module.h>
 
  34 #include <linux/moduleparam.h>
 
  35 #include <linux/init.h>
 
  36 #include <linux/delay.h>
 
  38 #include <linux/bitops.h>
 
  39 #include <linux/platform_device.h>
 
  40 #include <linux/jiffies.h>
 
  41 #include <sound/core.h>
 
  42 #include <sound/pcm.h>
 
  43 #include <sound/pcm_params.h>
 
  44 #include <sound/soc-dapm.h>
 
  45 #include <sound/initval.h>
 
  50 #define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
 
  51 #define dbg(format, arg...) printk(format, ## arg)
 
  53 #define dump_dapm(codec, action)
 
  54 #define dbg(format, arg...)
 
  59 #define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */
 
  60 #define pop_wait(time) schedule_timeout_uninterruptible(msecs_to_jiffies(time))
 
  61 #define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME)
 
  63 #define pop_dbg(format, arg...)
 
  64 #define pop_wait(time)
 
  67 /* dapm power sequences - make this per codec in the future */
 
  68 static int dapm_up_seq[] = {
 
  69         snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
 
  70         snd_soc_dapm_mux, snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_pga,
 
  71         snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
 
  73 static int dapm_down_seq[] = {
 
  74         snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
 
  75         snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
 
  76         snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_post
 
  79 static int dapm_status = 1;
 
  80 module_param(dapm_status, int, 0);
 
  81 MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
 
  83 /* create a new dapm widget */
 
  84 static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
 
  85         const struct snd_soc_dapm_widget *_widget)
 
  87         return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
 
  90 /* set up initial codec paths */
 
  91 static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
 
  92         struct snd_soc_dapm_path *p, int i)
 
  95         case snd_soc_dapm_switch:
 
  96         case snd_soc_dapm_mixer: {
 
  98                 int reg = w->kcontrols[i].private_value & 0xff;
 
  99                 int shift = (w->kcontrols[i].private_value >> 8) & 0x0f;
 
 100                 int mask = (w->kcontrols[i].private_value >> 16) & 0xff;
 
 101                 int invert = (w->kcontrols[i].private_value >> 24) & 0x01;
 
 103                 val = snd_soc_read(w->codec, reg);
 
 104                 val = (val >> shift) & mask;
 
 106                 if ((invert && !val) || (!invert && val))
 
 112         case snd_soc_dapm_mux: {
 
 113                 struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
 
 114                 int val, item, bitmask;
 
 116                 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
 
 118                 val = snd_soc_read(w->codec, e->reg);
 
 119                 item = (val >> e->shift_l) & (bitmask - 1);
 
 122                 for (i = 0; i < e->mask; i++) {
 
 123                         if (!(strcmp(p->name, e->texts[i])) && item == i)
 
 128         /* does not effect routing - always connected */
 
 129         case snd_soc_dapm_pga:
 
 130         case snd_soc_dapm_output:
 
 131         case snd_soc_dapm_adc:
 
 132         case snd_soc_dapm_input:
 
 133         case snd_soc_dapm_dac:
 
 134         case snd_soc_dapm_micbias:
 
 135         case snd_soc_dapm_vmid:
 
 138         /* does effect routing - dynamically connected */
 
 139         case snd_soc_dapm_hp:
 
 140         case snd_soc_dapm_mic:
 
 141         case snd_soc_dapm_spk:
 
 142         case snd_soc_dapm_line:
 
 143         case snd_soc_dapm_pre:
 
 144         case snd_soc_dapm_post:
 
 150 /* connect mux widget to it's interconnecting audio paths */
 
 151 static int dapm_connect_mux(struct snd_soc_codec *codec,
 
 152         struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
 
 153         struct snd_soc_dapm_path *path, const char *control_name,
 
 154         const struct snd_kcontrol_new *kcontrol)
 
 156         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 
 159         for (i = 0; i < e->mask; i++) {
 
 160                 if (!(strcmp(control_name, e->texts[i]))) {
 
 161                         list_add(&path->list, &codec->dapm_paths);
 
 162                         list_add(&path->list_sink, &dest->sources);
 
 163                         list_add(&path->list_source, &src->sinks);
 
 164                         path->name = (char*)e->texts[i];
 
 165                         dapm_set_path_status(dest, path, 0);
 
 173 /* connect mixer widget to it's interconnecting audio paths */
 
 174 static int dapm_connect_mixer(struct snd_soc_codec *codec,
 
 175         struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
 
 176         struct snd_soc_dapm_path *path, const char *control_name)
 
 180         /* search for mixer kcontrol */
 
 181         for (i = 0; i < dest->num_kcontrols; i++) {
 
 182                 if (!strcmp(control_name, dest->kcontrols[i].name)) {
 
 183                         list_add(&path->list, &codec->dapm_paths);
 
 184                         list_add(&path->list_sink, &dest->sources);
 
 185                         list_add(&path->list_source, &src->sinks);
 
 186                         path->name = dest->kcontrols[i].name;
 
 187                         dapm_set_path_status(dest, path, i);
 
 194 /* update dapm codec register bits */
 
 195 static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
 
 198         unsigned short old, new;
 
 199         struct snd_soc_codec *codec = widget->codec;
 
 201         /* check for valid widgets */
 
 202         if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
 
 203                 widget->id == snd_soc_dapm_output ||
 
 204                 widget->id == snd_soc_dapm_hp ||
 
 205                 widget->id == snd_soc_dapm_mic ||
 
 206                 widget->id == snd_soc_dapm_line ||
 
 207                 widget->id == snd_soc_dapm_spk)
 
 210         power = widget->power;
 
 212                 power = (power ? 0:1);
 
 214         old = snd_soc_read(codec, widget->reg);
 
 215         new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
 
 219                 pop_dbg("pop test %s : %s in %d ms\n", widget->name,
 
 220                         widget->power ? "on" : "off", POP_TIME);
 
 221                 snd_soc_write(codec, widget->reg, new);
 
 224         dbg("reg %x old %x new %x change %d\n", widget->reg, old, new, change);
 
 228 /* ramps the volume up or down to minimise pops before or after a
 
 229  * DAPM power event */
 
 230 static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
 
 232         const struct snd_kcontrol_new *k = widget->kcontrols;
 
 234         if (widget->muted && !power)
 
 236         if (!widget->muted && power)
 
 239         if (widget->num_kcontrols && k) {
 
 240                 int reg = k->private_value & 0xff;
 
 241                 int shift = (k->private_value >> 8) & 0x0f;
 
 242                 int mask = (k->private_value >> 16) & 0xff;
 
 243                 int invert = (k->private_value >> 24) & 0x01;
 
 247                         /* power up has happended, increase volume to last level */
 
 249                                 for (i = mask; i > widget->saved_value; i--)
 
 250                                         snd_soc_update_bits(widget->codec, reg, mask, i);
 
 252                                 for (i = 0; i < widget->saved_value; i++)
 
 253                                         snd_soc_update_bits(widget->codec, reg, mask, i);
 
 257                         /* power down is about to occur, decrease volume to mute */
 
 258                         int val = snd_soc_read(widget->codec, reg);
 
 259                         int i = widget->saved_value = (val >> shift) & mask;
 
 261                                 for (; i < mask; i++)
 
 262                                         snd_soc_update_bits(widget->codec, reg, mask, i);
 
 265                                         snd_soc_update_bits(widget->codec, reg, mask, i);
 
 273 /* create new dapm mixer control */
 
 274 static int dapm_new_mixer(struct snd_soc_codec *codec,
 
 275         struct snd_soc_dapm_widget *w)
 
 279         struct snd_soc_dapm_path *path;
 
 282         for (i = 0; i < w->num_kcontrols; i++) {
 
 285                 list_for_each_entry(path, &w->sources, list_sink) {
 
 287                         /* mixer/mux paths name must match control name */
 
 288                         if (path->name != (char*)w->kcontrols[i].name)
 
 291                         /* add dapm control with long name */
 
 292                         snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
 
 293                         path->long_name = kstrdup (name, GFP_KERNEL);
 
 294                         if (path->long_name == NULL)
 
 297                         path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
 
 299                         ret = snd_ctl_add(codec->card, path->kcontrol);
 
 301                                 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n",
 
 303                                 kfree(path->long_name);
 
 304                                 path->long_name = NULL;
 
 312 /* create new dapm mux control */
 
 313 static int dapm_new_mux(struct snd_soc_codec *codec,
 
 314         struct snd_soc_dapm_widget *w)
 
 316         struct snd_soc_dapm_path *path = NULL;
 
 317         struct snd_kcontrol *kcontrol;
 
 320         if (!w->num_kcontrols) {
 
 321                 printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
 
 325         kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
 
 326         ret = snd_ctl_add(codec->card, kcontrol);
 
 330         list_for_each_entry(path, &w->sources, list_sink)
 
 331                 path->kcontrol = kcontrol;
 
 336         printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
 
 340 /* create new dapm volume control */
 
 341 static int dapm_new_pga(struct snd_soc_codec *codec,
 
 342         struct snd_soc_dapm_widget *w)
 
 344         struct snd_kcontrol *kcontrol;
 
 347         if (!w->num_kcontrols)
 
 350         kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
 
 351         ret = snd_ctl_add(codec->card, kcontrol);
 
 353                 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
 
 360 /* reset 'walked' bit for each dapm path */
 
 361 static inline void dapm_clear_walk(struct snd_soc_codec *codec)
 
 363         struct snd_soc_dapm_path *p;
 
 365         list_for_each_entry(p, &codec->dapm_paths, list)
 
 370  * Recursively check for a completed path to an active or physically connected
 
 371  * output widget. Returns number of complete paths.
 
 373 static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
 
 375         struct snd_soc_dapm_path *path;
 
 378         if (widget->id == snd_soc_dapm_adc && widget->active)
 
 381         if (widget->connected) {
 
 382                 /* connected pin ? */
 
 383                 if (widget->id == snd_soc_dapm_output && !widget->ext)
 
 386                 /* connected jack or spk ? */
 
 387                 if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
 
 388                         widget->id == snd_soc_dapm_line)
 
 392         list_for_each_entry(path, &widget->sinks, list_source) {
 
 396                 if (path->sink && path->connect) {
 
 398                         con += is_connected_output_ep(path->sink);
 
 406  * Recursively check for a completed path to an active or physically connected
 
 407  * input widget. Returns number of complete paths.
 
 409 static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
 
 411         struct snd_soc_dapm_path *path;
 
 414         /* active stream ? */
 
 415         if (widget->id == snd_soc_dapm_dac && widget->active)
 
 418         if (widget->connected) {
 
 419                 /* connected pin ? */
 
 420                 if (widget->id == snd_soc_dapm_input && !widget->ext)
 
 423                 /* connected VMID/Bias for lower pops */
 
 424                 if (widget->id == snd_soc_dapm_vmid)
 
 427                 /* connected jack ? */
 
 428                 if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line)
 
 432         list_for_each_entry(path, &widget->sources, list_sink) {
 
 436                 if (path->source && path->connect) {
 
 438                         con += is_connected_input_ep(path->source);
 
 446  * Handler for generic register modifier widget.
 
 448 int dapm_reg_event(struct snd_soc_dapm_widget *w,
 
 449                    struct snd_kcontrol *kcontrol, int event)
 
 453         if (SND_SOC_DAPM_EVENT_ON(event))
 
 458         snd_soc_update_bits(w->codec, -(w->reg + 1),
 
 459                             w->mask << w->shift, val << w->shift);
 
 465  * Scan each dapm widget for complete audio path.
 
 466  * A complete path is a route that has valid endpoints i.e.:-
 
 468  *  o DAC to output pin.
 
 469  *  o Input Pin to ADC.
 
 470  *  o Input pin to Output pin (bypass, sidetone)
 
 471  *  o DAC to ADC (loopback).
 
 473 static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
 
 475         struct snd_soc_dapm_widget *w;
 
 476         int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;
 
 478         /* do we have a sequenced stream event */
 
 479         if (event == SND_SOC_DAPM_STREAM_START) {
 
 480                 c = ARRAY_SIZE(dapm_up_seq);
 
 482         } else if (event == SND_SOC_DAPM_STREAM_STOP) {
 
 483                 c = ARRAY_SIZE(dapm_down_seq);
 
 487         for(i = 0; i < c; i++) {
 
 488                 list_for_each_entry(w, &codec->dapm_widgets, list) {
 
 490                         /* is widget in stream order */
 
 491                         if (seq && seq[i] && w->id != seq[i])
 
 494                         /* vmid - no action */
 
 495                         if (w->id == snd_soc_dapm_vmid)
 
 499                         if (w->id == snd_soc_dapm_adc && w->active) {
 
 500                                 in = is_connected_input_ep(w);
 
 501                                 dapm_clear_walk(w->codec);
 
 502                                 w->power = (in != 0) ? 1 : 0;
 
 508                         if (w->id == snd_soc_dapm_dac && w->active) {
 
 509                                 out = is_connected_output_ep(w);
 
 510                                 dapm_clear_walk(w->codec);
 
 511                                 w->power = (out != 0) ? 1 : 0;
 
 516                         /* programmable gain/attenuation */
 
 517                         if (w->id == snd_soc_dapm_pga) {
 
 519                                 in = is_connected_input_ep(w);
 
 520                                 dapm_clear_walk(w->codec);
 
 521                                 out = is_connected_output_ep(w);
 
 522                                 dapm_clear_walk(w->codec);
 
 523                                 w->power = on = (out != 0 && in != 0) ? 1 : 0;
 
 526                                         dapm_set_pga(w, on); /* lower volume to reduce pops */
 
 529                                         dapm_set_pga(w, on); /* restore volume from zero */
 
 534                         /* pre and post event widgets */
 
 535                         if (w->id == snd_soc_dapm_pre) {
 
 539                                 if (event == SND_SOC_DAPM_STREAM_START) {
 
 541                                                 NULL, SND_SOC_DAPM_PRE_PMU);
 
 544                                 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
 
 546                                                 NULL, SND_SOC_DAPM_PRE_PMD);
 
 552                         if (w->id == snd_soc_dapm_post) {
 
 556                                 if (event == SND_SOC_DAPM_STREAM_START) {
 
 558                                                 NULL, SND_SOC_DAPM_POST_PMU);
 
 561                                 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
 
 563                                                 NULL, SND_SOC_DAPM_POST_PMD);
 
 570                         /* all other widgets */
 
 571                         in = is_connected_input_ep(w);
 
 572                         dapm_clear_walk(w->codec);
 
 573                         out = is_connected_output_ep(w);
 
 574                         dapm_clear_walk(w->codec);
 
 575                         power = (out != 0 && in != 0) ? 1 : 0;
 
 576                         power_change = (w->power == power) ? 0: 1;
 
 579                         /* call any power change event handlers */
 
 582                                         dbg("power %s event for %s flags %x\n",
 
 583                                                 w->power ? "on" : "off", w->name, w->event_flags);
 
 586                                                 if (w->event_flags & SND_SOC_DAPM_PRE_PMU) {
 
 588                                                                 NULL, SND_SOC_DAPM_PRE_PMU);
 
 593                                                 if (w->event_flags & SND_SOC_DAPM_POST_PMU){
 
 595                                                                 NULL, SND_SOC_DAPM_POST_PMU);
 
 600                                                 /* power down event */
 
 601                                                 if (w->event_flags & SND_SOC_DAPM_PRE_PMD) {
 
 603                                                                 NULL, SND_SOC_DAPM_PRE_PMD);
 
 608                                                 if (w->event_flags & SND_SOC_DAPM_POST_PMD) {
 
 610                                                                 NULL, SND_SOC_DAPM_POST_PMD);
 
 616                                         /* no event handler */
 
 626 static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
 
 628         struct snd_soc_dapm_widget *w;
 
 629         struct snd_soc_dapm_path *p = NULL;
 
 632         printk("DAPM %s %s\n", codec->name, action);
 
 634         list_for_each_entry(w, &codec->dapm_widgets, list) {
 
 636                 /* only display widgets that effect routing */
 
 638                 case snd_soc_dapm_pre:
 
 639                 case snd_soc_dapm_post:
 
 640                 case snd_soc_dapm_vmid:
 
 642                 case snd_soc_dapm_mux:
 
 643                 case snd_soc_dapm_output:
 
 644                 case snd_soc_dapm_input:
 
 645                 case snd_soc_dapm_switch:
 
 646                 case snd_soc_dapm_hp:
 
 647                 case snd_soc_dapm_mic:
 
 648                 case snd_soc_dapm_spk:
 
 649                 case snd_soc_dapm_line:
 
 650                 case snd_soc_dapm_micbias:
 
 651                 case snd_soc_dapm_dac:
 
 652                 case snd_soc_dapm_adc:
 
 653                 case snd_soc_dapm_pga:
 
 654                 case snd_soc_dapm_mixer:
 
 656                                 in = is_connected_input_ep(w);
 
 657                                 dapm_clear_walk(w->codec);
 
 658                                 out = is_connected_output_ep(w);
 
 659                                 dapm_clear_walk(w->codec);
 
 660                                 printk("%s: %s  in %d out %d\n", w->name,
 
 661                                         w->power ? "On":"Off",in, out);
 
 663                                 list_for_each_entry(p, &w->sources, list_sink) {
 
 665                                                 printk(" in  %s %s\n", p->name ? p->name : "static",
 
 668                                 list_for_each_entry(p, &w->sinks, list_source) {
 
 670                                                 printk(" out %s %s\n", p->name ? p->name : "static",
 
 680 /* test and update the power status of a mux widget */
 
 681 static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
 
 682                                  struct snd_kcontrol *kcontrol, int mask,
 
 683                                  int val, struct soc_enum* e)
 
 685         struct snd_soc_dapm_path *path;
 
 688         if (widget->id != snd_soc_dapm_mux)
 
 691         if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
 
 694         /* find dapm widget path assoc with kcontrol */
 
 695         list_for_each_entry(path, &widget->codec->dapm_paths, list) {
 
 696                 if (path->kcontrol != kcontrol)
 
 699                 if (!path->name || ! e->texts[val])
 
 703                 /* we now need to match the string in the enum to the path */
 
 704                 if (!(strcmp(path->name, e->texts[val])))
 
 705                         path->connect = 1; /* new connection */
 
 707                         path->connect = 0; /* old connection must be powered down */
 
 711                 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
 
 716 /* test and update the power status of a mixer or switch widget */
 
 717 static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
 
 718                                    struct snd_kcontrol *kcontrol, int reg,
 
 719                                    int val_mask, int val, int invert)
 
 721         struct snd_soc_dapm_path *path;
 
 724         if (widget->id != snd_soc_dapm_mixer &&
 
 725             widget->id != snd_soc_dapm_switch)
 
 728         if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
 
 731         /* find dapm widget path assoc with kcontrol */
 
 732         list_for_each_entry(path, &widget->codec->dapm_paths, list) {
 
 733                 if (path->kcontrol != kcontrol)
 
 736                 /* found, now check type */
 
 740                         path->connect = invert ? 0:1;
 
 742                         /* old connection must be powered down */
 
 743                         path->connect = invert ? 1:0;
 
 748                 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
 
 753 /* show dapm widget status in sys fs */
 
 754 static ssize_t dapm_widget_show(struct device *dev,
 
 755         struct device_attribute *attr, char *buf)
 
 757         struct snd_soc_device *devdata = dev_get_drvdata(dev);
 
 758         struct snd_soc_codec *codec = devdata->codec;
 
 759         struct snd_soc_dapm_widget *w;
 
 761         char *state = "not set";
 
 763         list_for_each_entry(w, &codec->dapm_widgets, list) {
 
 765                 /* only display widgets that burnm power */
 
 767                 case snd_soc_dapm_hp:
 
 768                 case snd_soc_dapm_mic:
 
 769                 case snd_soc_dapm_spk:
 
 770                 case snd_soc_dapm_line:
 
 771                 case snd_soc_dapm_micbias:
 
 772                 case snd_soc_dapm_dac:
 
 773                 case snd_soc_dapm_adc:
 
 774                 case snd_soc_dapm_pga:
 
 775                 case snd_soc_dapm_mixer:
 
 777                                 count += sprintf(buf + count, "%s: %s\n",
 
 778                                         w->name, w->power ? "On":"Off");
 
 785         switch (codec->bias_level) {
 
 786         case SND_SOC_BIAS_ON:
 
 789         case SND_SOC_BIAS_PREPARE:
 
 792         case SND_SOC_BIAS_STANDBY:
 
 795         case SND_SOC_BIAS_OFF:
 
 799         count += sprintf(buf + count, "PM State: %s\n", state);
 
 804 static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
 
 806 int snd_soc_dapm_sys_add(struct device *dev)
 
 811                 ret = device_create_file(dev, &dev_attr_dapm_widget);
 
 816 static void snd_soc_dapm_sys_remove(struct device *dev)
 
 819                 device_remove_file(dev, &dev_attr_dapm_widget);
 
 822 /* free all dapm widgets and resources */
 
 823 static void dapm_free_widgets(struct snd_soc_codec *codec)
 
 825         struct snd_soc_dapm_widget *w, *next_w;
 
 826         struct snd_soc_dapm_path *p, *next_p;
 
 828         list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {
 
 833         list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {
 
 841  * snd_soc_dapm_sync_endpoints - scan and power dapm paths
 
 842  * @codec: audio codec
 
 844  * Walks all dapm audio paths and powers widgets according to their
 
 845  * stream or path usage.
 
 847  * Returns 0 for success.
 
 849 int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec)
 
 851         return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
 
 853 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_endpoints);
 
 855 static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
 
 856         const char *sink, const char *control, const char *source)
 
 858         struct snd_soc_dapm_path *path;
 
 859         struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
 
 862         /* find src and dest widgets */
 
 863         list_for_each_entry(w, &codec->dapm_widgets, list) {
 
 865                 if (!wsink && !(strcmp(w->name, sink))) {
 
 869                 if (!wsource && !(strcmp(w->name, source))) {
 
 874         if (wsource == NULL || wsink == NULL)
 
 877         path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
 
 881         path->source = wsource;
 
 883         INIT_LIST_HEAD(&path->list);
 
 884         INIT_LIST_HEAD(&path->list_source);
 
 885         INIT_LIST_HEAD(&path->list_sink);
 
 887         /* check for external widgets */
 
 888         if (wsink->id == snd_soc_dapm_input) {
 
 889                 if (wsource->id == snd_soc_dapm_micbias ||
 
 890                         wsource->id == snd_soc_dapm_mic ||
 
 891                         wsink->id == snd_soc_dapm_line ||
 
 892                         wsink->id == snd_soc_dapm_output)
 
 895         if (wsource->id == snd_soc_dapm_output) {
 
 896                 if (wsink->id == snd_soc_dapm_spk ||
 
 897                         wsink->id == snd_soc_dapm_hp ||
 
 898                         wsink->id == snd_soc_dapm_line ||
 
 899                         wsink->id == snd_soc_dapm_input)
 
 903         /* connect static paths */
 
 904         if (control == NULL) {
 
 905                 list_add(&path->list, &codec->dapm_paths);
 
 906                 list_add(&path->list_sink, &wsink->sources);
 
 907                 list_add(&path->list_source, &wsource->sinks);
 
 912         /* connect dynamic paths */
 
 914         case snd_soc_dapm_adc:
 
 915         case snd_soc_dapm_dac:
 
 916         case snd_soc_dapm_pga:
 
 917         case snd_soc_dapm_input:
 
 918         case snd_soc_dapm_output:
 
 919         case snd_soc_dapm_micbias:
 
 920         case snd_soc_dapm_vmid:
 
 921         case snd_soc_dapm_pre:
 
 922         case snd_soc_dapm_post:
 
 923                 list_add(&path->list, &codec->dapm_paths);
 
 924                 list_add(&path->list_sink, &wsink->sources);
 
 925                 list_add(&path->list_source, &wsource->sinks);
 
 928         case snd_soc_dapm_mux:
 
 929                 ret = dapm_connect_mux(codec, wsource, wsink, path, control,
 
 930                         &wsink->kcontrols[0]);
 
 934         case snd_soc_dapm_switch:
 
 935         case snd_soc_dapm_mixer:
 
 936                 ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
 
 940         case snd_soc_dapm_hp:
 
 941         case snd_soc_dapm_mic:
 
 942         case snd_soc_dapm_line:
 
 943         case snd_soc_dapm_spk:
 
 944                 list_add(&path->list, &codec->dapm_paths);
 
 945                 list_add(&path->list_sink, &wsink->sources);
 
 946                 list_add(&path->list_source, &wsource->sinks);
 
 953         printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
 
 960  * snd_soc_dapm_connect_input - connect dapm widgets
 
 961  * @codec: audio codec
 
 962  * @sink: name of target widget
 
 963  * @control: mixer control name
 
 964  * @source: name of source name
 
 966  * Connects 2 dapm widgets together via a named audio path. The sink is
 
 967  * the widget receiving the audio signal, whilst the source is the sender
 
 968  * of the audio signal.
 
 970  * This function has been deprecated in favour of snd_soc_dapm_add_routes().
 
 972  * Returns 0 for success else error.
 
 974 int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
 
 975         const char *control, const char *source)
 
 977         return snd_soc_dapm_add_route(codec, sink, control, source);
 
 979 EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
 
 982  * snd_soc_dapm_add_routes - Add routes between DAPM widgets
 
 984  * @route: audio routes
 
 985  * @num: number of routes
 
 987  * Connects 2 dapm widgets together via a named audio path. The sink is
 
 988  * the widget receiving the audio signal, whilst the source is the sender
 
 989  * of the audio signal.
 
 991  * Returns 0 for success else error. On error all resources can be freed
 
 992  * with a call to snd_soc_card_free().
 
 994 int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
 
 995                             const struct snd_soc_dapm_route *route, int num)
 
 999         for (i = 0; i < num; i++) {
 
1000                 ret = snd_soc_dapm_add_route(codec, route->sink,
 
1001                                              route->control, route->source);
 
1003                         printk(KERN_ERR "Failed to add route %s->%s\n",
 
1013 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
 
1016  * snd_soc_dapm_new_widgets - add new dapm widgets
 
1017  * @codec: audio codec
 
1019  * Checks the codec for any new dapm widgets and creates them if found.
 
1021  * Returns 0 for success.
 
1023 int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
 
1025         struct snd_soc_dapm_widget *w;
 
1027         list_for_each_entry(w, &codec->dapm_widgets, list)
 
1033                 case snd_soc_dapm_switch:
 
1034                 case snd_soc_dapm_mixer:
 
1035                         dapm_new_mixer(codec, w);
 
1037                 case snd_soc_dapm_mux:
 
1038                         dapm_new_mux(codec, w);
 
1040                 case snd_soc_dapm_adc:
 
1041                 case snd_soc_dapm_dac:
 
1042                 case snd_soc_dapm_pga:
 
1043                         dapm_new_pga(codec, w);
 
1045                 case snd_soc_dapm_input:
 
1046                 case snd_soc_dapm_output:
 
1047                 case snd_soc_dapm_micbias:
 
1048                 case snd_soc_dapm_spk:
 
1049                 case snd_soc_dapm_hp:
 
1050                 case snd_soc_dapm_mic:
 
1051                 case snd_soc_dapm_line:
 
1052                 case snd_soc_dapm_vmid:
 
1053                 case snd_soc_dapm_pre:
 
1054                 case snd_soc_dapm_post:
 
1060         dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
 
1063 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
 
1066  * snd_soc_dapm_get_volsw - dapm mixer get callback
 
1067  * @kcontrol: mixer control
 
1068  * @uinfo: control element information
 
1070  * Callback to get the value of a dapm mixer control.
 
1072  * Returns 0 for success.
 
1074 int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
 
1075         struct snd_ctl_elem_value *ucontrol)
 
1077         struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
 
1078         int reg = kcontrol->private_value & 0xff;
 
1079         int shift = (kcontrol->private_value >> 8) & 0x0f;
 
1080         int rshift = (kcontrol->private_value >> 12) & 0x0f;
 
1081         int max = (kcontrol->private_value >> 16) & 0xff;
 
1082         int invert = (kcontrol->private_value >> 24) & 0x01;
 
1083         int mask = (1 << fls(max)) - 1;
 
1085         /* return the saved value if we are powered down */
 
1086         if (widget->id == snd_soc_dapm_pga && !widget->power) {
 
1087                 ucontrol->value.integer.value[0] = widget->saved_value;
 
1091         ucontrol->value.integer.value[0] =
 
1092                 (snd_soc_read(widget->codec, reg) >> shift) & mask;
 
1093         if (shift != rshift)
 
1094                 ucontrol->value.integer.value[1] =
 
1095                         (snd_soc_read(widget->codec, reg) >> rshift) & mask;
 
1097                 ucontrol->value.integer.value[0] =
 
1098                         max - ucontrol->value.integer.value[0];
 
1099                 if (shift != rshift)
 
1100                         ucontrol->value.integer.value[1] =
 
1101                                 max - ucontrol->value.integer.value[1];
 
1106 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
 
1109  * snd_soc_dapm_put_volsw - dapm mixer set callback
 
1110  * @kcontrol: mixer control
 
1111  * @uinfo: control element information
 
1113  * Callback to set the value of a dapm mixer control.
 
1115  * Returns 0 for success.
 
1117 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
 
1118         struct snd_ctl_elem_value *ucontrol)
 
1120         struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
 
1121         int reg = kcontrol->private_value & 0xff;
 
1122         int shift = (kcontrol->private_value >> 8) & 0x0f;
 
1123         int rshift = (kcontrol->private_value >> 12) & 0x0f;
 
1124         int max = (kcontrol->private_value >> 16) & 0xff;
 
1125         int mask = (1 << fls(max)) - 1;
 
1126         int invert = (kcontrol->private_value >> 24) & 0x01;
 
1127         unsigned short val, val2, val_mask;
 
1130         val = (ucontrol->value.integer.value[0] & mask);
 
1134         val_mask = mask << shift;
 
1136         if (shift != rshift) {
 
1137                 val2 = (ucontrol->value.integer.value[1] & mask);
 
1140                 val_mask |= mask << rshift;
 
1141                 val |= val2 << rshift;
 
1144         mutex_lock(&widget->codec->mutex);
 
1145         widget->value = val;
 
1147         /* save volume value if the widget is powered down */
 
1148         if (widget->id == snd_soc_dapm_pga && !widget->power) {
 
1149                 widget->saved_value = val;
 
1150                 mutex_unlock(&widget->codec->mutex);
 
1154         dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
 
1155         if (widget->event) {
 
1156                 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
 
1157                         ret = widget->event(widget, kcontrol,
 
1158                                                 SND_SOC_DAPM_PRE_REG);
 
1164                 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
 
1165                 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
 
1166                         ret = widget->event(widget, kcontrol,
 
1167                                                 SND_SOC_DAPM_POST_REG);
 
1169                 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
 
1172         mutex_unlock(&widget->codec->mutex);
 
1175 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
 
1178  * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
 
1179  * @kcontrol: mixer control
 
1180  * @uinfo: control element information
 
1182  * Callback to get the value of a dapm enumerated double mixer control.
 
1184  * Returns 0 for success.
 
1186 int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 
1187         struct snd_ctl_elem_value *ucontrol)
 
1189         struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
 
1190         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 
1191         unsigned short val, bitmask;
 
1193         for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
 
1195         val = snd_soc_read(widget->codec, e->reg);
 
1196         ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
 
1197         if (e->shift_l != e->shift_r)
 
1198                 ucontrol->value.enumerated.item[1] =
 
1199                         (val >> e->shift_r) & (bitmask - 1);
 
1203 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
 
1206  * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
 
1207  * @kcontrol: mixer control
 
1208  * @uinfo: control element information
 
1210  * Callback to set the value of a dapm enumerated double mixer control.
 
1212  * Returns 0 for success.
 
1214 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 
1215         struct snd_ctl_elem_value *ucontrol)
 
1217         struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
 
1218         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 
1219         unsigned short val, mux;
 
1220         unsigned short mask, bitmask;
 
1223         for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
 
1225         if (ucontrol->value.enumerated.item[0] > e->mask - 1)
 
1227         mux = ucontrol->value.enumerated.item[0];
 
1228         val = mux << e->shift_l;
 
1229         mask = (bitmask - 1) << e->shift_l;
 
1230         if (e->shift_l != e->shift_r) {
 
1231                 if (ucontrol->value.enumerated.item[1] > e->mask - 1)
 
1233                 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
 
1234                 mask |= (bitmask - 1) << e->shift_r;
 
1237         mutex_lock(&widget->codec->mutex);
 
1238         widget->value = val;
 
1239         dapm_mux_update_power(widget, kcontrol, mask, mux, e);
 
1240         if (widget->event) {
 
1241                 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
 
1242                         ret = widget->event(widget,
 
1243                                 kcontrol, SND_SOC_DAPM_PRE_REG);
 
1247                 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
 
1248                 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
 
1249                         ret = widget->event(widget,
 
1250                                 kcontrol, SND_SOC_DAPM_POST_REG);
 
1252                 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
 
1255         mutex_unlock(&widget->codec->mutex);
 
1258 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
 
1261  * snd_soc_dapm_new_control - create new dapm control
 
1262  * @codec: audio codec
 
1263  * @widget: widget template
 
1265  * Creates a new dapm control based upon the template.
 
1267  * Returns 0 for success else error.
 
1269 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
 
1270         const struct snd_soc_dapm_widget *widget)
 
1272         struct snd_soc_dapm_widget *w;
 
1274         if ((w = dapm_cnew_widget(widget)) == NULL)
 
1278         INIT_LIST_HEAD(&w->sources);
 
1279         INIT_LIST_HEAD(&w->sinks);
 
1280         INIT_LIST_HEAD(&w->list);
 
1281         list_add(&w->list, &codec->dapm_widgets);
 
1283         /* machine layer set ups unconnected pins and insertions */
 
1287 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
 
1290  * snd_soc_dapm_new_controls - create new dapm controls
 
1291  * @codec: audio codec
 
1292  * @widget: widget array
 
1293  * @num: number of widgets
 
1295  * Creates new DAPM controls based upon the templates.
 
1297  * Returns 0 for success else error.
 
1299 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
 
1300         const struct snd_soc_dapm_widget *widget,
 
1305         for (i = 0; i < num; i++) {
 
1306                 ret = snd_soc_dapm_new_control(codec, widget);
 
1313 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
 
1317  * snd_soc_dapm_stream_event - send a stream event to the dapm core
 
1318  * @codec: audio codec
 
1319  * @stream: stream name
 
1320  * @event: stream event
 
1322  * Sends a stream event to the dapm core. The core then makes any
 
1323  * necessary widget power changes.
 
1325  * Returns 0 for success else error.
 
1327 int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
 
1328         char *stream, int event)
 
1330         struct snd_soc_dapm_widget *w;
 
1335         mutex_lock(&codec->mutex);
 
1336         list_for_each_entry(w, &codec->dapm_widgets, list)
 
1340                 dbg("widget %s\n %s stream %s event %d\n", w->name, w->sname,
 
1342                 if (strstr(w->sname, stream)) {
 
1344                         case SND_SOC_DAPM_STREAM_START:
 
1347                         case SND_SOC_DAPM_STREAM_STOP:
 
1350                         case SND_SOC_DAPM_STREAM_SUSPEND:
 
1355                         case SND_SOC_DAPM_STREAM_RESUME:
 
1361                         case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
 
1363                         case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
 
1368         mutex_unlock(&codec->mutex);
 
1370         dapm_power_widgets(codec, event);
 
1371         dump_dapm(codec, __func__);
 
1374 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
 
1377  * snd_soc_dapm_set_bias_level - set the bias level for the system
 
1378  * @socdev: audio device
 
1379  * @level: level to configure
 
1381  * Configure the bias (power) levels for the SoC audio device.
 
1383  * Returns 0 for success else error.
 
1385 int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
 
1386                                 enum snd_soc_bias_level level)
 
1388         struct snd_soc_codec *codec = socdev->codec;
 
1389         struct snd_soc_machine *machine = socdev->machine;
 
1392         if (machine->set_bias_level)
 
1393                 ret = machine->set_bias_level(machine, level);
 
1394         if (ret == 0 && codec->set_bias_level)
 
1395                 ret = codec->set_bias_level(codec, level);
 
1401  * snd_soc_dapm_set_endpoint - set audio endpoint status
 
1402  * @codec: audio codec
 
1403  * @endpoint: audio signal endpoint (or start point)
 
1404  * @status: point status
 
1406  * Set audio endpoint status - connected or disconnected.
 
1408  * Returns 0 for success else error.
 
1410 int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
 
1411         char *endpoint, int status)
 
1413         struct snd_soc_dapm_widget *w;
 
1415         list_for_each_entry(w, &codec->dapm_widgets, list) {
 
1416                 if (!strcmp(w->name, endpoint)) {
 
1417                         w->connected = status;
 
1424 EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
 
1427  * snd_soc_dapm_get_endpoint_status - get audio endpoint status
 
1428  * @codec: audio codec
 
1429  * @endpoint: audio signal endpoint (or start point)
 
1431  * Get audio endpoint status - connected or disconnected.
 
1435 int snd_soc_dapm_get_endpoint_status(struct snd_soc_codec *codec,
 
1438         struct snd_soc_dapm_widget *w;
 
1440         list_for_each_entry(w, &codec->dapm_widgets, list) {
 
1441                 if (!strcmp(w->name, endpoint))
 
1442                         return w->connected;
 
1447 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_endpoint_status);
 
1450  * snd_soc_dapm_free - free dapm resources
 
1451  * @socdev: SoC device
 
1453  * Free all dapm widgets and resources.
 
1455 void snd_soc_dapm_free(struct snd_soc_device *socdev)
 
1457         struct snd_soc_codec *codec = socdev->codec;
 
1459         snd_soc_dapm_sys_remove(socdev->dev);
 
1460         dapm_free_widgets(codec);
 
1462 EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
 
1464 /* Module information */
 
1465 MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
 
1466 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
 
1467 MODULE_LICENSE("GPL");