linux/sound/pci/ca0106/ca0106_mixer.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
   3 *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
   4 *  Version: 0.0.18
   5 *
   6 *  FEATURES currently supported:
   7 *    See ca0106_main.c for features.
   8 * 
   9 *  Changelog:
  10 *    Support interrupts per period.
  11 *    Removed noise from Center/LFE channel when in Analog mode.
  12 *    Rename and remove mixer controls.
  13 *  0.0.6
  14 *    Use separate card based DMA buffer for periods table list.
  15 *  0.0.7
  16 *    Change remove and rename ctrls into lists.
  17 *  0.0.8
  18 *    Try to fix capture sources.
  19 *  0.0.9
  20 *    Fix AC3 output.
  21 *    Enable S32_LE format support.
  22 *  0.0.10
  23 *    Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".)
  24 *  0.0.11
  25 *    Add Model name recognition.
  26 *  0.0.12
  27 *    Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period.
  28 *    Remove redundent "voice" handling.
  29 *  0.0.13
  30 *    Single trigger call for multi channels.
  31 *  0.0.14
  32 *    Set limits based on what the sound card hardware can do.
  33 *    playback periods_min=2, periods_max=8
  34 *    capture hw constraints require period_size = n * 64 bytes.
  35 *    playback hw constraints require period_size = n * 64 bytes.
  36 *  0.0.15
  37 *    Separated ca0106.c into separate functional .c files.
  38 *  0.0.16
  39 *    Modified Copyright message.
  40 *  0.0.17
  41 *    Implement Mic and Line in Capture.
  42 *  0.0.18
  43 *    Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
  44 *
  45 *  This code was initially based on code from ALSA's emu10k1x.c which is:
  46 *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
  47 *
  48 *   This program is free software; you can redistribute it and/or modify
  49 *   it under the terms of the GNU General Public License as published by
  50 *   the Free Software Foundation; either version 2 of the License, or
  51 *   (at your option) any later version.
  52 *
  53 *   This program is distributed in the hope that it will be useful,
  54 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  55 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  56 *   GNU General Public License for more details.
  57 *
  58 *   You should have received a copy of the GNU General Public License
  59 *   along with this program; if not, write to the Free Software
  60 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  61 *
  62 */
  63#include <linux/delay.h>
  64#include <linux/init.h>
  65#include <linux/interrupt.h>
  66#include <linux/moduleparam.h>
  67#include <sound/core.h>
  68#include <sound/initval.h>
  69#include <sound/pcm.h>
  70#include <sound/ac97_codec.h>
  71#include <sound/info.h>
  72#include <sound/tlv.h>
  73#include <linux/io.h>
  74
  75#include "ca0106.h"
  76
  77static void ca0106_spdif_enable(struct snd_ca0106 *emu)
  78{
  79        unsigned int val;
  80
  81        if (emu->spdif_enable) {
  82                /* Digital */
  83                snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
  84                snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
  85                val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000;
  86                snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
  87                val = inl(emu->port + GPIO) & ~0x101;
  88                outl(val, emu->port + GPIO);
  89
  90        } else {
  91                /* Analog */
  92                snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
  93                snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
  94                val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000;
  95                snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
  96                val = inl(emu->port + GPIO) | 0x101;
  97                outl(val, emu->port + GPIO);
  98        }
  99}
 100
 101static void ca0106_set_capture_source(struct snd_ca0106 *emu)
 102{
 103        unsigned int val = emu->capture_source;
 104        unsigned int source, mask;
 105        source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
 106        mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
 107        snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
 108}
 109
 110static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
 111                                          unsigned int val, int force)
 112{
 113        unsigned int ngain, ogain;
 114        u32 source;
 115
 116        snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
 117        ngain = emu->i2c_capture_volume[val][0]; /* Left */
 118        ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
 119        if (force || ngain != ogain)
 120                snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff);
 121        ngain = emu->i2c_capture_volume[val][1]; /* Right */
 122        ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
 123        if (force || ngain != ogain)
 124                snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff);
 125        source = 1 << val;
 126        snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
 127        emu->i2c_capture_source = val;
 128}
 129
 130static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
 131{
 132        u32 tmp;
 133
 134        if (emu->capture_mic_line_in) {
 135                /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
 136                tmp = inl(emu->port+GPIO) & ~0x400;
 137                tmp = tmp | 0x400;
 138                outl(tmp, emu->port+GPIO);
 139                /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
 140        } else {
 141                /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
 142                tmp = inl(emu->port+GPIO) & ~0x400;
 143                outl(tmp, emu->port+GPIO);
 144                /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */
 145        }
 146}
 147
 148static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
 149{
 150        snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]);
 151}
 152
 153/*
 154 */
 155static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
 156static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
 157
 158#define snd_ca0106_shared_spdif_info    snd_ctl_boolean_mono_info
 159
 160static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
 161                                        struct snd_ctl_elem_value *ucontrol)
 162{
 163        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 164
 165        ucontrol->value.integer.value[0] = emu->spdif_enable;
 166        return 0;
 167}
 168
 169static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
 170                                        struct snd_ctl_elem_value *ucontrol)
 171{
 172        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 173        unsigned int val;
 174        int change = 0;
 175
 176        val = !!ucontrol->value.integer.value[0];
 177        change = (emu->spdif_enable != val);
 178        if (change) {
 179                emu->spdif_enable = val;
 180                ca0106_spdif_enable(emu);
 181        }
 182        return change;
 183}
 184
 185static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
 186                                          struct snd_ctl_elem_info *uinfo)
 187{
 188        static const char * const texts[6] = {
 189                "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
 190        };
 191
 192        return snd_ctl_enum_info(uinfo, 1, 6, texts);
 193}
 194
 195static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
 196                                        struct snd_ctl_elem_value *ucontrol)
 197{
 198        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 199
 200        ucontrol->value.enumerated.item[0] = emu->capture_source;
 201        return 0;
 202}
 203
 204static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
 205                                        struct snd_ctl_elem_value *ucontrol)
 206{
 207        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 208        unsigned int val;
 209        int change = 0;
 210
 211        val = ucontrol->value.enumerated.item[0] ;
 212        if (val >= 6)
 213                return -EINVAL;
 214        change = (emu->capture_source != val);
 215        if (change) {
 216                emu->capture_source = val;
 217                ca0106_set_capture_source(emu);
 218        }
 219        return change;
 220}
 221
 222static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
 223                                          struct snd_ctl_elem_info *uinfo)
 224{
 225        static const char * const texts[4] = {
 226                "Phone", "Mic", "Line in", "Aux"
 227        };
 228
 229        return snd_ctl_enum_info(uinfo, 1, 4, texts);
 230}
 231
 232static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
 233                                        struct snd_ctl_elem_value *ucontrol)
 234{
 235        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 236
 237        ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
 238        return 0;
 239}
 240
 241static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
 242                                        struct snd_ctl_elem_value *ucontrol)
 243{
 244        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 245        unsigned int source_id;
 246        int change = 0;
 247        /* If the capture source has changed,
 248         * update the capture volume from the cached value
 249         * for the particular source.
 250         */
 251        source_id = ucontrol->value.enumerated.item[0] ;
 252        if (source_id >= 4)
 253                return -EINVAL;
 254        change = (emu->i2c_capture_source != source_id);
 255        if (change) {
 256                ca0106_set_i2c_capture_source(emu, source_id, 0);
 257        }
 258        return change;
 259}
 260
 261static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
 262                                               struct snd_ctl_elem_info *uinfo)
 263{
 264        static const char * const texts[2] = { "Side out", "Line in" };
 265
 266        return snd_ctl_enum_info(uinfo, 1, 2, texts);
 267}
 268
 269static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
 270                                               struct snd_ctl_elem_info *uinfo)
 271{
 272        static const char * const texts[2] = { "Line in", "Mic in" };
 273
 274        return snd_ctl_enum_info(uinfo, 1, 2, texts);
 275}
 276
 277static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
 278                                        struct snd_ctl_elem_value *ucontrol)
 279{
 280        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 281
 282        ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
 283        return 0;
 284}
 285
 286static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
 287                                        struct snd_ctl_elem_value *ucontrol)
 288{
 289        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 290        unsigned int val;
 291        int change = 0;
 292
 293        val = ucontrol->value.enumerated.item[0] ;
 294        if (val > 1)
 295                return -EINVAL;
 296        change = (emu->capture_mic_line_in != val);
 297        if (change) {
 298                emu->capture_mic_line_in = val;
 299                ca0106_set_capture_mic_line_in(emu);
 300        }
 301        return change;
 302}
 303
 304static const struct snd_kcontrol_new snd_ca0106_capture_mic_line_in =
 305{
 306        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 307        .name =         "Shared Mic/Line in Capture Switch",
 308        .info =         snd_ca0106_capture_mic_line_in_info,
 309        .get =          snd_ca0106_capture_mic_line_in_get,
 310        .put =          snd_ca0106_capture_mic_line_in_put
 311};
 312
 313static const struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out =
 314{
 315        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 316        .name =         "Shared Line in/Side out Capture Switch",
 317        .info =         snd_ca0106_capture_line_in_side_out_info,
 318        .get =          snd_ca0106_capture_mic_line_in_get,
 319        .put =          snd_ca0106_capture_mic_line_in_put
 320};
 321
 322
 323static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
 324                                 struct snd_ctl_elem_info *uinfo)
 325{
 326        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
 327        uinfo->count = 1;
 328        return 0;
 329}
 330
 331static void decode_spdif_bits(unsigned char *status, unsigned int bits)
 332{
 333        status[0] = (bits >> 0) & 0xff;
 334        status[1] = (bits >> 8) & 0xff;
 335        status[2] = (bits >> 16) & 0xff;
 336        status[3] = (bits >> 24) & 0xff;
 337}
 338
 339static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol,
 340                                 struct snd_ctl_elem_value *ucontrol)
 341{
 342        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 343        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 344
 345        decode_spdif_bits(ucontrol->value.iec958.status,
 346                          emu->spdif_bits[idx]);
 347        return 0;
 348}
 349
 350static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol,
 351                                 struct snd_ctl_elem_value *ucontrol)
 352{
 353        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 354        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 355
 356        decode_spdif_bits(ucontrol->value.iec958.status,
 357                          emu->spdif_str_bits[idx]);
 358        return 0;
 359}
 360
 361static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
 362                                      struct snd_ctl_elem_value *ucontrol)
 363{
 364        ucontrol->value.iec958.status[0] = 0xff;
 365        ucontrol->value.iec958.status[1] = 0xff;
 366        ucontrol->value.iec958.status[2] = 0xff;
 367        ucontrol->value.iec958.status[3] = 0xff;
 368        return 0;
 369}
 370
 371static unsigned int encode_spdif_bits(unsigned char *status)
 372{
 373        return ((unsigned int)status[0] << 0) |
 374                ((unsigned int)status[1] << 8) |
 375                ((unsigned int)status[2] << 16) |
 376                ((unsigned int)status[3] << 24);
 377}
 378
 379static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol,
 380                                 struct snd_ctl_elem_value *ucontrol)
 381{
 382        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 383        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 384        unsigned int val;
 385
 386        val = encode_spdif_bits(ucontrol->value.iec958.status);
 387        if (val != emu->spdif_bits[idx]) {
 388                emu->spdif_bits[idx] = val;
 389                /* FIXME: this isn't safe, but needed to keep the compatibility
 390                 * with older alsa-lib config
 391                 */
 392                emu->spdif_str_bits[idx] = val;
 393                ca0106_set_spdif_bits(emu, idx);
 394                return 1;
 395        }
 396        return 0;
 397}
 398
 399static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol,
 400                                 struct snd_ctl_elem_value *ucontrol)
 401{
 402        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 403        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 404        unsigned int val;
 405
 406        val = encode_spdif_bits(ucontrol->value.iec958.status);
 407        if (val != emu->spdif_str_bits[idx]) {
 408                emu->spdif_str_bits[idx] = val;
 409                ca0106_set_spdif_bits(emu, idx);
 410                return 1;
 411        }
 412        return 0;
 413}
 414
 415static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
 416                                  struct snd_ctl_elem_info *uinfo)
 417{
 418        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 419        uinfo->count = 2;
 420        uinfo->value.integer.min = 0;
 421        uinfo->value.integer.max = 255;
 422        return 0;
 423}
 424
 425static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
 426                                 struct snd_ctl_elem_value *ucontrol)
 427{
 428        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 429        unsigned int value;
 430        int channel_id, reg;
 431
 432        channel_id = (kcontrol->private_value >> 8) & 0xff;
 433        reg = kcontrol->private_value & 0xff;
 434
 435        value = snd_ca0106_ptr_read(emu, reg, channel_id);
 436        ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
 437        ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
 438        return 0;
 439}
 440
 441static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
 442                                 struct snd_ctl_elem_value *ucontrol)
 443{
 444        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 445        unsigned int oval, nval;
 446        int channel_id, reg;
 447
 448        channel_id = (kcontrol->private_value >> 8) & 0xff;
 449        reg = kcontrol->private_value & 0xff;
 450
 451        oval = snd_ca0106_ptr_read(emu, reg, channel_id);
 452        nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
 453                ((0xff - ucontrol->value.integer.value[1]) << 16);
 454        nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
 455                ((0xff - ucontrol->value.integer.value[1]) );
 456        if (oval == nval)
 457                return 0;
 458        snd_ca0106_ptr_write(emu, reg, channel_id, nval);
 459        return 1;
 460}
 461
 462static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
 463                                  struct snd_ctl_elem_info *uinfo)
 464{
 465        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 466        uinfo->count = 2;
 467        uinfo->value.integer.min = 0;
 468        uinfo->value.integer.max = 255;
 469        return 0;
 470}
 471
 472static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
 473                                 struct snd_ctl_elem_value *ucontrol)
 474{
 475        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 476        int source_id;
 477
 478        source_id = kcontrol->private_value;
 479
 480        ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
 481        ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
 482        return 0;
 483}
 484
 485static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
 486                                 struct snd_ctl_elem_value *ucontrol)
 487{
 488        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 489        unsigned int ogain;
 490        unsigned int ngain;
 491        int source_id;
 492        int change = 0;
 493
 494        source_id = kcontrol->private_value;
 495        ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
 496        ngain = ucontrol->value.integer.value[0];
 497        if (ngain > 0xff)
 498                return -EINVAL;
 499        if (ogain != ngain) {
 500                if (emu->i2c_capture_source == source_id)
 501                        snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
 502                emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
 503                change = 1;
 504        }
 505        ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
 506        ngain = ucontrol->value.integer.value[1];
 507        if (ngain > 0xff)
 508                return -EINVAL;
 509        if (ogain != ngain) {
 510                if (emu->i2c_capture_source == source_id)
 511                        snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
 512                emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
 513                change = 1;
 514        }
 515
 516        return change;
 517}
 518
 519#define spi_mute_info   snd_ctl_boolean_mono_info
 520
 521static int spi_mute_get(struct snd_kcontrol *kcontrol,
 522                        struct snd_ctl_elem_value *ucontrol)
 523{
 524        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 525        unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
 526        unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
 527
 528        ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
 529        return 0;
 530}
 531
 532static int spi_mute_put(struct snd_kcontrol *kcontrol,
 533                        struct snd_ctl_elem_value *ucontrol)
 534{
 535        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 536        unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
 537        unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
 538        int ret;
 539
 540        ret = emu->spi_dac_reg[reg] & bit;
 541        if (ucontrol->value.integer.value[0]) {
 542                if (!ret)       /* bit already cleared, do nothing */
 543                        return 0;
 544                emu->spi_dac_reg[reg] &= ~bit;
 545        } else {
 546                if (ret)        /* bit already set, do nothing */
 547                        return 0;
 548                emu->spi_dac_reg[reg] |= bit;
 549        }
 550
 551        ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
 552        return ret ? -EINVAL : 1;
 553}
 554
 555#define CA_VOLUME(xname,chid,reg) \
 556{                                                               \
 557        .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
 558        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
 559                  SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
 560        .info =  snd_ca0106_volume_info,                        \
 561        .get =   snd_ca0106_volume_get,                         \
 562        .put =   snd_ca0106_volume_put,                         \
 563        .tlv = { .p = snd_ca0106_db_scale1 },                   \
 564        .private_value = ((chid) << 8) | (reg)                  \
 565}
 566
 567static struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
 568        CA_VOLUME("Analog Front Playback Volume",
 569                  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
 570        CA_VOLUME("Analog Rear Playback Volume",
 571                  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
 572        CA_VOLUME("Analog Center/LFE Playback Volume",
 573                  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
 574        CA_VOLUME("Analog Side Playback Volume",
 575                  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
 576
 577        CA_VOLUME("IEC958 Front Playback Volume",
 578                  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
 579        CA_VOLUME("IEC958 Rear Playback Volume",
 580                  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
 581        CA_VOLUME("IEC958 Center/LFE Playback Volume",
 582                  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
 583        CA_VOLUME("IEC958 Unknown Playback Volume",
 584                  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
 585
 586        CA_VOLUME("CAPTURE feedback Playback Volume",
 587                  1, CAPTURE_CONTROL),
 588
 589        {
 590                .access =       SNDRV_CTL_ELEM_ACCESS_READ,
 591                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
 592                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
 593                .count =        4,
 594                .info =         snd_ca0106_spdif_info,
 595                .get =          snd_ca0106_spdif_get_mask
 596        },
 597        {
 598                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 599                .name =         "IEC958 Playback Switch",
 600                .info =         snd_ca0106_shared_spdif_info,
 601                .get =          snd_ca0106_shared_spdif_get,
 602                .put =          snd_ca0106_shared_spdif_put
 603        },
 604        {
 605                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 606                .name =         "Digital Source Capture Enum",
 607                .info =         snd_ca0106_capture_source_info,
 608                .get =          snd_ca0106_capture_source_get,
 609                .put =          snd_ca0106_capture_source_put
 610        },
 611        {
 612                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 613                .name =         "Analog Source Capture Enum",
 614                .info =         snd_ca0106_i2c_capture_source_info,
 615                .get =          snd_ca0106_i2c_capture_source_get,
 616                .put =          snd_ca0106_i2c_capture_source_put
 617        },
 618        {
 619                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
 620                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
 621                .count =        4,
 622                .info =         snd_ca0106_spdif_info,
 623                .get =          snd_ca0106_spdif_get_default,
 624                .put =          snd_ca0106_spdif_put_default
 625        },
 626        {
 627                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
 628                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
 629                .count =        4,
 630                .info =         snd_ca0106_spdif_info,
 631                .get =          snd_ca0106_spdif_get_stream,
 632                .put =          snd_ca0106_spdif_put_stream
 633        },
 634};
 635
 636#define I2C_VOLUME(xname,chid) \
 637{                                                               \
 638        .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
 639        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
 640                  SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
 641        .info =  snd_ca0106_i2c_volume_info,                    \
 642        .get =   snd_ca0106_i2c_volume_get,                     \
 643        .put =   snd_ca0106_i2c_volume_put,                     \
 644        .tlv = { .p = snd_ca0106_db_scale2 },                   \
 645        .private_value = chid                                   \
 646}
 647
 648static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
 649        I2C_VOLUME("Phone Capture Volume", 0),
 650        I2C_VOLUME("Mic Capture Volume", 1),
 651        I2C_VOLUME("Line in Capture Volume", 2),
 652        I2C_VOLUME("Aux Capture Volume", 3),
 653};
 654
 655static const int spi_dmute_reg[] = {
 656        SPI_DMUTE0_REG,
 657        SPI_DMUTE1_REG,
 658        SPI_DMUTE2_REG,
 659        0,
 660        SPI_DMUTE4_REG,
 661};
 662static const int spi_dmute_bit[] = {
 663        SPI_DMUTE0_BIT,
 664        SPI_DMUTE1_BIT,
 665        SPI_DMUTE2_BIT,
 666        0,
 667        SPI_DMUTE4_BIT,
 668};
 669
 670static struct snd_kcontrol_new
 671snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
 672                              int channel_id)
 673{
 674        struct snd_kcontrol_new spi_switch = {0};
 675        int reg, bit;
 676        int dac_id;
 677
 678        spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 679        spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
 680        spi_switch.info = spi_mute_info;
 681        spi_switch.get = spi_mute_get;
 682        spi_switch.put = spi_mute_put;
 683
 684        switch (channel_id) {
 685        case PCM_FRONT_CHANNEL:
 686                spi_switch.name = "Analog Front Playback Switch";
 687                dac_id = (details->spi_dac & 0xf000) >> (4 * 3);
 688                break;
 689        case PCM_REAR_CHANNEL:
 690                spi_switch.name = "Analog Rear Playback Switch";
 691                dac_id = (details->spi_dac & 0x0f00) >> (4 * 2);
 692                break;
 693        case PCM_CENTER_LFE_CHANNEL:
 694                spi_switch.name = "Analog Center/LFE Playback Switch";
 695                dac_id = (details->spi_dac & 0x00f0) >> (4 * 1);
 696                break;
 697        case PCM_UNKNOWN_CHANNEL:
 698                spi_switch.name = "Analog Side Playback Switch";
 699                dac_id = (details->spi_dac & 0x000f) >> (4 * 0);
 700                break;
 701        default:
 702                /* Unused channel */
 703                spi_switch.name = NULL;
 704                dac_id = 0;
 705        }
 706        reg = spi_dmute_reg[dac_id];
 707        bit = spi_dmute_bit[dac_id];
 708
 709        spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit;
 710
 711        return spi_switch;
 712}
 713
 714static int remove_ctl(struct snd_card *card, const char *name)
 715{
 716        struct snd_ctl_elem_id id;
 717        memset(&id, 0, sizeof(id));
 718        strcpy(id.name, name);
 719        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 720        return snd_ctl_remove_id(card, &id);
 721}
 722
 723static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
 724{
 725        struct snd_ctl_elem_id sid;
 726        memset(&sid, 0, sizeof(sid));
 727        /* FIXME: strcpy is bad. */
 728        strcpy(sid.name, name);
 729        sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 730        return snd_ctl_find_id(card, &sid);
 731}
 732
 733static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
 734{
 735        struct snd_kcontrol *kctl = ctl_find(card, src);
 736        if (kctl) {
 737                strcpy(kctl->id.name, dst);
 738                return 0;
 739        }
 740        return -ENOENT;
 741}
 742
 743#define ADD_CTLS(emu, ctls)                                             \
 744        do {                                                            \
 745                int i, _err;                                            \
 746                for (i = 0; i < ARRAY_SIZE(ctls); i++) {                \
 747                        _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
 748                        if (_err < 0)                                   \
 749                                return _err;                            \
 750                }                                                       \
 751        } while (0)
 752
 753static
 754DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
 755
 756static char *slave_vols[] = {
 757        "Analog Front Playback Volume",
 758        "Analog Rear Playback Volume",
 759        "Analog Center/LFE Playback Volume",
 760        "Analog Side Playback Volume",
 761        "IEC958 Front Playback Volume",
 762        "IEC958 Rear Playback Volume",
 763        "IEC958 Center/LFE Playback Volume",
 764        "IEC958 Unknown Playback Volume",
 765        "CAPTURE feedback Playback Volume",
 766        NULL
 767};
 768
 769static char *slave_sws[] = {
 770        "Analog Front Playback Switch",
 771        "Analog Rear Playback Switch",
 772        "Analog Center/LFE Playback Switch",
 773        "Analog Side Playback Switch",
 774        "IEC958 Playback Switch",
 775        NULL
 776};
 777
 778static void add_slaves(struct snd_card *card,
 779                                 struct snd_kcontrol *master, char **list)
 780{
 781        for (; *list; list++) {
 782                struct snd_kcontrol *slave = ctl_find(card, *list);
 783                if (slave)
 784                        snd_ctl_add_slave(master, slave);
 785        }
 786}
 787
 788int snd_ca0106_mixer(struct snd_ca0106 *emu)
 789{
 790        int err;
 791        struct snd_card *card = emu->card;
 792        char **c;
 793        struct snd_kcontrol *vmaster;
 794        static char *ca0106_remove_ctls[] = {
 795                "Master Mono Playback Switch",
 796                "Master Mono Playback Volume",
 797                "3D Control - Switch",
 798                "3D Control Sigmatel - Depth",
 799                "PCM Playback Switch",
 800                "PCM Playback Volume",
 801                "CD Playback Switch",
 802                "CD Playback Volume",
 803                "Phone Playback Switch",
 804                "Phone Playback Volume",
 805                "Video Playback Switch",
 806                "Video Playback Volume",
 807                "Beep Playback Switch",
 808                "Beep Playback Volume",
 809                "Mono Output Select",
 810                "Capture Source",
 811                "Capture Switch",
 812                "Capture Volume",
 813                "External Amplifier",
 814                "Sigmatel 4-Speaker Stereo Playback Switch",
 815                "Surround Phase Inversion Playback Switch",
 816                NULL
 817        };
 818        static char *ca0106_rename_ctls[] = {
 819                "Master Playback Switch", "Capture Switch",
 820                "Master Playback Volume", "Capture Volume",
 821                "Line Playback Switch", "AC97 Line Capture Switch",
 822                "Line Playback Volume", "AC97 Line Capture Volume",
 823                "Aux Playback Switch", "AC97 Aux Capture Switch",
 824                "Aux Playback Volume", "AC97 Aux Capture Volume",
 825                "Mic Playback Switch", "AC97 Mic Capture Switch",
 826                "Mic Playback Volume", "AC97 Mic Capture Volume",
 827                "Mic Select", "AC97 Mic Select",
 828                "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
 829                NULL
 830        };
 831#if 1
 832        for (c = ca0106_remove_ctls; *c; c++)
 833                remove_ctl(card, *c);
 834        for (c = ca0106_rename_ctls; *c; c += 2)
 835                rename_ctl(card, c[0], c[1]);
 836#endif
 837
 838        ADD_CTLS(emu, snd_ca0106_volume_ctls);
 839        if (emu->details->i2c_adc == 1) {
 840                ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
 841                if (emu->details->gpio_type == 1)
 842                        err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
 843                else  /* gpio_type == 2 */
 844                        err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
 845                if (err < 0)
 846                        return err;
 847        }
 848        if (emu->details->spi_dac) {
 849                int i;
 850                for (i = 0;; i++) {
 851                        struct snd_kcontrol_new ctl;
 852                        ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i);
 853                        if (!ctl.name)
 854                                break;
 855                        err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu));
 856                        if (err < 0)
 857                                return err;
 858                }
 859        }
 860
 861        /* Create virtual master controls */
 862        vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
 863                                              snd_ca0106_master_db_scale);
 864        if (!vmaster)
 865                return -ENOMEM;
 866        err = snd_ctl_add(card, vmaster);
 867        if (err < 0)
 868                return err;
 869        add_slaves(card, vmaster, slave_vols);
 870
 871        if (emu->details->spi_dac) {
 872                vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
 873                                                      NULL);
 874                if (!vmaster)
 875                        return -ENOMEM;
 876                err = snd_ctl_add(card, vmaster);
 877                if (err < 0)
 878                        return err;
 879                add_slaves(card, vmaster, slave_sws);
 880        }
 881
 882        strcpy(card->mixername, "CA0106");
 883        return 0;
 884}
 885
 886#ifdef CONFIG_PM_SLEEP
 887struct ca0106_vol_tbl {
 888        unsigned int channel_id;
 889        unsigned int reg;
 890};
 891
 892static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
 893        { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
 894        { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
 895        { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
 896        { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
 897        { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
 898        { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
 899        { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
 900        { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
 901        { 1, CAPTURE_CONTROL },
 902};
 903
 904void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
 905{
 906        int i;
 907
 908        /* save volumes */
 909        for (i = 0; i < NUM_SAVED_VOLUMES; i++)
 910                chip->saved_vol[i] =
 911                        snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
 912                                            saved_volumes[i].channel_id);
 913}
 914
 915void snd_ca0106_mixer_resume(struct snd_ca0106  *chip)
 916{
 917        int i;
 918
 919        for (i = 0; i < NUM_SAVED_VOLUMES; i++)
 920                snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
 921                                     saved_volumes[i].channel_id,
 922                                     chip->saved_vol[i]);
 923
 924        ca0106_spdif_enable(chip);
 925        ca0106_set_capture_source(chip);
 926        ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
 927        for (i = 0; i < 4; i++)
 928                ca0106_set_spdif_bits(chip, i);
 929        if (chip->details->i2c_adc)
 930                ca0106_set_capture_mic_line_in(chip);
 931}
 932#endif /* CONFIG_PM_SLEEP */
 933