cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

revo.c (15262B)


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