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 initally 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/slab.h>
  67#include <linux/moduleparam.h>
  68#include <sound/core.h>
  69#include <sound/initval.h>
  70#include <sound/pcm.h>
  71#include <sound/ac97_codec.h>
  72#include <sound/info.h>
  73#include <sound/tlv.h>
  74#include <asm/io.h>
  75
  76#include "ca0106.h"
  77
  78static void ca0106_spdif_enable(struct snd_ca0106 *emu)
  79{
  80        unsigned int val;
  81
  82        if (emu->spdif_enable) {
  83                /* Digital */
  84                snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
  85                snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
  86                val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000;
  87                snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
  88                val = inl(emu->port + GPIO) & ~0x101;
  89                outl(val, emu->port + GPIO);
  90
  91        } else {
  92                /* Analog */
  93                snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
  94                snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
  95                val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000;
  96                snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
  97                val = inl(emu->port + GPIO) | 0x101;
  98                outl(val, emu->port + GPIO);
  99        }
 100}
 101
 102static void ca0106_set_capture_source(struct snd_ca0106 *emu)
 103{
 104        unsigned int val = emu->capture_source;
 105        unsigned int source, mask;
 106        source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
 107        mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
 108        snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
 109}
 110
 111static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
 112                                          unsigned int val, int force)
 113{
 114        unsigned int ngain, ogain;
 115        u32 source;
 116
 117        snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
 118        ngain = emu->i2c_capture_volume[val][0]; /* Left */
 119        ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
 120        if (force || ngain != ogain)
 121                snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff);
 122        ngain = emu->i2c_capture_volume[val][1]; /* Right */
 123        ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
 124        if (force || ngain != ogain)
 125                snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff);
 126        source = 1 << val;
 127        snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
 128        emu->i2c_capture_source = val;
 129}
 130
 131static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
 132{
 133        u32 tmp;
 134
 135        if (emu->capture_mic_line_in) {
 136                /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
 137                tmp = inl(emu->port+GPIO) & ~0x400;
 138                tmp = tmp | 0x400;
 139                outl(tmp, emu->port+GPIO);
 140                /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
 141        } else {
 142                /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
 143                tmp = inl(emu->port+GPIO) & ~0x400;
 144                outl(tmp, emu->port+GPIO);
 145                /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */
 146        }
 147}
 148
 149static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
 150{
 151        snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]);
 152}
 153
 154/*
 155 */
 156static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
 157static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
 158
 159#define snd_ca0106_shared_spdif_info    snd_ctl_boolean_mono_info
 160
 161static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
 162                                        struct snd_ctl_elem_value *ucontrol)
 163{
 164        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 165
 166        ucontrol->value.integer.value[0] = emu->spdif_enable;
 167        return 0;
 168}
 169
 170static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
 171                                        struct snd_ctl_elem_value *ucontrol)
 172{
 173        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 174        unsigned int val;
 175        int change = 0;
 176
 177        val = !!ucontrol->value.integer.value[0];
 178        change = (emu->spdif_enable != val);
 179        if (change) {
 180                emu->spdif_enable = val;
 181                ca0106_spdif_enable(emu);
 182        }
 183        return change;
 184}
 185
 186static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
 187                                          struct snd_ctl_elem_info *uinfo)
 188{
 189        static char *texts[6] = {
 190                "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
 191        };
 192
 193        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 194        uinfo->count = 1;
 195        uinfo->value.enumerated.items = 6;
 196        if (uinfo->value.enumerated.item > 5)
 197                uinfo->value.enumerated.item = 5;
 198        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
 199        return 0;
 200}
 201
 202static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
 203                                        struct snd_ctl_elem_value *ucontrol)
 204{
 205        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 206
 207        ucontrol->value.enumerated.item[0] = emu->capture_source;
 208        return 0;
 209}
 210
 211static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
 212                                        struct snd_ctl_elem_value *ucontrol)
 213{
 214        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 215        unsigned int val;
 216        int change = 0;
 217
 218        val = ucontrol->value.enumerated.item[0] ;
 219        if (val >= 6)
 220                return -EINVAL;
 221        change = (emu->capture_source != val);
 222        if (change) {
 223                emu->capture_source = val;
 224                ca0106_set_capture_source(emu);
 225        }
 226        return change;
 227}
 228
 229static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
 230                                          struct snd_ctl_elem_info *uinfo)
 231{
 232        static char *texts[6] = {
 233                "Phone", "Mic", "Line in", "Aux"
 234        };
 235
 236        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 237        uinfo->count = 1;
 238        uinfo->value.enumerated.items = 4;
 239        if (uinfo->value.enumerated.item > 3)
 240                uinfo->value.enumerated.item = 3;
 241        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
 242        return 0;
 243}
 244
 245static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
 246                                        struct snd_ctl_elem_value *ucontrol)
 247{
 248        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 249
 250        ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
 251        return 0;
 252}
 253
 254static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
 255                                        struct snd_ctl_elem_value *ucontrol)
 256{
 257        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 258        unsigned int source_id;
 259        int change = 0;
 260        /* If the capture source has changed,
 261         * update the capture volume from the cached value
 262         * for the particular source.
 263         */
 264        source_id = ucontrol->value.enumerated.item[0] ;
 265        if (source_id >= 4)
 266                return -EINVAL;
 267        change = (emu->i2c_capture_source != source_id);
 268        if (change) {
 269                ca0106_set_i2c_capture_source(emu, source_id, 0);
 270        }
 271        return change;
 272}
 273
 274static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
 275                                               struct snd_ctl_elem_info *uinfo)
 276{
 277        static char *texts[2] = { "Side out", "Line in" };
 278
 279        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 280        uinfo->count = 1;
 281        uinfo->value.enumerated.items = 2;
 282        if (uinfo->value.enumerated.item > 1)
 283                uinfo->value.enumerated.item = 1;
 284        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
 285        return 0;
 286}
 287
 288static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
 289                                               struct snd_ctl_elem_info *uinfo)
 290{
 291        static char *texts[2] = { "Line in", "Mic in" };
 292
 293        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 294        uinfo->count = 1;
 295        uinfo->value.enumerated.items = 2;
 296        if (uinfo->value.enumerated.item > 1)
 297                uinfo->value.enumerated.item = 1;
 298        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
 299        return 0;
 300}
 301
 302static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
 303                                        struct snd_ctl_elem_value *ucontrol)
 304{
 305        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 306
 307        ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
 308        return 0;
 309}
 310
 311static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
 312                                        struct snd_ctl_elem_value *ucontrol)
 313{
 314        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 315        unsigned int val;
 316        int change = 0;
 317
 318        val = ucontrol->value.enumerated.item[0] ;
 319        if (val > 1)
 320                return -EINVAL;
 321        change = (emu->capture_mic_line_in != val);
 322        if (change) {
 323                emu->capture_mic_line_in = val;
 324                ca0106_set_capture_mic_line_in(emu);
 325        }
 326        return change;
 327}
 328
 329static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
 330{
 331        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 332        .name =         "Shared Mic/Line in Capture Switch",
 333        .info =         snd_ca0106_capture_mic_line_in_info,
 334        .get =          snd_ca0106_capture_mic_line_in_get,
 335        .put =          snd_ca0106_capture_mic_line_in_put
 336};
 337
 338static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
 339{
 340        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 341        .name =         "Shared Line in/Side out Capture Switch",
 342        .info =         snd_ca0106_capture_line_in_side_out_info,
 343        .get =          snd_ca0106_capture_mic_line_in_get,
 344        .put =          snd_ca0106_capture_mic_line_in_put
 345};
 346
 347
 348static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
 349                                 struct snd_ctl_elem_info *uinfo)
 350{
 351        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
 352        uinfo->count = 1;
 353        return 0;
 354}
 355
 356static void decode_spdif_bits(unsigned char *status, unsigned int bits)
 357{
 358        status[0] = (bits >> 0) & 0xff;
 359        status[1] = (bits >> 8) & 0xff;
 360        status[2] = (bits >> 16) & 0xff;
 361        status[3] = (bits >> 24) & 0xff;
 362}
 363
 364static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol,
 365                                 struct snd_ctl_elem_value *ucontrol)
 366{
 367        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 368        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 369
 370        decode_spdif_bits(ucontrol->value.iec958.status,
 371                          emu->spdif_bits[idx]);
 372        return 0;
 373}
 374
 375static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol,
 376                                 struct snd_ctl_elem_value *ucontrol)
 377{
 378        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 379        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 380
 381        decode_spdif_bits(ucontrol->value.iec958.status,
 382                          emu->spdif_str_bits[idx]);
 383        return 0;
 384}
 385
 386static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
 387                                      struct snd_ctl_elem_value *ucontrol)
 388{
 389        ucontrol->value.iec958.status[0] = 0xff;
 390        ucontrol->value.iec958.status[1] = 0xff;
 391        ucontrol->value.iec958.status[2] = 0xff;
 392        ucontrol->value.iec958.status[3] = 0xff;
 393        return 0;
 394}
 395
 396static unsigned int encode_spdif_bits(unsigned char *status)
 397{
 398        return ((unsigned int)status[0] << 0) |
 399                ((unsigned int)status[1] << 8) |
 400                ((unsigned int)status[2] << 16) |
 401                ((unsigned int)status[3] << 24);
 402}
 403
 404static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol,
 405                                 struct snd_ctl_elem_value *ucontrol)
 406{
 407        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 408        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 409        unsigned int val;
 410
 411        val = encode_spdif_bits(ucontrol->value.iec958.status);
 412        if (val != emu->spdif_bits[idx]) {
 413                emu->spdif_bits[idx] = val;
 414                /* FIXME: this isn't safe, but needed to keep the compatibility
 415                 * with older alsa-lib config
 416                 */
 417                emu->spdif_str_bits[idx] = val;
 418                ca0106_set_spdif_bits(emu, idx);
 419                return 1;
 420        }
 421        return 0;
 422}
 423
 424static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol,
 425                                 struct snd_ctl_elem_value *ucontrol)
 426{
 427        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 428        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 429        unsigned int val;
 430
 431        val = encode_spdif_bits(ucontrol->value.iec958.status);
 432        if (val != emu->spdif_str_bits[idx]) {
 433                emu->spdif_str_bits[idx] = val;
 434                ca0106_set_spdif_bits(emu, idx);
 435                return 1;
 436        }
 437        return 0;
 438}
 439
 440static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
 441                                  struct snd_ctl_elem_info *uinfo)
 442{
 443        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 444        uinfo->count = 2;
 445        uinfo->value.integer.min = 0;
 446        uinfo->value.integer.max = 255;
 447        return 0;
 448}
 449
 450static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
 451                                 struct snd_ctl_elem_value *ucontrol)
 452{
 453        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 454        unsigned int value;
 455        int channel_id, reg;
 456
 457        channel_id = (kcontrol->private_value >> 8) & 0xff;
 458        reg = kcontrol->private_value & 0xff;
 459
 460        value = snd_ca0106_ptr_read(emu, reg, channel_id);
 461        ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
 462        ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
 463        return 0;
 464}
 465
 466static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
 467                                 struct snd_ctl_elem_value *ucontrol)
 468{
 469        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 470        unsigned int oval, nval;
 471        int channel_id, reg;
 472
 473        channel_id = (kcontrol->private_value >> 8) & 0xff;
 474        reg = kcontrol->private_value & 0xff;
 475
 476        oval = snd_ca0106_ptr_read(emu, reg, channel_id);
 477        nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
 478                ((0xff - ucontrol->value.integer.value[1]) << 16);
 479        nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
 480                ((0xff - ucontrol->value.integer.value[1]) );
 481        if (oval == nval)
 482                return 0;
 483        snd_ca0106_ptr_write(emu, reg, channel_id, nval);
 484        return 1;
 485}
 486
 487static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
 488                                  struct snd_ctl_elem_info *uinfo)
 489{
 490        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 491        uinfo->count = 2;
 492        uinfo->value.integer.min = 0;
 493        uinfo->value.integer.max = 255;
 494        return 0;
 495}
 496
 497static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
 498                                 struct snd_ctl_elem_value *ucontrol)
 499{
 500        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 501        int source_id;
 502
 503        source_id = kcontrol->private_value;
 504
 505        ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
 506        ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
 507        return 0;
 508}
 509
 510static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
 511                                 struct snd_ctl_elem_value *ucontrol)
 512{
 513        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 514        unsigned int ogain;
 515        unsigned int ngain;
 516        int source_id;
 517        int change = 0;
 518
 519        source_id = kcontrol->private_value;
 520        ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
 521        ngain = ucontrol->value.integer.value[0];
 522        if (ngain > 0xff)
 523                return -EINVAL;
 524        if (ogain != ngain) {
 525                if (emu->i2c_capture_source == source_id)
 526                        snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
 527                emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
 528                change = 1;
 529        }
 530        ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
 531        ngain = ucontrol->value.integer.value[1];
 532        if (ngain > 0xff)
 533                return -EINVAL;
 534        if (ogain != ngain) {
 535                if (emu->i2c_capture_source == source_id)
 536                        snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
 537                emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
 538                change = 1;
 539        }
 540
 541        return change;
 542}
 543
 544#define spi_mute_info   snd_ctl_boolean_mono_info
 545
 546static int spi_mute_get(struct snd_kcontrol *kcontrol,
 547                        struct snd_ctl_elem_value *ucontrol)
 548{
 549        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 550        unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
 551        unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
 552
 553        ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
 554        return 0;
 555}
 556
 557static int spi_mute_put(struct snd_kcontrol *kcontrol,
 558                        struct snd_ctl_elem_value *ucontrol)
 559{
 560        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
 561        unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
 562        unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
 563        int ret;
 564
 565        ret = emu->spi_dac_reg[reg] & bit;
 566        if (ucontrol->value.integer.value[0]) {
 567                if (!ret)       /* bit already cleared, do nothing */
 568                        return 0;
 569                emu->spi_dac_reg[reg] &= ~bit;
 570        } else {
 571                if (ret)        /* bit already set, do nothing */
 572                        return 0;
 573                emu->spi_dac_reg[reg] |= bit;
 574        }
 575
 576        ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
 577        return ret ? -EINVAL : 1;
 578}
 579
 580#define CA_VOLUME(xname,chid,reg) \
 581{                                                               \
 582        .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
 583        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
 584                  SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
 585        .info =  snd_ca0106_volume_info,                        \
 586        .get =   snd_ca0106_volume_get,                         \
 587        .put =   snd_ca0106_volume_put,                         \
 588        .tlv = { .p = snd_ca0106_db_scale1 },                   \
 589        .private_value = ((chid) << 8) | (reg)                  \
 590}
 591
 592static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
 593        CA_VOLUME("Analog Front Playback Volume",
 594                  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
 595        CA_VOLUME("Analog Rear Playback Volume",
 596                  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
 597        CA_VOLUME("Analog Center/LFE Playback Volume",
 598                  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
 599        CA_VOLUME("Analog Side Playback Volume",
 600                  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
 601
 602        CA_VOLUME("IEC958 Front Playback Volume",
 603                  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
 604        CA_VOLUME("IEC958 Rear Playback Volume",
 605                  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
 606        CA_VOLUME("IEC958 Center/LFE Playback Volume",
 607                  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
 608        CA_VOLUME("IEC958 Unknown Playback Volume",
 609                  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
 610
 611        CA_VOLUME("CAPTURE feedback Playback Volume",
 612                  1, CAPTURE_CONTROL),
 613
 614        {
 615                .access =       SNDRV_CTL_ELEM_ACCESS_READ,
 616                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
 617                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
 618                .count =        4,
 619                .info =         snd_ca0106_spdif_info,
 620                .get =          snd_ca0106_spdif_get_mask
 621        },
 622        {
 623                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 624                .name =         "IEC958 Playback Switch",
 625                .info =         snd_ca0106_shared_spdif_info,
 626                .get =          snd_ca0106_shared_spdif_get,
 627                .put =          snd_ca0106_shared_spdif_put
 628        },
 629        {
 630                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 631                .name =         "Digital Source Capture Enum",
 632                .info =         snd_ca0106_capture_source_info,
 633                .get =          snd_ca0106_capture_source_get,
 634                .put =          snd_ca0106_capture_source_put
 635        },
 636        {
 637                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
 638                .name =         "Analog Source Capture Enum",
 639                .info =         snd_ca0106_i2c_capture_source_info,
 640                .get =          snd_ca0106_i2c_capture_source_get,
 641                .put =          snd_ca0106_i2c_capture_source_put
 642        },
 643        {
 644                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
 645                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
 646                .count =        4,
 647                .info =         snd_ca0106_spdif_info,
 648                .get =          snd_ca0106_spdif_get_default,
 649                .put =          snd_ca0106_spdif_put_default
 650        },
 651        {
 652                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
 653                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
 654                .count =        4,
 655                .info =         snd_ca0106_spdif_info,
 656                .get =          snd_ca0106_spdif_get_stream,
 657                .put =          snd_ca0106_spdif_put_stream
 658        },
 659};
 660
 661#define I2C_VOLUME(xname,chid) \
 662{                                                               \
 663        .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
 664        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
 665                  SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
 666        .info =  snd_ca0106_i2c_volume_info,                    \
 667        .get =   snd_ca0106_i2c_volume_get,                     \
 668        .put =   snd_ca0106_i2c_volume_put,                     \
 669        .tlv = { .p = snd_ca0106_db_scale2 },                   \
 670        .private_value = chid                                   \
 671}
 672
 673static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
 674        I2C_VOLUME("Phone Capture Volume", 0),
 675        I2C_VOLUME("Mic Capture Volume", 1),
 676        I2C_VOLUME("Line in Capture Volume", 2),
 677        I2C_VOLUME("Aux Capture Volume", 3),
 678};
 679
 680#define SPI_SWITCH(xname,reg,bit) \
 681{                                                               \
 682        .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,    \
 683        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,              \
 684        .info   = spi_mute_info,                                \
 685        .get    = spi_mute_get,                                 \
 686        .put    = spi_mute_put,                                 \
 687        .private_value = (reg<<SPI_REG_SHIFT) | (bit)           \
 688}
 689
 690static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
 691__devinitdata = {
 692        SPI_SWITCH("Analog Front Playback Switch",
 693                   SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
 694        SPI_SWITCH("Analog Rear Playback Switch",
 695                   SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
 696        SPI_SWITCH("Analog Center/LFE Playback Switch",
 697                   SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
 698        SPI_SWITCH("Analog Side Playback Switch",
 699                   SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
 700};
 701
 702static int __devinit remove_ctl(struct snd_card *card, const char *name)
 703{
 704        struct snd_ctl_elem_id id;
 705        memset(&id, 0, sizeof(id));
 706        strcpy(id.name, name);
 707        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 708        return snd_ctl_remove_id(card, &id);
 709}
 710
 711static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
 712{
 713        struct snd_ctl_elem_id sid;
 714        memset(&sid, 0, sizeof(sid));
 715        /* FIXME: strcpy is bad. */
 716        strcpy(sid.name, name);
 717        sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 718        return snd_ctl_find_id(card, &sid);
 719}
 720
 721static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
 722{
 723        struct snd_kcontrol *kctl = ctl_find(card, src);
 724        if (kctl) {
 725                strcpy(kctl->id.name, dst);
 726                return 0;
 727        }
 728        return -ENOENT;
 729}
 730
 731#define ADD_CTLS(emu, ctls)                                             \
 732        do {                                                            \
 733                int i, _err;                                            \
 734                for (i = 0; i < ARRAY_SIZE(ctls); i++) {                \
 735                        _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
 736                        if (_err < 0)                                   \
 737                                return _err;                            \
 738                }                                                       \
 739        } while (0)
 740
 741static __devinitdata
 742DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
 743
 744static char *slave_vols[] __devinitdata = {
 745        "Analog Front Playback Volume",
 746        "Analog Rear Playback Volume",
 747        "Analog Center/LFE Playback Volume",
 748        "Analog Side Playback Volume",
 749        "IEC958 Front Playback Volume",
 750        "IEC958 Rear Playback Volume",
 751        "IEC958 Center/LFE Playback Volume",
 752        "IEC958 Unknown Playback Volume",
 753        "CAPTURE feedback Playback Volume",
 754        NULL
 755};
 756
 757static char *slave_sws[] __devinitdata = {
 758        "Analog Front Playback Switch",
 759        "Analog Rear Playback Switch",
 760        "Analog Center/LFE Playback Switch",
 761        "Analog Side Playback Switch",
 762        "IEC958 Playback Switch",
 763        NULL
 764};
 765
 766static void __devinit add_slaves(struct snd_card *card,
 767                                 struct snd_kcontrol *master, char **list)
 768{
 769        for (; *list; list++) {
 770                struct snd_kcontrol *slave = ctl_find(card, *list);
 771                if (slave)
 772                        snd_ctl_add_slave(master, slave);
 773        }
 774}
 775
 776int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
 777{
 778        int err;
 779        struct snd_card *card = emu->card;
 780        char **c;
 781        struct snd_kcontrol *vmaster;
 782        static char *ca0106_remove_ctls[] = {
 783                "Master Mono Playback Switch",
 784                "Master Mono Playback Volume",
 785                "3D Control - Switch",
 786                "3D Control Sigmatel - Depth",
 787                "PCM Playback Switch",
 788                "PCM Playback Volume",
 789                "CD Playback Switch",
 790                "CD Playback Volume",
 791                "Phone Playback Switch",
 792                "Phone Playback Volume",
 793                "Video Playback Switch",
 794                "Video Playback Volume",
 795                "PC Speaker Playback Switch",
 796                "PC Speaker Playback Volume",
 797                "Mono Output Select",
 798                "Capture Source",
 799                "Capture Switch",
 800                "Capture Volume",
 801                "External Amplifier",
 802                "Sigmatel 4-Speaker Stereo Playback Switch",
 803                "Surround Phase Inversion Playback Switch",
 804                NULL
 805        };
 806        static char *ca0106_rename_ctls[] = {
 807                "Master Playback Switch", "Capture Switch",
 808                "Master Playback Volume", "Capture Volume",
 809                "Line Playback Switch", "AC97 Line Capture Switch",
 810                "Line Playback Volume", "AC97 Line Capture Volume",
 811                "Aux Playback Switch", "AC97 Aux Capture Switch",
 812                "Aux Playback Volume", "AC97 Aux Capture Volume",
 813                "Mic Playback Switch", "AC97 Mic Capture Switch",
 814                "Mic Playback Volume", "AC97 Mic Capture Volume",
 815                "Mic Select", "AC97 Mic Select",
 816                "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
 817                NULL
 818        };
 819#if 1
 820        for (c = ca0106_remove_ctls; *c; c++)
 821                remove_ctl(card, *c);
 822        for (c = ca0106_rename_ctls; *c; c += 2)
 823                rename_ctl(card, c[0], c[1]);
 824#endif
 825
 826        ADD_CTLS(emu, snd_ca0106_volume_ctls);
 827        if (emu->details->i2c_adc == 1) {
 828                ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
 829                if (emu->details->gpio_type == 1)
 830                        err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
 831                else  /* gpio_type == 2 */
 832                        err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
 833                if (err < 0)
 834                        return err;
 835        }
 836        if (emu->details->spi_dac == 1)
 837                ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
 838
 839        /* Create virtual master controls */
 840        vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
 841                                              snd_ca0106_master_db_scale);
 842        if (!vmaster)
 843                return -ENOMEM;
 844        err = snd_ctl_add(card, vmaster);
 845        if (err < 0)
 846                return err;
 847        add_slaves(card, vmaster, slave_vols);
 848
 849        if (emu->details->spi_dac == 1) {
 850                vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
 851                                                      NULL);
 852                if (!vmaster)
 853                        return -ENOMEM;
 854                err = snd_ctl_add(card, vmaster);
 855                if (err < 0)
 856                        return err;
 857                add_slaves(card, vmaster, slave_sws);
 858        }
 859
 860        strcpy(card->mixername, "CA0106");
 861        return 0;
 862}
 863
 864#ifdef CONFIG_PM
 865struct ca0106_vol_tbl {
 866        unsigned int channel_id;
 867        unsigned int reg;
 868};
 869
 870static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
 871        { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
 872        { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
 873        { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
 874        { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
 875        { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
 876        { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
 877        { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
 878        { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
 879        { 1, CAPTURE_CONTROL },
 880};
 881
 882void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
 883{
 884        int i;
 885
 886        /* save volumes */
 887        for (i = 0; i < NUM_SAVED_VOLUMES; i++)
 888                chip->saved_vol[i] =
 889                        snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
 890                                            saved_volumes[i].channel_id);
 891}
 892
 893void snd_ca0106_mixer_resume(struct snd_ca0106  *chip)
 894{
 895        int i;
 896
 897        for (i = 0; i < NUM_SAVED_VOLUMES; i++)
 898                snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
 899                                     saved_volumes[i].channel_id,
 900                                     chip->saved_vol[i]);
 901
 902        ca0106_spdif_enable(chip);
 903        ca0106_set_capture_source(chip);
 904        ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
 905        for (i = 0; i < 4; i++)
 906                ca0106_set_spdif_bits(chip, i);
 907        if (chip->details->i2c_adc)
 908                ca0106_set_capture_mic_line_in(chip);
 909}
 910#endif /* CONFIG_PM */
 911