linux/sound/soc/soc-core.c
<<
>>
Prefs
   1/*
   2 * soc-core.c  --  ALSA SoC Audio Layer
   3 *
   4 * Copyright 2005 Wolfson Microelectronics PLC.
   5 * Copyright 2005 Openedhand Ltd.
   6 *
   7 * Author: Liam Girdwood
   8 *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
   9 *         with code, comments and ideas from :-
  10 *         Richard Purdie <richard@openedhand.com>
  11 *
  12 *  This program is free software; you can redistribute  it and/or modify it
  13 *  under  the terms of  the GNU General  Public License as published by the
  14 *  Free Software Foundation;  either version 2 of the  License, or (at your
  15 *  option) any later version.
  16 *
  17 *  Revision history
  18 *    12th Aug 2005   Initial version.
  19 *    25th Oct 2005   Working Codec, Interface and Platform registration.
  20 *
  21 *  TODO:
  22 *   o Add hw rules to enforce rates, etc.
  23 *   o More testing with other codecs/machines.
  24 *   o Add more codecs and platforms to ensure good API coverage.
  25 *   o Support TDM on PCM and I2S
  26 */
  27
  28#include <linux/module.h>
  29#include <linux/moduleparam.h>
  30#include <linux/init.h>
  31#include <linux/delay.h>
  32#include <linux/pm.h>
  33#include <linux/bitops.h>
  34#include <linux/platform_device.h>
  35#include <sound/driver.h>
  36#include <sound/core.h>
  37#include <sound/pcm.h>
  38#include <sound/pcm_params.h>
  39#include <sound/soc.h>
  40#include <sound/soc-dapm.h>
  41#include <sound/initval.h>
  42
  43/* debug */
  44#define SOC_DEBUG 0
  45#if SOC_DEBUG
  46#define dbg(format, arg...) printk(format, ## arg)
  47#else
  48#define dbg(format, arg...)
  49#endif
  50
  51static DEFINE_MUTEX(pcm_mutex);
  52static DEFINE_MUTEX(io_mutex);
  53static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
  54
  55/*
  56 * This is a timeout to do a DAPM powerdown after a stream is closed().
  57 * It can be used to eliminate pops between different playback streams, e.g.
  58 * between two audio tracks.
  59 */
  60static int pmdown_time = 5000;
  61module_param(pmdown_time, int, 0);
  62MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
  63
  64/*
  65 * This function forces any delayed work to be queued and run.
  66 */
  67static int run_delayed_work(struct delayed_work *dwork)
  68{
  69        int ret;
  70
  71        /* cancel any work waiting to be queued. */
  72        ret = cancel_delayed_work(dwork);
  73
  74        /* if there was any work waiting then we run it now and
  75         * wait for it's completion */
  76        if (ret) {
  77                schedule_delayed_work(dwork, 0);
  78                flush_scheduled_work();
  79        }
  80        return ret;
  81}
  82
  83#ifdef CONFIG_SND_SOC_AC97_BUS
  84/* unregister ac97 codec */
  85static int soc_ac97_dev_unregister(struct snd_soc_codec *codec)
  86{
  87        if (codec->ac97->dev.bus)
  88                device_unregister(&codec->ac97->dev);
  89        return 0;
  90}
  91
  92/* stop no dev release warning */
  93static void soc_ac97_device_release(struct device *dev){}
  94
  95/* register ac97 codec to bus */
  96static int soc_ac97_dev_register(struct snd_soc_codec *codec)
  97{
  98        int err;
  99
 100        codec->ac97->dev.bus = &ac97_bus_type;
 101        codec->ac97->dev.parent = NULL;
 102        codec->ac97->dev.release = soc_ac97_device_release;
 103
 104        snprintf(codec->ac97->dev.bus_id, BUS_ID_SIZE, "%d-%d:%s",
 105                 codec->card->number, 0, codec->name);
 106        err = device_register(&codec->ac97->dev);
 107        if (err < 0) {
 108                snd_printk(KERN_ERR "Can't register ac97 bus\n");
 109                codec->ac97->dev.bus = NULL;
 110                return err;
 111        }
 112        return 0;
 113}
 114#endif
 115
 116static inline const char* get_dai_name(int type)
 117{
 118        switch(type) {
 119        case SND_SOC_DAI_AC97_BUS:
 120        case SND_SOC_DAI_AC97:
 121                return "AC97";
 122        case SND_SOC_DAI_I2S:
 123                return "I2S";
 124        case SND_SOC_DAI_PCM:
 125                return "PCM";
 126        }
 127        return NULL;
 128}
 129
 130/*
 131 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
 132 * then initialized and any private data can be allocated. This also calls
 133 * startup for the cpu DAI, platform, machine and codec DAI.
 134 */
 135static int soc_pcm_open(struct snd_pcm_substream *substream)
 136{
 137        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 138        struct snd_soc_device *socdev = rtd->socdev;
 139        struct snd_pcm_runtime *runtime = substream->runtime;
 140        struct snd_soc_dai_link *machine = rtd->dai;
 141        struct snd_soc_platform *platform = socdev->platform;
 142        struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
 143        struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
 144        int ret = 0;
 145
 146        mutex_lock(&pcm_mutex);
 147
 148        /* startup the audio subsystem */
 149        if (cpu_dai->ops.startup) {
 150                ret = cpu_dai->ops.startup(substream);
 151                if (ret < 0) {
 152                        printk(KERN_ERR "asoc: can't open interface %s\n",
 153                                cpu_dai->name);
 154                        goto out;
 155                }
 156        }
 157
 158        if (platform->pcm_ops->open) {
 159                ret = platform->pcm_ops->open(substream);
 160                if (ret < 0) {
 161                        printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
 162                        goto platform_err;
 163                }
 164        }
 165
 166        if (codec_dai->ops.startup) {
 167                ret = codec_dai->ops.startup(substream);
 168                if (ret < 0) {
 169                        printk(KERN_ERR "asoc: can't open codec %s\n",
 170                                codec_dai->name);
 171                        goto codec_dai_err;
 172                }
 173        }
 174
 175        if (machine->ops && machine->ops->startup) {
 176                ret = machine->ops->startup(substream);
 177                if (ret < 0) {
 178                        printk(KERN_ERR "asoc: %s startup failed\n", machine->name);
 179                        goto machine_err;
 180                }
 181        }
 182
 183        /* Check that the codec and cpu DAI's are compatible */
 184        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 185                runtime->hw.rate_min =
 186                        max(codec_dai->playback.rate_min, cpu_dai->playback.rate_min);
 187                runtime->hw.rate_max =
 188                        min(codec_dai->playback.rate_max, cpu_dai->playback.rate_max);
 189                runtime->hw.channels_min =
 190                        max(codec_dai->playback.channels_min,
 191                                cpu_dai->playback.channels_min);
 192                runtime->hw.channels_max =
 193                        min(codec_dai->playback.channels_max,
 194                                cpu_dai->playback.channels_max);
 195                runtime->hw.formats =
 196                        codec_dai->playback.formats & cpu_dai->playback.formats;
 197                runtime->hw.rates =
 198                        codec_dai->playback.rates & cpu_dai->playback.rates;
 199        } else {
 200                runtime->hw.rate_min =
 201                        max(codec_dai->capture.rate_min, cpu_dai->capture.rate_min);
 202                runtime->hw.rate_max =
 203                        min(codec_dai->capture.rate_max, cpu_dai->capture.rate_max);
 204                runtime->hw.channels_min =
 205                        max(codec_dai->capture.channels_min,
 206                                cpu_dai->capture.channels_min);
 207                runtime->hw.channels_max =
 208                        min(codec_dai->capture.channels_max,
 209                                cpu_dai->capture.channels_max);
 210                runtime->hw.formats =
 211                        codec_dai->capture.formats & cpu_dai->capture.formats;
 212                runtime->hw.rates =
 213                        codec_dai->capture.rates & cpu_dai->capture.rates;
 214        }
 215
 216        snd_pcm_limit_hw_rates(runtime);
 217        if (!runtime->hw.rates) {
 218                printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
 219                        codec_dai->name, cpu_dai->name);
 220                goto machine_err;
 221        }
 222        if (!runtime->hw.formats) {
 223                printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
 224                        codec_dai->name, cpu_dai->name);
 225                goto machine_err;
 226        }
 227        if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
 228                printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
 229                        codec_dai->name, cpu_dai->name);
 230                goto machine_err;
 231        }
 232
 233        dbg("asoc: %s <-> %s info:\n",codec_dai->name, cpu_dai->name);
 234        dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
 235        dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
 236                runtime->hw.channels_max);
 237        dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
 238                runtime->hw.rate_max);
 239
 240        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 241                cpu_dai->playback.active = codec_dai->playback.active = 1;
 242        else
 243                cpu_dai->capture.active = codec_dai->capture.active = 1;
 244        cpu_dai->active = codec_dai->active = 1;
 245        cpu_dai->runtime = runtime;
 246        socdev->codec->active++;
 247        mutex_unlock(&pcm_mutex);
 248        return 0;
 249
 250machine_err:
 251        if (machine->ops && machine->ops->shutdown)
 252                machine->ops->shutdown(substream);
 253
 254codec_dai_err:
 255        if (platform->pcm_ops->close)
 256                platform->pcm_ops->close(substream);
 257
 258platform_err:
 259        if (cpu_dai->ops.shutdown)
 260                cpu_dai->ops.shutdown(substream);
 261out:
 262        mutex_unlock(&pcm_mutex);
 263        return ret;
 264}
 265
 266/*
 267 * Power down the audio subsystem pmdown_time msecs after close is called.
 268 * This is to ensure there are no pops or clicks in between any music tracks
 269 * due to DAPM power cycling.
 270 */
 271static void close_delayed_work(struct work_struct *work)
 272{
 273        struct snd_soc_device *socdev =
 274                container_of(work, struct snd_soc_device, delayed_work.work);
 275        struct snd_soc_codec *codec = socdev->codec;
 276        struct snd_soc_codec_dai *codec_dai;
 277        int i;
 278
 279        mutex_lock(&pcm_mutex);
 280        for(i = 0; i < codec->num_dai; i++) {
 281                codec_dai = &codec->dai[i];
 282
 283                dbg("pop wq checking: %s status: %s waiting: %s\n",
 284                        codec_dai->playback.stream_name,
 285                        codec_dai->playback.active ? "active" : "inactive",
 286                        codec_dai->pop_wait ? "yes" : "no");
 287
 288                /* are we waiting on this codec DAI stream */
 289                if (codec_dai->pop_wait == 1) {
 290
 291                        codec_dai->pop_wait = 0;
 292                        snd_soc_dapm_stream_event(codec, codec_dai->playback.stream_name,
 293                                SND_SOC_DAPM_STREAM_STOP);
 294
 295                        /* power down the codec power domain if no longer active */
 296                        if (codec->active == 0) {
 297                                dbg("pop wq D3 %s %s\n", codec->name,
 298                                        codec_dai->playback.stream_name);
 299                                if (codec->dapm_event)
 300                                        codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot);
 301                        }
 302                }
 303        }
 304        mutex_unlock(&pcm_mutex);
 305}
 306
 307/*
 308 * Called by ALSA when a PCM substream is closed. Private data can be
 309 * freed here. The cpu DAI, codec DAI, machine and platform are also
 310 * shutdown.
 311 */
 312static int soc_codec_close(struct snd_pcm_substream *substream)
 313{
 314        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 315        struct snd_soc_device *socdev = rtd->socdev;
 316        struct snd_soc_dai_link *machine = rtd->dai;
 317        struct snd_soc_platform *platform = socdev->platform;
 318        struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
 319        struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
 320        struct snd_soc_codec *codec = socdev->codec;
 321
 322        mutex_lock(&pcm_mutex);
 323
 324        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 325                cpu_dai->playback.active = codec_dai->playback.active = 0;
 326        else
 327                cpu_dai->capture.active = codec_dai->capture.active = 0;
 328
 329        if (codec_dai->playback.active == 0 &&
 330                codec_dai->capture.active == 0) {
 331                cpu_dai->active = codec_dai->active = 0;
 332        }
 333        codec->active--;
 334
 335        if (cpu_dai->ops.shutdown)
 336                cpu_dai->ops.shutdown(substream);
 337
 338        if (codec_dai->ops.shutdown)
 339                codec_dai->ops.shutdown(substream);
 340
 341        if (machine->ops && machine->ops->shutdown)
 342                machine->ops->shutdown(substream);
 343
 344        if (platform->pcm_ops->close)
 345                platform->pcm_ops->close(substream);
 346        cpu_dai->runtime = NULL;
 347
 348        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 349                /* start delayed pop wq here for playback streams */
 350                codec_dai->pop_wait = 1;
 351                schedule_delayed_work(&socdev->delayed_work,
 352                        msecs_to_jiffies(pmdown_time));
 353        } else {
 354                /* capture streams can be powered down now */
 355                snd_soc_dapm_stream_event(codec,
 356                        codec_dai->capture.stream_name, SND_SOC_DAPM_STREAM_STOP);
 357
 358                if (codec->active == 0 && codec_dai->pop_wait == 0){
 359                        if (codec->dapm_event)
 360                                codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot);
 361                }
 362        }
 363
 364        mutex_unlock(&pcm_mutex);
 365        return 0;
 366}
 367
 368/*
 369 * Called by ALSA when the PCM substream is prepared, can set format, sample
 370 * rate, etc.  This function is non atomic and can be called multiple times,
 371 * it can refer to the runtime info.
 372 */
 373static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 374{
 375        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 376        struct snd_soc_device *socdev = rtd->socdev;
 377        struct snd_soc_dai_link *machine = rtd->dai;
 378        struct snd_soc_platform *platform = socdev->platform;
 379        struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
 380        struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
 381        struct snd_soc_codec *codec = socdev->codec;
 382        int ret = 0;
 383
 384        mutex_lock(&pcm_mutex);
 385
 386        if (machine->ops && machine->ops->prepare) {
 387                ret = machine->ops->prepare(substream);
 388                if (ret < 0) {
 389                        printk(KERN_ERR "asoc: machine prepare error\n");
 390                        goto out;
 391                }
 392        }
 393
 394        if (platform->pcm_ops->prepare) {
 395                ret = platform->pcm_ops->prepare(substream);
 396                if (ret < 0) {
 397                        printk(KERN_ERR "asoc: platform prepare error\n");
 398                        goto out;
 399                }
 400        }
 401
 402        if (codec_dai->ops.prepare) {
 403                ret = codec_dai->ops.prepare(substream);
 404                if (ret < 0) {
 405                        printk(KERN_ERR "asoc: codec DAI prepare error\n");
 406                        goto out;
 407                }
 408        }
 409
 410        if (cpu_dai->ops.prepare) {
 411                ret = cpu_dai->ops.prepare(substream);
 412                if (ret < 0) {
 413                        printk(KERN_ERR "asoc: cpu DAI prepare error\n");
 414                        goto out;
 415                }
 416        }
 417
 418        /* we only want to start a DAPM playback stream if we are not waiting
 419         * on an existing one stopping */
 420        if (codec_dai->pop_wait) {
 421                /* we are waiting for the delayed work to start */
 422                if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 423                                snd_soc_dapm_stream_event(socdev->codec,
 424                                        codec_dai->capture.stream_name,
 425                                        SND_SOC_DAPM_STREAM_START);
 426                else {
 427                        codec_dai->pop_wait = 0;
 428                        cancel_delayed_work(&socdev->delayed_work);
 429                        if (codec_dai->dai_ops.digital_mute)
 430                                codec_dai->dai_ops.digital_mute(codec_dai, 0);
 431                }
 432        } else {
 433                /* no delayed work - do we need to power up codec */
 434                if (codec->dapm_state != SNDRV_CTL_POWER_D0) {
 435
 436                        if (codec->dapm_event)
 437                                codec->dapm_event(codec, SNDRV_CTL_POWER_D1);
 438
 439                        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 440                                snd_soc_dapm_stream_event(codec,
 441                                        codec_dai->playback.stream_name,
 442                                        SND_SOC_DAPM_STREAM_START);
 443                        else
 444                                snd_soc_dapm_stream_event(codec,
 445                                        codec_dai->capture.stream_name,
 446                                        SND_SOC_DAPM_STREAM_START);
 447
 448                        if (codec->dapm_event)
 449                                codec->dapm_event(codec, SNDRV_CTL_POWER_D0);
 450                        if (codec_dai->dai_ops.digital_mute)
 451                                codec_dai->dai_ops.digital_mute(codec_dai, 0);
 452
 453                } else {
 454                        /* codec already powered - power on widgets */
 455                        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 456                                snd_soc_dapm_stream_event(codec,
 457                                        codec_dai->playback.stream_name,
 458                                        SND_SOC_DAPM_STREAM_START);
 459                        else
 460                                snd_soc_dapm_stream_event(codec,
 461                                        codec_dai->capture.stream_name,
 462                                        SND_SOC_DAPM_STREAM_START);
 463                        if (codec_dai->dai_ops.digital_mute)
 464                                codec_dai->dai_ops.digital_mute(codec_dai, 0);
 465                }
 466        }
 467
 468out:
 469        mutex_unlock(&pcm_mutex);
 470        return ret;
 471}
 472
 473/*
 474 * Called by ALSA when the hardware params are set by application. This
 475 * function can also be called multiple times and can allocate buffers
 476 * (using snd_pcm_lib_* ). It's non-atomic.
 477 */
 478static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
 479                                struct snd_pcm_hw_params *params)
 480{
 481        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 482        struct snd_soc_device *socdev = rtd->socdev;
 483        struct snd_soc_dai_link *machine = rtd->dai;
 484        struct snd_soc_platform *platform = socdev->platform;
 485        struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
 486        struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
 487        int ret = 0;
 488
 489        mutex_lock(&pcm_mutex);
 490
 491        if (machine->ops && machine->ops->hw_params) {
 492                ret = machine->ops->hw_params(substream, params);
 493                if (ret < 0) {
 494                        printk(KERN_ERR "asoc: machine hw_params failed\n");
 495                        goto out;
 496                }
 497        }
 498
 499        if (codec_dai->ops.hw_params) {
 500                ret = codec_dai->ops.hw_params(substream, params);
 501                if (ret < 0) {
 502                        printk(KERN_ERR "asoc: can't set codec %s hw params\n",
 503                                codec_dai->name);
 504                        goto codec_err;
 505                }
 506        }
 507
 508        if (cpu_dai->ops.hw_params) {
 509                ret = cpu_dai->ops.hw_params(substream, params);
 510                if (ret < 0) {
 511                        printk(KERN_ERR "asoc: can't set interface %s hw params\n",
 512                                cpu_dai->name);
 513                        goto interface_err;
 514                }
 515        }
 516
 517        if (platform->pcm_ops->hw_params) {
 518                ret = platform->pcm_ops->hw_params(substream, params);
 519                if (ret < 0) {
 520                        printk(KERN_ERR "asoc: can't set platform %s hw params\n",
 521                                platform->name);
 522                        goto platform_err;
 523                }
 524        }
 525
 526out:
 527        mutex_unlock(&pcm_mutex);
 528        return ret;
 529
 530platform_err:
 531        if (cpu_dai->ops.hw_free)
 532                cpu_dai->ops.hw_free(substream);
 533
 534interface_err:
 535        if (codec_dai->ops.hw_free)
 536                codec_dai->ops.hw_free(substream);
 537
 538codec_err:
 539        if(machine->ops && machine->ops->hw_free)
 540                machine->ops->hw_free(substream);
 541
 542        mutex_unlock(&pcm_mutex);
 543        return ret;
 544}
 545
 546/*
 547 * Free's resources allocated by hw_params, can be called multiple times
 548 */
 549static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
 550{
 551        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 552        struct snd_soc_device *socdev = rtd->socdev;
 553        struct snd_soc_dai_link *machine = rtd->dai;
 554        struct snd_soc_platform *platform = socdev->platform;
 555        struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
 556        struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
 557        struct snd_soc_codec *codec = socdev->codec;
 558
 559        mutex_lock(&pcm_mutex);
 560
 561        /* apply codec digital mute */
 562        if (!codec->active && codec_dai->dai_ops.digital_mute)
 563                codec_dai->dai_ops.digital_mute(codec_dai, 1);
 564
 565        /* free any machine hw params */
 566        if (machine->ops && machine->ops->hw_free)
 567                machine->ops->hw_free(substream);
 568
 569        /* free any DMA resources */
 570        if (platform->pcm_ops->hw_free)
 571                platform->pcm_ops->hw_free(substream);
 572
 573        /* now free hw params for the DAI's  */
 574        if (codec_dai->ops.hw_free)
 575                codec_dai->ops.hw_free(substream);
 576
 577        if (cpu_dai->ops.hw_free)
 578                cpu_dai->ops.hw_free(substream);
 579
 580        mutex_unlock(&pcm_mutex);
 581        return 0;
 582}
 583
 584static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 585{
 586        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 587        struct snd_soc_device *socdev = rtd->socdev;
 588        struct snd_soc_dai_link *machine = rtd->dai;
 589        struct snd_soc_platform *platform = socdev->platform;
 590        struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
 591        struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
 592        int ret;
 593
 594        if (codec_dai->ops.trigger) {
 595                ret = codec_dai->ops.trigger(substream, cmd);
 596                if (ret < 0)
 597                        return ret;
 598        }
 599
 600        if (platform->pcm_ops->trigger) {
 601                ret = platform->pcm_ops->trigger(substream, cmd);
 602                if (ret < 0)
 603                        return ret;
 604        }
 605
 606        if (cpu_dai->ops.trigger) {
 607                ret = cpu_dai->ops.trigger(substream, cmd);
 608                if (ret < 0)
 609                        return ret;
 610        }
 611        return 0;
 612}
 613
 614/* ASoC PCM operations */
 615static struct snd_pcm_ops soc_pcm_ops = {
 616        .open           = soc_pcm_open,
 617        .close          = soc_codec_close,
 618        .hw_params      = soc_pcm_hw_params,
 619        .hw_free        = soc_pcm_hw_free,
 620        .prepare        = soc_pcm_prepare,
 621        .trigger        = soc_pcm_trigger,
 622};
 623
 624#ifdef CONFIG_PM
 625/* powers down audio subsystem for suspend */
 626static int soc_suspend(struct platform_device *pdev, pm_message_t state)
 627{
 628        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 629        struct snd_soc_machine *machine = socdev->machine;
 630        struct snd_soc_platform *platform = socdev->platform;
 631        struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
 632        struct snd_soc_codec *codec = socdev->codec;
 633        int i;
 634
 635        /* mute any active DAC's */
 636        for(i = 0; i < machine->num_links; i++) {
 637                struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
 638                if (dai->dai_ops.digital_mute && dai->playback.active)
 639                        dai->dai_ops.digital_mute(dai, 1);
 640        }
 641
 642        if (machine->suspend_pre)
 643                machine->suspend_pre(pdev, state);
 644
 645        for(i = 0; i < machine->num_links; i++) {
 646                struct snd_soc_cpu_dai  *cpu_dai = machine->dai_link[i].cpu_dai;
 647                if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
 648                        cpu_dai->suspend(pdev, cpu_dai);
 649                if (platform->suspend)
 650                        platform->suspend(pdev, cpu_dai);
 651        }
 652
 653        /* close any waiting streams and save state */
 654        run_delayed_work(&socdev->delayed_work);
 655        codec->suspend_dapm_state = codec->dapm_state;
 656
 657        for(i = 0; i < codec->num_dai; i++) {
 658                char *stream = codec->dai[i].playback.stream_name;
 659                if (stream != NULL)
 660                        snd_soc_dapm_stream_event(codec, stream,
 661                                SND_SOC_DAPM_STREAM_SUSPEND);
 662                stream = codec->dai[i].capture.stream_name;
 663                if (stream != NULL)
 664                        snd_soc_dapm_stream_event(codec, stream,
 665                                SND_SOC_DAPM_STREAM_SUSPEND);
 666        }
 667
 668        if (codec_dev->suspend)
 669                codec_dev->suspend(pdev, state);
 670
 671        for(i = 0; i < machine->num_links; i++) {
 672                struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
 673                if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
 674                        cpu_dai->suspend(pdev, cpu_dai);
 675        }
 676
 677        if (machine->suspend_post)
 678                machine->suspend_post(pdev, state);
 679
 680        return 0;
 681}
 682
 683/* powers up audio subsystem after a suspend */
 684static int soc_resume(struct platform_device *pdev)
 685{
 686        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 687        struct snd_soc_machine *machine = socdev->machine;
 688        struct snd_soc_platform *platform = socdev->platform;
 689        struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
 690        struct snd_soc_codec *codec = socdev->codec;
 691        int i;
 692
 693        if (machine->resume_pre)
 694                machine->resume_pre(pdev);
 695
 696        for(i = 0; i < machine->num_links; i++) {
 697                struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
 698                if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
 699                        cpu_dai->resume(pdev, cpu_dai);
 700        }
 701
 702        if (codec_dev->resume)
 703                codec_dev->resume(pdev);
 704
 705        for(i = 0; i < codec->num_dai; i++) {
 706                char* stream = codec->dai[i].playback.stream_name;
 707                if (stream != NULL)
 708                        snd_soc_dapm_stream_event(codec, stream,
 709                                SND_SOC_DAPM_STREAM_RESUME);
 710                stream = codec->dai[i].capture.stream_name;
 711                if (stream != NULL)
 712                        snd_soc_dapm_stream_event(codec, stream,
 713                                SND_SOC_DAPM_STREAM_RESUME);
 714        }
 715
 716        /* unmute any active DAC's */
 717        for(i = 0; i < machine->num_links; i++) {
 718                struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
 719                if (dai->dai_ops.digital_mute && dai->playback.active)
 720                        dai->dai_ops.digital_mute(dai, 0);
 721        }
 722
 723        for(i = 0; i < machine->num_links; i++) {
 724                struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
 725                if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
 726                        cpu_dai->resume(pdev, cpu_dai);
 727                if (platform->resume)
 728                        platform->resume(pdev, cpu_dai);
 729        }
 730
 731        if (machine->resume_post)
 732                machine->resume_post(pdev);
 733
 734        return 0;
 735}
 736
 737#else
 738#define soc_suspend     NULL
 739#define soc_resume      NULL
 740#endif
 741
 742/* probes a new socdev */
 743static int soc_probe(struct platform_device *pdev)
 744{
 745        int ret = 0, i;
 746        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 747        struct snd_soc_machine *machine = socdev->machine;
 748        struct snd_soc_platform *platform = socdev->platform;
 749        struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
 750
 751        if (machine->probe) {
 752                ret = machine->probe(pdev);
 753                if(ret < 0)
 754                        return ret;
 755        }
 756
 757        for (i = 0; i < machine->num_links; i++) {
 758                struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
 759                if (cpu_dai->probe) {
 760                        ret = cpu_dai->probe(pdev);
 761                        if(ret < 0)
 762                                goto cpu_dai_err;
 763                }
 764        }
 765
 766        if (codec_dev->probe) {
 767                ret = codec_dev->probe(pdev);
 768                if(ret < 0)
 769                        goto cpu_dai_err;
 770        }
 771
 772        if (platform->probe) {
 773                ret = platform->probe(pdev);
 774                if(ret < 0)
 775                        goto platform_err;
 776        }
 777
 778        /* DAPM stream work */
 779        INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
 780        return 0;
 781
 782platform_err:
 783        if (codec_dev->remove)
 784                codec_dev->remove(pdev);
 785
 786cpu_dai_err:
 787        for (i--; i >= 0; i--) {
 788                struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
 789                if (cpu_dai->remove)
 790                        cpu_dai->remove(pdev);
 791        }
 792
 793        if (machine->remove)
 794                machine->remove(pdev);
 795
 796        return ret;
 797}
 798
 799/* removes a socdev */
 800static int soc_remove(struct platform_device *pdev)
 801{
 802        int i;
 803        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
 804        struct snd_soc_machine *machine = socdev->machine;
 805        struct snd_soc_platform *platform = socdev->platform;
 806        struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
 807
 808        run_delayed_work(&socdev->delayed_work);
 809
 810        if (platform->remove)
 811                platform->remove(pdev);
 812
 813        if (codec_dev->remove)
 814                codec_dev->remove(pdev);
 815
 816        for (i = 0; i < machine->num_links; i++) {
 817                struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
 818                if (cpu_dai->remove)
 819                        cpu_dai->remove(pdev);
 820        }
 821
 822        if (machine->remove)
 823                machine->remove(pdev);
 824
 825        return 0;
 826}
 827
 828/* ASoC platform driver */
 829static struct platform_driver soc_driver = {
 830        .driver         = {
 831                .name           = "soc-audio",
 832        },
 833        .probe          = soc_probe,
 834        .remove         = soc_remove,
 835        .suspend        = soc_suspend,
 836        .resume         = soc_resume,
 837};
 838
 839/* create a new pcm */
 840static int soc_new_pcm(struct snd_soc_device *socdev,
 841        struct snd_soc_dai_link *dai_link, int num)
 842{
 843        struct snd_soc_codec *codec = socdev->codec;
 844        struct snd_soc_codec_dai *codec_dai = dai_link->codec_dai;
 845        struct snd_soc_cpu_dai *cpu_dai = dai_link->cpu_dai;
 846        struct snd_soc_pcm_runtime *rtd;
 847        struct snd_pcm *pcm;
 848        char new_name[64];
 849        int ret = 0, playback = 0, capture = 0;
 850
 851        rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
 852        if (rtd == NULL)
 853                return -ENOMEM;
 854
 855        rtd->dai = dai_link;
 856        rtd->socdev = socdev;
 857        codec_dai->codec = socdev->codec;
 858
 859        /* check client and interface hw capabilities */
 860        sprintf(new_name, "%s %s-%s-%d",dai_link->stream_name, codec_dai->name,
 861                get_dai_name(cpu_dai->type), num);
 862
 863        if (codec_dai->playback.channels_min)
 864                playback = 1;
 865        if (codec_dai->capture.channels_min)
 866                capture = 1;
 867
 868        ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback,
 869                capture, &pcm);
 870        if (ret < 0) {
 871                printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
 872                kfree(rtd);
 873                return ret;
 874        }
 875
 876        pcm->private_data = rtd;
 877        soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap;
 878        soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer;
 879        soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl;
 880        soc_pcm_ops.copy = socdev->platform->pcm_ops->copy;
 881        soc_pcm_ops.silence = socdev->platform->pcm_ops->silence;
 882        soc_pcm_ops.ack = socdev->platform->pcm_ops->ack;
 883        soc_pcm_ops.page = socdev->platform->pcm_ops->page;
 884
 885        if (playback)
 886                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
 887
 888        if (capture)
 889                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
 890
 891        ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm);
 892        if (ret < 0) {
 893                printk(KERN_ERR "asoc: platform pcm constructor failed\n");
 894                kfree(rtd);
 895                return ret;
 896        }
 897
 898        pcm->private_free = socdev->platform->pcm_free;
 899        printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
 900                cpu_dai->name);
 901        return ret;
 902}
 903
 904/* codec register dump */
 905static ssize_t codec_reg_show(struct device *dev,
 906        struct device_attribute *attr, char *buf)
 907{
 908        struct snd_soc_device *devdata = dev_get_drvdata(dev);
 909        struct snd_soc_codec *codec = devdata->codec;
 910        int i, step = 1, count = 0;
 911
 912        if (!codec->reg_cache_size)
 913                return 0;
 914
 915        if (codec->reg_cache_step)
 916                step = codec->reg_cache_step;
 917
 918        count += sprintf(buf, "%s registers\n", codec->name);
 919        for(i = 0; i < codec->reg_cache_size; i += step)
 920                count += sprintf(buf + count, "%2x: %4x\n", i, codec->read(codec, i));
 921
 922        return count;
 923}
 924static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
 925
 926/**
 927 * snd_soc_new_ac97_codec - initailise AC97 device
 928 * @codec: audio codec
 929 * @ops: AC97 bus operations
 930 * @num: AC97 codec number
 931 *
 932 * Initialises AC97 codec resources for use by ad-hoc devices only.
 933 */
 934int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
 935        struct snd_ac97_bus_ops *ops, int num)
 936{
 937        mutex_lock(&codec->mutex);
 938
 939        codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
 940        if (codec->ac97 == NULL) {
 941                mutex_unlock(&codec->mutex);
 942                return -ENOMEM;
 943        }
 944
 945        codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL);
 946        if (codec->ac97->bus == NULL) {
 947                kfree(codec->ac97);
 948                codec->ac97 = NULL;
 949                mutex_unlock(&codec->mutex);
 950                return -ENOMEM;
 951        }
 952
 953        codec->ac97->bus->ops = ops;
 954        codec->ac97->num = num;
 955        mutex_unlock(&codec->mutex);
 956        return 0;
 957}
 958EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
 959
 960/**
 961 * snd_soc_free_ac97_codec - free AC97 codec device
 962 * @codec: audio codec
 963 *
 964 * Frees AC97 codec device resources.
 965 */
 966void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
 967{
 968        mutex_lock(&codec->mutex);
 969        kfree(codec->ac97->bus);
 970        kfree(codec->ac97);
 971        codec->ac97 = NULL;
 972        mutex_unlock(&codec->mutex);
 973}
 974EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
 975
 976/**
 977 * snd_soc_update_bits - update codec register bits
 978 * @codec: audio codec
 979 * @reg: codec register
 980 * @mask: register mask
 981 * @value: new value
 982 *
 983 * Writes new register value.
 984 *
 985 * Returns 1 for change else 0.
 986 */
 987int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
 988                                unsigned short mask, unsigned short value)
 989{
 990        int change;
 991        unsigned short old, new;
 992
 993        mutex_lock(&io_mutex);
 994        old = snd_soc_read(codec, reg);
 995        new = (old & ~mask) | value;
 996        change = old != new;
 997        if (change)
 998                snd_soc_write(codec, reg, new);
 999
1000        mutex_unlock(&io_mutex);
1001        return change;
1002}
1003EXPORT_SYMBOL_GPL(snd_soc_update_bits);
1004
1005/**
1006 * snd_soc_test_bits - test register for change
1007 * @codec: audio codec
1008 * @reg: codec register
1009 * @mask: register mask
1010 * @value: new value
1011 *
1012 * Tests a register with a new value and checks if the new value is
1013 * different from the old value.
1014 *
1015 * Returns 1 for change else 0.
1016 */
1017int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1018                                unsigned short mask, unsigned short value)
1019{
1020        int change;
1021        unsigned short old, new;
1022
1023        mutex_lock(&io_mutex);
1024        old = snd_soc_read(codec, reg);
1025        new = (old & ~mask) | value;
1026        change = old != new;
1027        mutex_unlock(&io_mutex);
1028
1029        return change;
1030}
1031EXPORT_SYMBOL_GPL(snd_soc_test_bits);
1032
1033/**
1034 * snd_soc_new_pcms - create new sound card and pcms
1035 * @socdev: the SoC audio device
1036 *
1037 * Create a new sound card based upon the codec and interface pcms.
1038 *
1039 * Returns 0 for success, else error.
1040 */
1041int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1042{
1043        struct snd_soc_codec *codec = socdev->codec;
1044        struct snd_soc_machine *machine = socdev->machine;
1045        int ret = 0, i;
1046
1047        mutex_lock(&codec->mutex);
1048
1049        /* register a sound card */
1050        codec->card = snd_card_new(idx, xid, codec->owner, 0);
1051        if (!codec->card) {
1052                printk(KERN_ERR "asoc: can't create sound card for codec %s\n",
1053                        codec->name);
1054                mutex_unlock(&codec->mutex);
1055                return -ENODEV;
1056        }
1057
1058        codec->card->dev = socdev->dev;
1059        codec->card->private_data = codec;
1060        strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
1061
1062        /* create the pcms */
1063        for(i = 0; i < machine->num_links; i++) {
1064                ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
1065                if (ret < 0) {
1066                        printk(KERN_ERR "asoc: can't create pcm %s\n",
1067                                machine->dai_link[i].stream_name);
1068                        mutex_unlock(&codec->mutex);
1069                        return ret;
1070                }
1071        }
1072
1073        mutex_unlock(&codec->mutex);
1074        return ret;
1075}
1076EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1077
1078/**
1079 * snd_soc_register_card - register sound card
1080 * @socdev: the SoC audio device
1081 *
1082 * Register a SoC sound card. Also registers an AC97 device if the
1083 * codec is AC97 for ad hoc devices.
1084 *
1085 * Returns 0 for success, else error.
1086 */
1087int snd_soc_register_card(struct snd_soc_device *socdev)
1088{
1089        struct snd_soc_codec *codec = socdev->codec;
1090        struct snd_soc_machine *machine = socdev->machine;
1091        int ret = 0, i, ac97 = 0, err = 0;
1092
1093        mutex_lock(&codec->mutex);
1094        for(i = 0; i < machine->num_links; i++) {
1095                if (socdev->machine->dai_link[i].init) {
1096                        err = socdev->machine->dai_link[i].init(codec);
1097                        if (err < 0) {
1098                                printk(KERN_ERR "asoc: failed to init %s\n",
1099                                        socdev->machine->dai_link[i].stream_name);
1100                                continue;
1101                        }
1102                }
1103                if (socdev->machine->dai_link[i].codec_dai->type == 
1104                        SND_SOC_DAI_AC97_BUS)
1105                        ac97 = 1;
1106        }
1107        snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1108                 "%s", machine->name);
1109        snprintf(codec->card->longname, sizeof(codec->card->longname),
1110                 "%s (%s)", machine->name, codec->name);
1111
1112        ret = snd_card_register(codec->card);
1113        if (ret < 0) {
1114                printk(KERN_ERR "asoc: failed to register soundcard for codec %s\n",
1115                                codec->name);
1116                goto out;
1117        }
1118
1119#ifdef CONFIG_SND_SOC_AC97_BUS
1120        if (ac97) {
1121                ret = soc_ac97_dev_register(codec);
1122                if (ret < 0) {
1123                        printk(KERN_ERR "asoc: AC97 device register failed\n");
1124                        snd_card_free(codec->card);
1125                        goto out;
1126                }
1127        }
1128#endif
1129
1130        err = snd_soc_dapm_sys_add(socdev->dev);
1131        if (err < 0)
1132                printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
1133
1134        err = device_create_file(socdev->dev, &dev_attr_codec_reg);
1135        if (err < 0)
1136                printk(KERN_WARNING "asoc: failed to add codec sysfs entries\n");
1137out:
1138        mutex_unlock(&codec->mutex);
1139        return ret;
1140}
1141EXPORT_SYMBOL_GPL(snd_soc_register_card);
1142
1143/**
1144 * snd_soc_free_pcms - free sound card and pcms
1145 * @socdev: the SoC audio device
1146 *
1147 * Frees sound card and pcms associated with the socdev.
1148 * Also unregister the codec if it is an AC97 device.
1149 */
1150void snd_soc_free_pcms(struct snd_soc_device *socdev)
1151{
1152        struct snd_soc_codec *codec = socdev->codec;
1153#ifdef CONFIG_SND_SOC_AC97_BUS
1154        struct snd_soc_codec_dai *codec_dai;
1155        int i;
1156#endif
1157
1158        mutex_lock(&codec->mutex);
1159#ifdef CONFIG_SND_SOC_AC97_BUS
1160        for(i = 0; i < codec->num_dai; i++) {
1161                codec_dai = &codec->dai[i];
1162                if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) {
1163                        soc_ac97_dev_unregister(codec);
1164                        goto free_card;
1165                }
1166        }
1167free_card:
1168#endif
1169
1170        if (codec->card)
1171                snd_card_free(codec->card);
1172        device_remove_file(socdev->dev, &dev_attr_codec_reg);
1173        mutex_unlock(&codec->mutex);
1174}
1175EXPORT_SYMBOL_GPL(snd_soc_free_pcms);
1176
1177/**
1178 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
1179 * @substream: the pcm substream
1180 * @hw: the hardware parameters
1181 *
1182 * Sets the substream runtime hardware parameters.
1183 */
1184int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
1185        const struct snd_pcm_hardware *hw)
1186{
1187        struct snd_pcm_runtime *runtime = substream->runtime;
1188        runtime->hw.info = hw->info;
1189        runtime->hw.formats = hw->formats;
1190        runtime->hw.period_bytes_min = hw->period_bytes_min;
1191        runtime->hw.period_bytes_max = hw->period_bytes_max;
1192        runtime->hw.periods_min = hw->periods_min;
1193        runtime->hw.periods_max = hw->periods_max;
1194        runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
1195        runtime->hw.fifo_size = hw->fifo_size;
1196        return 0;
1197}
1198EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
1199
1200/**
1201 * snd_soc_cnew - create new control
1202 * @_template: control template
1203 * @data: control private data
1204 * @lnng_name: control long name
1205 *
1206 * Create a new mixer control from a template control.
1207 *
1208 * Returns 0 for success, else error.
1209 */
1210struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
1211        void *data, char *long_name)
1212{
1213        struct snd_kcontrol_new template;
1214
1215        memcpy(&template, _template, sizeof(template));
1216        if (long_name)
1217                template.name = long_name;
1218        template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
1219        template.index = 0;
1220
1221        return snd_ctl_new1(&template, data);
1222}
1223EXPORT_SYMBOL_GPL(snd_soc_cnew);
1224
1225/**
1226 * snd_soc_info_enum_double - enumerated double mixer info callback
1227 * @kcontrol: mixer control
1228 * @uinfo: control element information
1229 *
1230 * Callback to provide information about a double enumerated
1231 * mixer control.
1232 *
1233 * Returns 0 for success.
1234 */
1235int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
1236        struct snd_ctl_elem_info *uinfo)
1237{
1238        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1239
1240        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1241        uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
1242        uinfo->value.enumerated.items = e->mask;
1243
1244        if (uinfo->value.enumerated.item > e->mask - 1)
1245                uinfo->value.enumerated.item = e->mask - 1;
1246        strcpy(uinfo->value.enumerated.name,
1247                e->texts[uinfo->value.enumerated.item]);
1248        return 0;
1249}
1250EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
1251
1252/**
1253 * snd_soc_get_enum_double - enumerated double mixer get callback
1254 * @kcontrol: mixer control
1255 * @uinfo: control element information
1256 *
1257 * Callback to get the value of a double enumerated mixer.
1258 *
1259 * Returns 0 for success.
1260 */
1261int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
1262        struct snd_ctl_elem_value *ucontrol)
1263{
1264        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1265        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1266        unsigned short val, bitmask;
1267
1268        for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
1269                ;
1270        val = snd_soc_read(codec, e->reg);
1271        ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
1272        if (e->shift_l != e->shift_r)
1273                ucontrol->value.enumerated.item[1] =
1274                        (val >> e->shift_r) & (bitmask - 1);
1275
1276        return 0;
1277}
1278EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
1279
1280/**
1281 * snd_soc_put_enum_double - enumerated double mixer put callback
1282 * @kcontrol: mixer control
1283 * @uinfo: control element information
1284 *
1285 * Callback to set the value of a double enumerated mixer.
1286 *
1287 * Returns 0 for success.
1288 */
1289int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
1290        struct snd_ctl_elem_value *ucontrol)
1291{
1292        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1293        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1294        unsigned short val;
1295        unsigned short mask, bitmask;
1296
1297        for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
1298                ;
1299        if (ucontrol->value.enumerated.item[0] > e->mask - 1)
1300                return -EINVAL;
1301        val = ucontrol->value.enumerated.item[0] << e->shift_l;
1302        mask = (bitmask - 1) << e->shift_l;
1303        if (e->shift_l != e->shift_r) {
1304                if (ucontrol->value.enumerated.item[1] > e->mask - 1)
1305                        return -EINVAL;
1306                val |= ucontrol->value.enumerated.item[1] << e->shift_r;
1307                mask |= (bitmask - 1) << e->shift_r;
1308        }
1309
1310        return snd_soc_update_bits(codec, e->reg, mask, val);
1311}
1312EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1313
1314/**
1315 * snd_soc_info_enum_ext - external enumerated single mixer info callback
1316 * @kcontrol: mixer control
1317 * @uinfo: control element information
1318 *
1319 * Callback to provide information about an external enumerated
1320 * single mixer.
1321 *
1322 * Returns 0 for success.
1323 */
1324int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
1325        struct snd_ctl_elem_info *uinfo)
1326{
1327        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1328
1329        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1330        uinfo->count = 1;
1331        uinfo->value.enumerated.items = e->mask;
1332
1333        if (uinfo->value.enumerated.item > e->mask - 1)
1334                uinfo->value.enumerated.item = e->mask - 1;
1335        strcpy(uinfo->value.enumerated.name,
1336                e->texts[uinfo->value.enumerated.item]);
1337        return 0;
1338}
1339EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
1340
1341/**
1342 * snd_soc_info_volsw_ext - external single mixer info callback
1343 * @kcontrol: mixer control
1344 * @uinfo: control element information
1345 *
1346 * Callback to provide information about a single external mixer control.
1347 *
1348 * Returns 0 for success.
1349 */
1350int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
1351        struct snd_ctl_elem_info *uinfo)
1352{
1353        int mask = kcontrol->private_value;
1354
1355        uinfo->type =
1356                mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1357        uinfo->count = 1;
1358        uinfo->value.integer.min = 0;
1359        uinfo->value.integer.max = mask;
1360        return 0;
1361}
1362EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
1363
1364/**
1365 * snd_soc_info_volsw - single mixer info callback
1366 * @kcontrol: mixer control
1367 * @uinfo: control element information
1368 *
1369 * Callback to provide information about a single mixer control.
1370 *
1371 * Returns 0 for success.
1372 */
1373int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1374        struct snd_ctl_elem_info *uinfo)
1375{
1376        int mask = (kcontrol->private_value >> 16) & 0xff;
1377        int shift = (kcontrol->private_value >> 8) & 0x0f;
1378        int rshift = (kcontrol->private_value >> 12) & 0x0f;
1379
1380        uinfo->type =
1381                mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1382        uinfo->count = shift == rshift ? 1 : 2;
1383        uinfo->value.integer.min = 0;
1384        uinfo->value.integer.max = mask;
1385        return 0;
1386}
1387EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
1388
1389/**
1390 * snd_soc_get_volsw - single mixer get callback
1391 * @kcontrol: mixer control
1392 * @uinfo: control element information
1393 *
1394 * Callback to get the value of a single mixer control.
1395 *
1396 * Returns 0 for success.
1397 */
1398int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
1399        struct snd_ctl_elem_value *ucontrol)
1400{
1401        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1402        int reg = kcontrol->private_value & 0xff;
1403        int shift = (kcontrol->private_value >> 8) & 0x0f;
1404        int rshift = (kcontrol->private_value >> 12) & 0x0f;
1405        int mask = (kcontrol->private_value >> 16) & 0xff;
1406        int invert = (kcontrol->private_value >> 24) & 0x01;
1407
1408        ucontrol->value.integer.value[0] =
1409                (snd_soc_read(codec, reg) >> shift) & mask;
1410        if (shift != rshift)
1411                ucontrol->value.integer.value[1] =
1412                        (snd_soc_read(codec, reg) >> rshift) & mask;
1413        if (invert) {
1414                ucontrol->value.integer.value[0] =
1415                        mask - ucontrol->value.integer.value[0];
1416                if (shift != rshift)
1417                        ucontrol->value.integer.value[1] =
1418                                mask - ucontrol->value.integer.value[1];
1419        }
1420
1421        return 0;
1422}
1423EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
1424
1425/**
1426 * snd_soc_put_volsw - single mixer put callback
1427 * @kcontrol: mixer control
1428 * @uinfo: control element information
1429 *
1430 * Callback to set the value of a single mixer control.
1431 *
1432 * Returns 0 for success.
1433 */
1434int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
1435        struct snd_ctl_elem_value *ucontrol)
1436{
1437        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1438        int reg = kcontrol->private_value & 0xff;
1439        int shift = (kcontrol->private_value >> 8) & 0x0f;
1440        int rshift = (kcontrol->private_value >> 12) & 0x0f;
1441        int mask = (kcontrol->private_value >> 16) & 0xff;
1442        int invert = (kcontrol->private_value >> 24) & 0x01;
1443        int err;
1444        unsigned short val, val2, val_mask;
1445
1446        val = (ucontrol->value.integer.value[0] & mask);
1447        if (invert)
1448                val = mask - val;
1449        val_mask = mask << shift;
1450        val = val << shift;
1451        if (shift != rshift) {
1452                val2 = (ucontrol->value.integer.value[1] & mask);
1453                if (invert)
1454                        val2 = mask - val2;
1455                val_mask |= mask << rshift;
1456                val |= val2 << rshift;
1457        }
1458        err = snd_soc_update_bits(codec, reg, val_mask, val);
1459        return err;
1460}
1461EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
1462
1463/**
1464 * snd_soc_info_volsw_2r - double mixer info callback
1465 * @kcontrol: mixer control
1466 * @uinfo: control element information
1467 *
1468 * Callback to provide information about a double mixer control that
1469 * spans 2 codec registers.
1470 *
1471 * Returns 0 for success.
1472 */
1473int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
1474        struct snd_ctl_elem_info *uinfo)
1475{
1476        int mask = (kcontrol->private_value >> 12) & 0xff;
1477
1478        uinfo->type =
1479                mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1480        uinfo->count = 2;
1481        uinfo->value.integer.min = 0;
1482        uinfo->value.integer.max = mask;
1483        return 0;
1484}
1485EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
1486
1487/**
1488 * snd_soc_get_volsw_2r - double mixer get callback
1489 * @kcontrol: mixer control
1490 * @uinfo: control element information
1491 *
1492 * Callback to get the value of a double mixer control that spans 2 registers.
1493 *
1494 * Returns 0 for success.
1495 */
1496int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
1497        struct snd_ctl_elem_value *ucontrol)
1498{
1499        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1500        int reg = kcontrol->private_value & 0xff;
1501        int reg2 = (kcontrol->private_value >> 24) & 0xff;
1502        int shift = (kcontrol->private_value >> 8) & 0x0f;
1503        int mask = (kcontrol->private_value >> 12) & 0xff;
1504        int invert = (kcontrol->private_value >> 20) & 0x01;
1505
1506        ucontrol->value.integer.value[0] =
1507                (snd_soc_read(codec, reg) >> shift) & mask;
1508        ucontrol->value.integer.value[1] =
1509                (snd_soc_read(codec, reg2) >> shift) & mask;
1510        if (invert) {
1511                ucontrol->value.integer.value[0] =
1512                        mask - ucontrol->value.integer.value[0];
1513                ucontrol->value.integer.value[1] =
1514                        mask - ucontrol->value.integer.value[1];
1515        }
1516
1517        return 0;
1518}
1519EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
1520
1521/**
1522 * snd_soc_put_volsw_2r - double mixer set callback
1523 * @kcontrol: mixer control
1524 * @uinfo: control element information
1525 *
1526 * Callback to set the value of a double mixer control that spans 2 registers.
1527 *
1528 * Returns 0 for success.
1529 */
1530int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
1531        struct snd_ctl_elem_value *ucontrol)
1532{
1533        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1534        int reg = kcontrol->private_value & 0xff;
1535        int reg2 = (kcontrol->private_value >> 24) & 0xff;
1536        int shift = (kcontrol->private_value >> 8) & 0x0f;
1537        int mask = (kcontrol->private_value >> 12) & 0xff;
1538        int invert = (kcontrol->private_value >> 20) & 0x01;
1539        int err;
1540        unsigned short val, val2, val_mask;
1541
1542        val_mask = mask << shift;
1543        val = (ucontrol->value.integer.value[0] & mask);
1544        val2 = (ucontrol->value.integer.value[1] & mask);
1545
1546        if (invert) {
1547                val = mask - val;
1548                val2 = mask - val2;
1549        }
1550
1551        val = val << shift;
1552        val2 = val2 << shift;
1553
1554        if ((err = snd_soc_update_bits(codec, reg, val_mask, val)) < 0)
1555                return err;
1556
1557        err = snd_soc_update_bits(codec, reg2, val_mask, val2);
1558        return err;
1559}
1560EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
1561
1562static int __devinit snd_soc_init(void)
1563{
1564        printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
1565        return platform_driver_register(&soc_driver);
1566}
1567
1568static void snd_soc_exit(void)
1569{
1570        platform_driver_unregister(&soc_driver);
1571}
1572
1573module_init(snd_soc_init);
1574module_exit(snd_soc_exit);
1575
1576/* Module information */
1577MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
1578MODULE_DESCRIPTION("ALSA SoC Core");
1579MODULE_LICENSE("GPL");
1580