linux/sound/pci/au88x0/au88x0_pcm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 */
   4 
   5/*
   6 * Vortex PCM ALSA driver.
   7 *
   8 * Supports ADB and WT DMA. Unfortunately, WT channels do not run yet.
   9 * It remains stuck,and DMA transfers do not happen. 
  10 */
  11#include <sound/asoundef.h>
  12#include <linux/time.h>
  13#include <sound/core.h>
  14#include <sound/pcm.h>
  15#include <sound/pcm_params.h>
  16#include "au88x0.h"
  17
  18#define VORTEX_PCM_TYPE(x) (x->name[40])
  19
  20/* hardware definition */
  21static const struct snd_pcm_hardware snd_vortex_playback_hw_adb = {
  22        .info =
  23            (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
  24             SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
  25             SNDRV_PCM_INFO_MMAP_VALID),
  26        .formats =
  27            SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |
  28            SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,
  29        .rates = SNDRV_PCM_RATE_CONTINUOUS,
  30        .rate_min = 5000,
  31        .rate_max = 48000,
  32        .channels_min = 1,
  33        .channels_max = 2,
  34        .buffer_bytes_max = 0x10000,
  35        .period_bytes_min = 0x20,
  36        .period_bytes_max = 0x1000,
  37        .periods_min = 2,
  38        .periods_max = 1024,
  39};
  40
  41#ifndef CHIP_AU8820
  42static const struct snd_pcm_hardware snd_vortex_playback_hw_a3d = {
  43        .info =
  44            (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
  45             SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
  46             SNDRV_PCM_INFO_MMAP_VALID),
  47        .formats =
  48            SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |
  49            SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,
  50        .rates = SNDRV_PCM_RATE_CONTINUOUS,
  51        .rate_min = 5000,
  52        .rate_max = 48000,
  53        .channels_min = 1,
  54        .channels_max = 1,
  55        .buffer_bytes_max = 0x10000,
  56        .period_bytes_min = 0x100,
  57        .period_bytes_max = 0x1000,
  58        .periods_min = 2,
  59        .periods_max = 64,
  60};
  61#endif
  62static const struct snd_pcm_hardware snd_vortex_playback_hw_spdif = {
  63        .info =
  64            (SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
  65             SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
  66             SNDRV_PCM_INFO_MMAP_VALID),
  67        .formats =
  68            SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |
  69            SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | SNDRV_PCM_FMTBIT_MU_LAW |
  70            SNDRV_PCM_FMTBIT_A_LAW,
  71        .rates =
  72            SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
  73        .rate_min = 32000,
  74        .rate_max = 48000,
  75        .channels_min = 1,
  76        .channels_max = 2,
  77        .buffer_bytes_max = 0x10000,
  78        .period_bytes_min = 0x100,
  79        .period_bytes_max = 0x1000,
  80        .periods_min = 2,
  81        .periods_max = 64,
  82};
  83
  84#ifndef CHIP_AU8810
  85static const struct snd_pcm_hardware snd_vortex_playback_hw_wt = {
  86        .info = (SNDRV_PCM_INFO_MMAP |
  87                 SNDRV_PCM_INFO_INTERLEAVED |
  88                 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
  89        .formats = SNDRV_PCM_FMTBIT_S16_LE,
  90        .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS, // SNDRV_PCM_RATE_48000,
  91        .rate_min = 8000,
  92        .rate_max = 48000,
  93        .channels_min = 1,
  94        .channels_max = 2,
  95        .buffer_bytes_max = 0x10000,
  96        .period_bytes_min = 0x0400,
  97        .period_bytes_max = 0x1000,
  98        .periods_min = 2,
  99        .periods_max = 64,
 100};
 101#endif
 102#ifdef CHIP_AU8830
 103static const unsigned int au8830_channels[3] = {
 104        1, 2, 4,
 105};
 106
 107static const struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {
 108        .count = ARRAY_SIZE(au8830_channels),
 109        .list = au8830_channels,
 110        .mask = 0,
 111};
 112#endif
 113
 114static void vortex_notify_pcm_vol_change(struct snd_card *card,
 115                        struct snd_kcontrol *kctl, int activate)
 116{
 117        if (activate)
 118                kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 119        else
 120                kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 121        snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
 122                                SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id));
 123}
 124
 125/* open callback */
 126static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
 127{
 128        vortex_t *vortex = snd_pcm_substream_chip(substream);
 129        struct snd_pcm_runtime *runtime = substream->runtime;
 130        int err;
 131        
 132        /* Force equal size periods */
 133        err = snd_pcm_hw_constraint_integer(runtime,
 134                                            SNDRV_PCM_HW_PARAM_PERIODS);
 135        if (err < 0)
 136                return err;
 137        /* Avoid PAGE_SIZE boundary to fall inside of a period. */
 138        err = snd_pcm_hw_constraint_pow2(runtime, 0,
 139                                         SNDRV_PCM_HW_PARAM_PERIOD_BYTES);
 140        if (err < 0)
 141                return err;
 142
 143        snd_pcm_hw_constraint_step(runtime, 0,
 144                                        SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 64);
 145
 146        if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
 147#ifndef CHIP_AU8820
 148                if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_A3D) {
 149                        runtime->hw = snd_vortex_playback_hw_a3d;
 150                }
 151#endif
 152                if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_SPDIF) {
 153                        runtime->hw = snd_vortex_playback_hw_spdif;
 154                        switch (vortex->spdif_sr) {
 155                        case 32000:
 156                                runtime->hw.rates = SNDRV_PCM_RATE_32000;
 157                                break;
 158                        case 44100:
 159                                runtime->hw.rates = SNDRV_PCM_RATE_44100;
 160                                break;
 161                        case 48000:
 162                                runtime->hw.rates = SNDRV_PCM_RATE_48000;
 163                                break;
 164                        }
 165                }
 166                if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB
 167                    || VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_I2S)
 168                        runtime->hw = snd_vortex_playback_hw_adb;
 169#ifdef CHIP_AU8830
 170                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 171                        VORTEX_IS_QUAD(vortex) &&
 172                        VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
 173                        runtime->hw.channels_max = 4;
 174                        snd_pcm_hw_constraint_list(runtime, 0,
 175                                SNDRV_PCM_HW_PARAM_CHANNELS,
 176                                &hw_constraints_au8830_channels);
 177                }
 178#endif
 179                substream->runtime->private_data = NULL;
 180        }
 181#ifndef CHIP_AU8810
 182        else {
 183                runtime->hw = snd_vortex_playback_hw_wt;
 184                substream->runtime->private_data = NULL;
 185        }
 186#endif
 187        return 0;
 188}
 189
 190/* close callback */
 191static int snd_vortex_pcm_close(struct snd_pcm_substream *substream)
 192{
 193        //vortex_t *chip = snd_pcm_substream_chip(substream);
 194        stream_t *stream = (stream_t *) substream->runtime->private_data;
 195
 196        // the hardware-specific codes will be here
 197        if (stream != NULL) {
 198                stream->substream = NULL;
 199                stream->nr_ch = 0;
 200        }
 201        substream->runtime->private_data = NULL;
 202        return 0;
 203}
 204
 205/* hw_params callback */
 206static int
 207snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
 208                         struct snd_pcm_hw_params *hw_params)
 209{
 210        vortex_t *chip = snd_pcm_substream_chip(substream);
 211        stream_t *stream = (stream_t *) (substream->runtime->private_data);
 212
 213        /*
 214           pr_info( "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),
 215           params_period_bytes(hw_params), params_channels(hw_params));
 216         */
 217        spin_lock_irq(&chip->lock);
 218        // Make audio routes and config buffer DMA.
 219        if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
 220                int dma, type = VORTEX_PCM_TYPE(substream->pcm);
 221                /* Dealloc any routes. */
 222                if (stream != NULL)
 223                        vortex_adb_allocroute(chip, stream->dma,
 224                                              stream->nr_ch, stream->dir,
 225                                              stream->type,
 226                                              substream->number);
 227                /* Alloc routes. */
 228                dma =
 229                    vortex_adb_allocroute(chip, -1,
 230                                          params_channels(hw_params),
 231                                          substream->stream, type,
 232                                          substream->number);
 233                if (dma < 0) {
 234                        spin_unlock_irq(&chip->lock);
 235                        return dma;
 236                }
 237                stream = substream->runtime->private_data = &chip->dma_adb[dma];
 238                stream->substream = substream;
 239                /* Setup Buffers. */
 240                vortex_adbdma_setbuffers(chip, dma,
 241                                         params_period_bytes(hw_params),
 242                                         params_periods(hw_params));
 243                if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
 244                        chip->pcm_vol[substream->number].active = 1;
 245                        vortex_notify_pcm_vol_change(chip->card,
 246                                chip->pcm_vol[substream->number].kctl, 1);
 247                }
 248        }
 249#ifndef CHIP_AU8810
 250        else {
 251                /* if (stream != NULL)
 252                   vortex_wt_allocroute(chip, substream->number, 0); */
 253                vortex_wt_allocroute(chip, substream->number,
 254                                     params_channels(hw_params));
 255                stream = substream->runtime->private_data =
 256                    &chip->dma_wt[substream->number];
 257                stream->dma = substream->number;
 258                stream->substream = substream;
 259                vortex_wtdma_setbuffers(chip, substream->number,
 260                                        params_period_bytes(hw_params),
 261                                        params_periods(hw_params));
 262        }
 263#endif
 264        spin_unlock_irq(&chip->lock);
 265        return 0;
 266}
 267
 268/* hw_free callback */
 269static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
 270{
 271        vortex_t *chip = snd_pcm_substream_chip(substream);
 272        stream_t *stream = (stream_t *) (substream->runtime->private_data);
 273
 274        spin_lock_irq(&chip->lock);
 275        // Delete audio routes.
 276        if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
 277                if (stream != NULL) {
 278                        if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
 279                                chip->pcm_vol[substream->number].active = 0;
 280                                vortex_notify_pcm_vol_change(chip->card,
 281                                        chip->pcm_vol[substream->number].kctl,
 282                                        0);
 283                        }
 284                        vortex_adb_allocroute(chip, stream->dma,
 285                                              stream->nr_ch, stream->dir,
 286                                              stream->type,
 287                                              substream->number);
 288                }
 289        }
 290#ifndef CHIP_AU8810
 291        else {
 292                if (stream != NULL)
 293                        vortex_wt_allocroute(chip, stream->dma, 0);
 294        }
 295#endif
 296        substream->runtime->private_data = NULL;
 297        spin_unlock_irq(&chip->lock);
 298
 299        return 0;
 300}
 301
 302/* prepare callback */
 303static int snd_vortex_pcm_prepare(struct snd_pcm_substream *substream)
 304{
 305        vortex_t *chip = snd_pcm_substream_chip(substream);
 306        struct snd_pcm_runtime *runtime = substream->runtime;
 307        stream_t *stream = (stream_t *) substream->runtime->private_data;
 308        int dma = stream->dma, fmt, dir;
 309
 310        // set up the hardware with the current configuration.
 311        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 312                dir = 1;
 313        else
 314                dir = 0;
 315        fmt = vortex_alsafmt_aspfmt(runtime->format, chip);
 316        spin_lock_irq(&chip->lock);
 317        if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
 318                vortex_adbdma_setmode(chip, dma, 1, dir, fmt,
 319                                runtime->channels == 1 ? 0 : 1, 0);
 320                vortex_adbdma_setstartbuffer(chip, dma, 0);
 321                if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_SPDIF)
 322                        vortex_adb_setsrc(chip, dma, runtime->rate, dir);
 323        }
 324#ifndef CHIP_AU8810
 325        else {
 326                vortex_wtdma_setmode(chip, dma, 1, fmt, 0, 0);
 327                // FIXME: Set rate (i guess using vortex_wt_writereg() somehow).
 328                vortex_wtdma_setstartbuffer(chip, dma, 0);
 329        }
 330#endif
 331        spin_unlock_irq(&chip->lock);
 332        return 0;
 333}
 334
 335/* trigger callback */
 336static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 337{
 338        vortex_t *chip = snd_pcm_substream_chip(substream);
 339        stream_t *stream = (stream_t *) substream->runtime->private_data;
 340        int dma = stream->dma;
 341
 342        spin_lock(&chip->lock);
 343        switch (cmd) {
 344        case SNDRV_PCM_TRIGGER_START:
 345                // do something to start the PCM engine
 346                //printk(KERN_INFO "vortex: start %d\n", dma);
 347                stream->fifo_enabled = 1;
 348                if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
 349                        vortex_adbdma_resetup(chip, dma);
 350                        vortex_adbdma_startfifo(chip, dma);
 351                }
 352#ifndef CHIP_AU8810
 353                else {
 354                        dev_info(chip->card->dev, "wt start %d\n", dma);
 355                        vortex_wtdma_startfifo(chip, dma);
 356                }
 357#endif
 358                break;
 359        case SNDRV_PCM_TRIGGER_STOP:
 360                // do something to stop the PCM engine
 361                //printk(KERN_INFO "vortex: stop %d\n", dma);
 362                stream->fifo_enabled = 0;
 363                if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
 364                        vortex_adbdma_stopfifo(chip, dma);
 365#ifndef CHIP_AU8810
 366                else {
 367                        dev_info(chip->card->dev, "wt stop %d\n", dma);
 368                        vortex_wtdma_stopfifo(chip, dma);
 369                }
 370#endif
 371                break;
 372        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 373                //printk(KERN_INFO "vortex: pause %d\n", dma);
 374                if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
 375                        vortex_adbdma_pausefifo(chip, dma);
 376#ifndef CHIP_AU8810
 377                else
 378                        vortex_wtdma_pausefifo(chip, dma);
 379#endif
 380                break;
 381        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 382                //printk(KERN_INFO "vortex: resume %d\n", dma);
 383                if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
 384                        vortex_adbdma_resumefifo(chip, dma);
 385#ifndef CHIP_AU8810
 386                else
 387                        vortex_wtdma_resumefifo(chip, dma);
 388#endif
 389                break;
 390        default:
 391                spin_unlock(&chip->lock);
 392                return -EINVAL;
 393        }
 394        spin_unlock(&chip->lock);
 395        return 0;
 396}
 397
 398/* pointer callback */
 399static snd_pcm_uframes_t snd_vortex_pcm_pointer(struct snd_pcm_substream *substream)
 400{
 401        vortex_t *chip = snd_pcm_substream_chip(substream);
 402        stream_t *stream = (stream_t *) substream->runtime->private_data;
 403        int dma = stream->dma;
 404        snd_pcm_uframes_t current_ptr = 0;
 405
 406        spin_lock(&chip->lock);
 407        if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
 408                current_ptr = vortex_adbdma_getlinearpos(chip, dma);
 409#ifndef CHIP_AU8810
 410        else
 411                current_ptr = vortex_wtdma_getlinearpos(chip, dma);
 412#endif
 413        //printk(KERN_INFO "vortex: pointer = 0x%x\n", current_ptr);
 414        spin_unlock(&chip->lock);
 415        current_ptr = bytes_to_frames(substream->runtime, current_ptr);
 416        if (current_ptr >= substream->runtime->buffer_size)
 417                current_ptr = 0;
 418        return current_ptr;
 419}
 420
 421/* operators */
 422static const struct snd_pcm_ops snd_vortex_playback_ops = {
 423        .open = snd_vortex_pcm_open,
 424        .close = snd_vortex_pcm_close,
 425        .hw_params = snd_vortex_pcm_hw_params,
 426        .hw_free = snd_vortex_pcm_hw_free,
 427        .prepare = snd_vortex_pcm_prepare,
 428        .trigger = snd_vortex_pcm_trigger,
 429        .pointer = snd_vortex_pcm_pointer,
 430};
 431
 432/*
 433*  definitions of capture are omitted here...
 434*/
 435
 436static const char * const vortex_pcm_prettyname[VORTEX_PCM_LAST] = {
 437        CARD_NAME " ADB",
 438        CARD_NAME " SPDIF",
 439        CARD_NAME " A3D",
 440        CARD_NAME " WT",
 441        CARD_NAME " I2S",
 442};
 443static const char * const vortex_pcm_name[VORTEX_PCM_LAST] = {
 444        "adb",
 445        "spdif",
 446        "a3d",
 447        "wt",
 448        "i2s",
 449};
 450
 451/* SPDIF kcontrol */
 452
 453static int snd_vortex_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 454{
 455        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
 456        uinfo->count = 1;
 457        return 0;
 458}
 459
 460static int snd_vortex_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 461{
 462        ucontrol->value.iec958.status[0] = 0xff;
 463        ucontrol->value.iec958.status[1] = 0xff;
 464        ucontrol->value.iec958.status[2] = 0xff;
 465        ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;
 466        return 0;
 467}
 468
 469static int snd_vortex_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 470{
 471        vortex_t *vortex = snd_kcontrol_chip(kcontrol);
 472        ucontrol->value.iec958.status[0] = 0x00;
 473        ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL|IEC958_AES1_CON_DIGDIGCONV_ID;
 474        ucontrol->value.iec958.status[2] = 0x00;
 475        switch (vortex->spdif_sr) {
 476        case 32000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_32000; break;
 477        case 44100: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_44100; break;
 478        case 48000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; break;
 479        }
 480        return 0;
 481}
 482
 483static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 484{
 485        vortex_t *vortex = snd_kcontrol_chip(kcontrol);
 486        int spdif_sr = 48000;
 487        switch (ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) {
 488        case IEC958_AES3_CON_FS_32000: spdif_sr = 32000; break;
 489        case IEC958_AES3_CON_FS_44100: spdif_sr = 44100; break;
 490        case IEC958_AES3_CON_FS_48000: spdif_sr = 48000; break;
 491        }
 492        if (spdif_sr == vortex->spdif_sr)
 493                return 0;
 494        vortex->spdif_sr = spdif_sr;
 495        vortex_spdif_init(vortex, vortex->spdif_sr, 1);
 496        return 1;
 497}
 498
 499/* spdif controls */
 500static const struct snd_kcontrol_new snd_vortex_mixer_spdif[] = {
 501        {
 502                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
 503                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
 504                .info =         snd_vortex_spdif_info,
 505                .get =          snd_vortex_spdif_get,
 506                .put =          snd_vortex_spdif_put,
 507        },
 508        {
 509                .access =       SNDRV_CTL_ELEM_ACCESS_READ,
 510                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
 511                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
 512                .info =         snd_vortex_spdif_info,
 513                .get =          snd_vortex_spdif_mask_get
 514        },
 515};
 516
 517/* subdevice PCM Volume control */
 518
 519static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol,
 520                                struct snd_ctl_elem_info *uinfo)
 521{
 522        vortex_t *vortex = snd_kcontrol_chip(kcontrol);
 523        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 524        uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
 525        uinfo->value.integer.min = -128;
 526        uinfo->value.integer.max = 32;
 527        return 0;
 528}
 529
 530static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol,
 531                                struct snd_ctl_elem_value *ucontrol)
 532{
 533        int i;
 534        vortex_t *vortex = snd_kcontrol_chip(kcontrol);
 535        int subdev = kcontrol->id.subdevice;
 536        struct pcm_vol *p = &vortex->pcm_vol[subdev];
 537        int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
 538        for (i = 0; i < max_chn; i++)
 539                ucontrol->value.integer.value[i] = p->vol[i];
 540        return 0;
 541}
 542
 543static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
 544                                struct snd_ctl_elem_value *ucontrol)
 545{
 546        int i;
 547        int changed = 0;
 548        int mixin;
 549        unsigned char vol;
 550        vortex_t *vortex = snd_kcontrol_chip(kcontrol);
 551        int subdev = kcontrol->id.subdevice;
 552        struct pcm_vol *p = &vortex->pcm_vol[subdev];
 553        int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
 554        for (i = 0; i < max_chn; i++) {
 555                if (p->vol[i] != ucontrol->value.integer.value[i]) {
 556                        p->vol[i] = ucontrol->value.integer.value[i];
 557                        if (p->active) {
 558                                switch (vortex->dma_adb[p->dma].nr_ch) {
 559                                case 1:
 560                                        mixin = p->mixin[0];
 561                                        break;
 562                                case 2:
 563                                default:
 564                                        mixin = p->mixin[(i < 2) ? i : (i - 2)];
 565                                        break;
 566                                case 4:
 567                                        mixin = p->mixin[i];
 568                                        break;
 569                                }
 570                                vol = p->vol[i];
 571                                vortex_mix_setinputvolumebyte(vortex,
 572                                        vortex->mixplayb[i], mixin, vol);
 573                        }
 574                        changed = 1;
 575                }
 576        }
 577        return changed;
 578}
 579
 580static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
 581
 582static const struct snd_kcontrol_new snd_vortex_pcm_vol = {
 583        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
 584        .name = "PCM Playback Volume",
 585        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 586                SNDRV_CTL_ELEM_ACCESS_TLV_READ |
 587                SNDRV_CTL_ELEM_ACCESS_INACTIVE,
 588        .info = snd_vortex_pcm_vol_info,
 589        .get = snd_vortex_pcm_vol_get,
 590        .put = snd_vortex_pcm_vol_put,
 591        .tlv = { .p = vortex_pcm_vol_db_scale },
 592};
 593
 594/* create a pcm device */
 595static int snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
 596{
 597        struct snd_pcm *pcm;
 598        struct snd_kcontrol *kctl;
 599        int i;
 600        int err, nr_capt;
 601
 602        if (!chip || idx < 0 || idx >= VORTEX_PCM_LAST)
 603                return -ENODEV;
 604
 605        /* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the 
 606         * same dma engine. WT uses it own separate dma engine which can't capture. */
 607        if (idx == VORTEX_PCM_ADB)
 608                nr_capt = nr;
 609        else
 610                nr_capt = 0;
 611        err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
 612                          nr_capt, &pcm);
 613        if (err < 0)
 614                return err;
 615        snprintf(pcm->name, sizeof(pcm->name),
 616                "%s %s", CARD_NAME_SHORT, vortex_pcm_name[idx]);
 617        chip->pcm[idx] = pcm;
 618        // This is an evil hack, but it saves a lot of duplicated code.
 619        VORTEX_PCM_TYPE(pcm) = idx;
 620        pcm->private_data = chip;
 621        /* set operators */
 622        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 623                        &snd_vortex_playback_ops);
 624        if (idx == VORTEX_PCM_ADB)
 625                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 626                                &snd_vortex_playback_ops);
 627        
 628        /* pre-allocation of Scatter-Gather buffers */
 629        
 630        snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
 631                                       &chip->pci_dev->dev, 0x10000, 0x10000);
 632
 633        switch (VORTEX_PCM_TYPE(pcm)) {
 634        case VORTEX_PCM_ADB:
 635                err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 636                                             snd_pcm_std_chmaps,
 637                                             VORTEX_IS_QUAD(chip) ? 4 : 2,
 638                                             0, NULL);
 639                if (err < 0)
 640                        return err;
 641                err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
 642                                             snd_pcm_std_chmaps, 2, 0, NULL);
 643                if (err < 0)
 644                        return err;
 645                break;
 646#ifdef CHIP_AU8830
 647        case VORTEX_PCM_A3D:
 648                err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 649                                             snd_pcm_std_chmaps, 1, 0, NULL);
 650                if (err < 0)
 651                        return err;
 652                break;
 653#endif
 654        }
 655
 656        if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) {
 657                for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) {
 658                        kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip);
 659                        if (!kctl)
 660                                return -ENOMEM;
 661                        err = snd_ctl_add(chip->card, kctl);
 662                        if (err < 0)
 663                                return err;
 664                }
 665        }
 666        if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) {
 667                for (i = 0; i < NR_PCM; i++) {
 668                        chip->pcm_vol[i].active = 0;
 669                        chip->pcm_vol[i].dma = -1;
 670                        kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip);
 671                        if (!kctl)
 672                                return -ENOMEM;
 673                        chip->pcm_vol[i].kctl = kctl;
 674                        kctl->id.device = 0;
 675                        kctl->id.subdevice = i;
 676                        err = snd_ctl_add(chip->card, kctl);
 677                        if (err < 0)
 678                                return err;
 679                }
 680        }
 681        return 0;
 682}
 683