linux/sound/pci/ice1712/revo.c
<<
>>
Prefs
   1/*
   2 *   ALSA driver for ICEnsemble ICE1712 (Envy24)
   3 *
   4 *   Lowlevel functions for M-Audio Audiophile 192, Revolution 7.1 and 5.1
   5 *
   6 *      Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
   7 *
   8 *   This program is free software; you can redistribute it and/or modify
   9 *   it under the terms of the GNU General Public License as published by
  10 *   the Free Software Foundation; either version 2 of the License, or
  11 *   (at your option) any later version.
  12 *
  13 *   This program is distributed in the hope that it will be useful,
  14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *   GNU General Public License for more details.
  17 *
  18 *   You should have received a copy of the GNU General Public License
  19 *   along with this program; if not, write to the Free Software
  20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  21 *
  22 */      
  23
  24#include <asm/io.h>
  25#include <linux/delay.h>
  26#include <linux/interrupt.h>
  27#include <linux/init.h>
  28#include <linux/slab.h>
  29#include <sound/core.h>
  30
  31#include "ice1712.h"
  32#include "envy24ht.h"
  33#include "revo.h"
  34
  35/* a non-standard I2C device for revo51 */
  36struct revo51_spec {
  37        struct snd_i2c_device *dev;
  38        struct snd_pt2258 *pt2258;
  39};
  40
  41static void revo_i2s_mclk_changed(struct snd_ice1712 *ice)
  42{
  43        /* assert PRST# to converters; MT05 bit 7 */
  44        outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
  45        mdelay(5);
  46        /* deassert PRST# */
  47        outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
  48}
  49
  50/*
  51 * change the rate of Envy24HT, AK4355 and AK4381
  52 */
  53static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
  54{
  55        unsigned char old, tmp, dfs;
  56        int reg, shift;
  57
  58        if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
  59                return;
  60
  61        /* adjust DFS on codecs */
  62        if (rate > 96000)
  63                dfs = 2;
  64        else if (rate > 48000)
  65                dfs = 1;
  66        else
  67                dfs = 0;
  68
  69        if (ak->type == SND_AK4355 || ak->type == SND_AK4358) {
  70                reg = 2;
  71                shift = 4;
  72        } else {
  73                reg = 1;
  74                shift = 3;
  75        }
  76        tmp = snd_akm4xxx_get(ak, 0, reg);
  77        old = (tmp >> shift) & 0x03;
  78        if (old == dfs)
  79                return;
  80
  81        /* reset DFS */
  82        snd_akm4xxx_reset(ak, 1);
  83        tmp = snd_akm4xxx_get(ak, 0, reg);
  84        tmp &= ~(0x03 << shift);
  85        tmp |= dfs << shift;
  86        /* snd_akm4xxx_write(ak, 0, reg, tmp); */
  87        snd_akm4xxx_set(ak, 0, reg, tmp); /* value is written in reset(0) */
  88        snd_akm4xxx_reset(ak, 0);
  89}
  90
  91/*
  92 * I2C access to the PT2258 volume controller on GPIO 6/7 (Revolution 5.1)
  93 */
  94
  95static void revo_i2c_start(struct snd_i2c_bus *bus)
  96{
  97        struct snd_ice1712 *ice = bus->private_data;
  98        snd_ice1712_save_gpio_status(ice);
  99}
 100
 101static void revo_i2c_stop(struct snd_i2c_bus *bus)
 102{
 103        struct snd_ice1712 *ice = bus->private_data;
 104        snd_ice1712_restore_gpio_status(ice);
 105}
 106
 107static void revo_i2c_direction(struct snd_i2c_bus *bus, int clock, int data)
 108{
 109        struct snd_ice1712 *ice = bus->private_data;
 110        unsigned int mask, val;
 111
 112        val = 0;
 113        if (clock)
 114                val |= VT1724_REVO_I2C_CLOCK;   /* write SCL */
 115        if (data)
 116                val |= VT1724_REVO_I2C_DATA;    /* write SDA */
 117        mask = VT1724_REVO_I2C_CLOCK | VT1724_REVO_I2C_DATA;
 118        ice->gpio.direction &= ~mask;
 119        ice->gpio.direction |= val;
 120        snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
 121        snd_ice1712_gpio_set_mask(ice, ~mask);
 122}
 123
 124static void revo_i2c_setlines(struct snd_i2c_bus *bus, int clk, int data)
 125{
 126        struct snd_ice1712 *ice = bus->private_data;
 127        unsigned int val = 0;
 128
 129        if (clk)
 130                val |= VT1724_REVO_I2C_CLOCK;
 131        if (data)
 132                val |= VT1724_REVO_I2C_DATA;
 133        snd_ice1712_gpio_write_bits(ice,
 134                                    VT1724_REVO_I2C_DATA |
 135                                    VT1724_REVO_I2C_CLOCK, val);
 136        udelay(5);
 137}
 138
 139static int revo_i2c_getdata(struct snd_i2c_bus *bus, int ack)
 140{
 141        struct snd_ice1712 *ice = bus->private_data;
 142        int bit;
 143
 144        if (ack)
 145                udelay(5);
 146        bit = snd_ice1712_gpio_read_bits(ice, VT1724_REVO_I2C_DATA) ? 1 : 0;
 147        return bit;
 148}
 149
 150static struct snd_i2c_bit_ops revo51_bit_ops = {
 151        .start = revo_i2c_start,
 152        .stop = revo_i2c_stop,
 153        .direction = revo_i2c_direction,
 154        .setlines = revo_i2c_setlines,
 155        .getdata = revo_i2c_getdata,
 156};
 157
 158static int revo51_i2c_init(struct snd_ice1712 *ice,
 159                           struct snd_pt2258 *pt)
 160{
 161        struct revo51_spec *spec;
 162        int err;
 163
 164        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 165        if (!spec)
 166                return -ENOMEM;
 167        ice->spec = spec;
 168
 169        /* create the I2C bus */
 170        err = snd_i2c_bus_create(ice->card, "ICE1724 GPIO6", NULL, &ice->i2c);
 171        if (err < 0)
 172                return err;
 173
 174        ice->i2c->private_data = ice;
 175        ice->i2c->hw_ops.bit = &revo51_bit_ops;
 176
 177        /* create the I2C device */
 178        err = snd_i2c_device_create(ice->i2c, "PT2258", 0x40, &spec->dev);
 179        if (err < 0)
 180                return err;
 181
 182        pt->card = ice->card;
 183        pt->i2c_bus = ice->i2c;
 184        pt->i2c_dev = spec->dev;
 185        spec->pt2258 = pt;
 186
 187        snd_pt2258_reset(pt);
 188
 189        return 0;
 190}
 191
 192/*
 193 * initialize the chips on M-Audio Revolution cards
 194 */
 195
 196#define AK_DAC(xname,xch) { .name = xname, .num_channels = xch }
 197
 198static const struct snd_akm4xxx_dac_channel revo71_front[] = {
 199        {
 200                .name = "PCM Playback Volume",
 201                .num_channels = 2,
 202                /* front channels DAC supports muting */
 203                .switch_name = "PCM Playback Switch",
 204        },
 205};
 206
 207static const struct snd_akm4xxx_dac_channel revo71_surround[] = {
 208        AK_DAC("PCM Center Playback Volume", 1),
 209        AK_DAC("PCM LFE Playback Volume", 1),
 210        AK_DAC("PCM Side Playback Volume", 2),
 211        AK_DAC("PCM Rear Playback Volume", 2),
 212};
 213
 214static const struct snd_akm4xxx_dac_channel revo51_dac[] = {
 215        AK_DAC("PCM Playback Volume", 2),
 216        AK_DAC("PCM Center Playback Volume", 1),
 217        AK_DAC("PCM LFE Playback Volume", 1),
 218        AK_DAC("PCM Rear Playback Volume", 2),
 219        AK_DAC("PCM Headphone Volume", 2),
 220};
 221
 222static const char *revo51_adc_input_names[] = {
 223        "Mic",
 224        "Line",
 225        "CD",
 226        NULL
 227};
 228
 229static const struct snd_akm4xxx_adc_channel revo51_adc[] = {
 230        {
 231                .name = "PCM Capture Volume",
 232                .switch_name = "PCM Capture Switch",
 233                .num_channels = 2,
 234                .input_names = revo51_adc_input_names
 235        },
 236};
 237
 238static struct snd_akm4xxx akm_revo_front __devinitdata = {
 239        .type = SND_AK4381,
 240        .num_dacs = 2,
 241        .ops = {
 242                .set_rate_val = revo_set_rate_val
 243        },
 244        .dac_info = revo71_front,
 245};
 246
 247static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
 248        .caddr = 1,
 249        .cif = 0,
 250        .data_mask = VT1724_REVO_CDOUT,
 251        .clk_mask = VT1724_REVO_CCLK,
 252        .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
 253        .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS2,
 254        .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
 255        .add_flags = VT1724_REVO_CCLK, /* high at init */
 256        .mask_flags = 0,
 257};
 258
 259static struct snd_akm4xxx akm_revo_surround __devinitdata = {
 260        .type = SND_AK4355,
 261        .idx_offset = 1,
 262        .num_dacs = 6,
 263        .ops = {
 264                .set_rate_val = revo_set_rate_val
 265        },
 266        .dac_info = revo71_surround,
 267};
 268
 269static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
 270        .caddr = 3,
 271        .cif = 0,
 272        .data_mask = VT1724_REVO_CDOUT,
 273        .clk_mask = VT1724_REVO_CCLK,
 274        .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
 275        .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 276        .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
 277        .add_flags = VT1724_REVO_CCLK, /* high at init */
 278        .mask_flags = 0,
 279};
 280
 281static struct snd_akm4xxx akm_revo51 __devinitdata = {
 282        .type = SND_AK4358,
 283        .num_dacs = 8,
 284        .ops = {
 285                .set_rate_val = revo_set_rate_val
 286        },
 287        .dac_info = revo51_dac,
 288};
 289
 290static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
 291        .caddr = 2,
 292        .cif = 0,
 293        .data_mask = VT1724_REVO_CDOUT,
 294        .clk_mask = VT1724_REVO_CCLK,
 295        .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 296        .cs_addr = VT1724_REVO_CS1,
 297        .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 298        .add_flags = VT1724_REVO_CCLK, /* high at init */
 299        .mask_flags = 0,
 300};
 301
 302static struct snd_akm4xxx akm_revo51_adc __devinitdata = {
 303        .type = SND_AK5365,
 304        .num_adcs = 2,
 305        .adc_info = revo51_adc,
 306};
 307
 308static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
 309        .caddr = 2,
 310        .cif = 0,
 311        .data_mask = VT1724_REVO_CDOUT,
 312        .clk_mask = VT1724_REVO_CCLK,
 313        .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 314        .cs_addr = VT1724_REVO_CS0,
 315        .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 316        .add_flags = VT1724_REVO_CCLK, /* high at init */
 317        .mask_flags = 0,
 318};
 319
 320static struct snd_pt2258 ptc_revo51_volume;
 321
 322/* AK4358 for AP192 DAC, AK5385A for ADC */
 323static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 324{
 325        struct snd_ice1712 *ice = ak->private_data[0];
 326        int dfs;
 327
 328        revo_set_rate_val(ak, rate);
 329
 330        /* reset CKS */
 331        snd_ice1712_gpio_write_bits(ice, 1 << 8, rate > 96000 ? 1 << 8 : 0);
 332        /* reset DFS pins of AK5385A for ADC, too */
 333        if (rate > 96000)
 334                dfs = 2;
 335        else if (rate > 48000)
 336                dfs = 1;
 337        else
 338                dfs = 0;
 339        snd_ice1712_gpio_write_bits(ice, 3 << 9, dfs << 9);
 340        /* reset ADC */
 341        snd_ice1712_gpio_write_bits(ice, 1 << 11, 0);
 342        snd_ice1712_gpio_write_bits(ice, 1 << 11, 1 << 11);
 343}
 344
 345static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
 346        AK_DAC("PCM Playback Volume", 2)
 347};
 348
 349static struct snd_akm4xxx akm_ap192 __devinitdata = {
 350        .type = SND_AK4358,
 351        .num_dacs = 2,
 352        .ops = {
 353                .set_rate_val = ap192_set_rate_val
 354        },
 355        .dac_info = ap192_dac,
 356};
 357
 358static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
 359        .caddr = 2,
 360        .cif = 0,
 361        .data_mask = VT1724_REVO_CDOUT,
 362        .clk_mask = VT1724_REVO_CCLK,
 363        .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 364        .cs_addr = VT1724_REVO_CS1,
 365        .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
 366        .add_flags = VT1724_REVO_CCLK, /* high at init */
 367        .mask_flags = 0,
 368};
 369
 370/* AK4114 support on Audiophile 192 */
 371/* CDTO (pin 32) -- GPIO2 pin 52
 372 * CDTI (pin 33) -- GPIO3 pin 53 (shared with AK4358)
 373 * CCLK (pin 34) -- GPIO1 pin 51 (shared with AK4358)
 374 * CSN  (pin 35) -- GPIO7 pin 59
 375 */
 376#define AK4114_ADDR     0x02
 377
 378static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
 379                       unsigned int data, int idx)
 380{
 381        for (; idx >= 0; idx--) {
 382                /* drop clock */
 383                gpio &= ~VT1724_REVO_CCLK;
 384                snd_ice1712_gpio_write(ice, gpio);
 385                udelay(1);
 386                /* set data */
 387                if (data & (1 << idx))
 388                        gpio |= VT1724_REVO_CDOUT;
 389                else
 390                        gpio &= ~VT1724_REVO_CDOUT;
 391                snd_ice1712_gpio_write(ice, gpio);
 392                udelay(1);
 393                /* raise clock */
 394                gpio |= VT1724_REVO_CCLK;
 395                snd_ice1712_gpio_write(ice, gpio);
 396                udelay(1);
 397        }
 398}
 399
 400static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio,
 401                               int idx)
 402{
 403        unsigned char data = 0;
 404
 405        for (; idx >= 0; idx--) {
 406                /* drop clock */
 407                gpio &= ~VT1724_REVO_CCLK;
 408                snd_ice1712_gpio_write(ice, gpio);
 409                udelay(1);
 410                /* read data */
 411                if (snd_ice1712_gpio_read(ice) & VT1724_REVO_CDIN)
 412                        data |= (1 << idx);
 413                udelay(1);
 414                /* raise clock */
 415                gpio |= VT1724_REVO_CCLK;
 416                snd_ice1712_gpio_write(ice, gpio);
 417                udelay(1);
 418        }
 419        return data;
 420}
 421
 422static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
 423{
 424        unsigned int tmp;
 425
 426        snd_ice1712_save_gpio_status(ice);
 427        tmp = snd_ice1712_gpio_read(ice);
 428        tmp |= VT1724_REVO_CCLK; /* high at init */
 429        tmp |= VT1724_REVO_CS0;
 430        tmp &= ~VT1724_REVO_CS1;
 431        snd_ice1712_gpio_write(ice, tmp);
 432        udelay(1);
 433        return tmp;
 434}
 435
 436static void ap192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
 437{
 438        tmp |= VT1724_REVO_CS1;
 439        tmp |= VT1724_REVO_CS0;
 440        snd_ice1712_gpio_write(ice, tmp);
 441        udelay(1);
 442        snd_ice1712_restore_gpio_status(ice);
 443}
 444
 445static void ap192_ak4114_write(void *private_data, unsigned char addr,
 446                               unsigned char data)
 447{
 448        struct snd_ice1712 *ice = private_data;
 449        unsigned int tmp, addrdata;
 450
 451        tmp = ap192_4wire_start(ice);
 452        addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f);
 453        addrdata = (addrdata << 8) | data;
 454        write_data(ice, tmp, addrdata, 15);
 455        ap192_4wire_finish(ice, tmp);
 456}
 457
 458static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr)
 459{
 460        struct snd_ice1712 *ice = private_data;
 461        unsigned int tmp;
 462        unsigned char data;
 463
 464        tmp = ap192_4wire_start(ice);
 465        write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7);
 466        data = read_data(ice, tmp, 7);
 467        ap192_4wire_finish(ice, tmp);
 468        return data;
 469}
 470
 471static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
 472{
 473        static const unsigned char ak4114_init_vals[] = {
 474                AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
 475                AK4114_DIF_I24I2S,
 476                AK4114_TX1E,
 477                AK4114_EFH_1024 | AK4114_DIT | AK4114_IPS(1),
 478                0,
 479                0
 480        };
 481        static const unsigned char ak4114_init_txcsb[] = {
 482                0x41, 0x02, 0x2c, 0x00, 0x00
 483        };
 484        struct ak4114 *ak;
 485        int err;
 486
 487        err = snd_ak4114_create(ice->card,
 488                                 ap192_ak4114_read,
 489                                 ap192_ak4114_write,
 490                                 ak4114_init_vals, ak4114_init_txcsb,
 491                                 ice, &ak);
 492        /* AK4114 in Revo cannot detect external rate correctly.
 493         * No reason to stop capture stream due to incorrect checks */
 494        ak->check_flags = AK4114_CHECK_NO_RATE;
 495
 496        return 0; /* error ignored; it's no fatal error */
 497}
 498
 499static int __devinit revo_init(struct snd_ice1712 *ice)
 500{
 501        struct snd_akm4xxx *ak;
 502        int err;
 503
 504        /* determine I2C, DACs and ADCs */
 505        switch (ice->eeprom.subvendor) {
 506        case VT1724_SUBDEVICE_REVOLUTION71:
 507                ice->num_total_dacs = 8;
 508                ice->num_total_adcs = 2;
 509                ice->gpio.i2s_mclk_changed = revo_i2s_mclk_changed;
 510                break;
 511        case VT1724_SUBDEVICE_REVOLUTION51:
 512                ice->num_total_dacs = 8;
 513                ice->num_total_adcs = 2;
 514                break;
 515        case VT1724_SUBDEVICE_AUDIOPHILE192:
 516                ice->num_total_dacs = 2;
 517                ice->num_total_adcs = 2;
 518                break;
 519        default:
 520                snd_BUG();
 521                return -EINVAL;
 522        }
 523
 524        /* second stage of initialization, analog parts and others */
 525        ak = ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL);
 526        if (! ak)
 527                return -ENOMEM;
 528        switch (ice->eeprom.subvendor) {
 529        case VT1724_SUBDEVICE_REVOLUTION71:
 530                ice->akm_codecs = 2;
 531                err = snd_ice1712_akm4xxx_init(ak, &akm_revo_front,
 532                                                &akm_revo_front_priv, ice);
 533                if (err < 0)
 534                        return err;
 535                err = snd_ice1712_akm4xxx_init(ak+1, &akm_revo_surround,
 536                                                &akm_revo_surround_priv, ice);
 537                if (err < 0)
 538                        return err;
 539                /* unmute all codecs */
 540                snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
 541                                                VT1724_REVO_MUTE);
 542                break;
 543        case VT1724_SUBDEVICE_REVOLUTION51:
 544                ice->akm_codecs = 2;
 545                err = snd_ice1712_akm4xxx_init(ak, &akm_revo51,
 546                                               &akm_revo51_priv, ice);
 547                if (err < 0)
 548                        return err;
 549                err = snd_ice1712_akm4xxx_init(ak+1, &akm_revo51_adc,
 550                                               &akm_revo51_adc_priv, ice);
 551                if (err < 0)
 552                        return err;
 553                err = revo51_i2c_init(ice, &ptc_revo51_volume);
 554                if (err < 0)
 555                        return err;
 556                /* unmute all codecs */
 557                snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
 558                                            VT1724_REVO_MUTE);
 559                break;
 560        case VT1724_SUBDEVICE_AUDIOPHILE192:
 561                ice->akm_codecs = 1;
 562                err = snd_ice1712_akm4xxx_init(ak, &akm_ap192, &akm_ap192_priv,
 563                                               ice);
 564                if (err < 0)
 565                        return err;
 566                
 567                /* unmute all codecs */
 568                snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
 569                                            VT1724_REVO_MUTE);
 570                break;
 571        }
 572
 573        return 0;
 574}
 575
 576
 577static int __devinit revo_add_controls(struct snd_ice1712 *ice)
 578{
 579        struct revo51_spec *spec;
 580        int err;
 581
 582        switch (ice->eeprom.subvendor) {
 583        case VT1724_SUBDEVICE_REVOLUTION71:
 584                err = snd_ice1712_akm4xxx_build_controls(ice);
 585                if (err < 0)
 586                        return err;
 587                break;
 588        case VT1724_SUBDEVICE_REVOLUTION51:
 589                err = snd_ice1712_akm4xxx_build_controls(ice);
 590                if (err < 0)
 591                        return err;
 592                spec = ice->spec;
 593                err = snd_pt2258_build_controls(spec->pt2258);
 594                if (err < 0)
 595                        return err;
 596                break;
 597        case VT1724_SUBDEVICE_AUDIOPHILE192:
 598                err = snd_ice1712_akm4xxx_build_controls(ice);
 599                if (err < 0)
 600                        return err;
 601                err = ap192_ak4114_init(ice);
 602                if (err < 0)
 603                        return err;
 604                break;
 605        }
 606        return 0;
 607}
 608
 609/* entry point */
 610struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
 611        {
 612                .subvendor = VT1724_SUBDEVICE_REVOLUTION71,
 613                .name = "M Audio Revolution-7.1",
 614                .model = "revo71",
 615                .chip_init = revo_init,
 616                .build_controls = revo_add_controls,
 617        },
 618        {
 619                .subvendor = VT1724_SUBDEVICE_REVOLUTION51,
 620                .name = "M Audio Revolution-5.1",
 621                .model = "revo51",
 622                .chip_init = revo_init,
 623                .build_controls = revo_add_controls,
 624        },
 625        {
 626                .subvendor = VT1724_SUBDEVICE_AUDIOPHILE192,
 627                .name = "M Audio Audiophile192",
 628                .model = "ap192",
 629                .chip_init = revo_init,
 630                .build_controls = revo_add_controls,
 631        },
 632        { } /* terminator */
 633};
 634