1 /* 2 * ALSA driver for ICEnsemble ICE1712 (Envy24) 3 * 4 * Lowlevel functions for M-Audio Revolution 7.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 <sound/driver.h> 25 #include <asm/io.h> 26 #include <linux/delay.h> 27 #include <linux/interrupt.h> 28 #include <linux/init.h> 29 #include <linux/slab.h> 30 #include <sound/core.h> 31 32 #include "ice1712.h" 33 #include "envy24ht.h" 34 #include "revo.h" 35 36 static void revo_i2s_mclk_changed(struct snd_ice1712 *ice) 37 { 38 /* assert PRST# to converters; MT05 bit 7 */ 39 outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD)); 40 mdelay(5); 41 /* deassert PRST# */ 42 outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD)); 43 } 44 45 /* 46 * change the rate of envy24HT, AK4355 and AK4381 47 */ 48 static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) 49 { 50 unsigned char old, tmp, dfs; 51 int reg, shift; 52 53 if (rate == 0) /* no hint - S/PDIF input is master, simply return */ 54 return; 55 56 /* adjust DFS on codecs */ 57 if (rate > 96000) 58 dfs = 2; 59 else if (rate > 48000) 60 dfs = 1; 61 else 62 dfs = 0; 63 64 if (ak->type == SND_AK4355 || ak->type == SND_AK4358) { 65 reg = 2; 66 shift = 4; 67 } else { 68 reg = 1; 69 shift = 3; 70 } 71 tmp = snd_akm4xxx_get(ak, 0, reg); 72 old = (tmp >> shift) & 0x03; 73 if (old == dfs) 74 return; 75 76 /* reset DFS */ 77 snd_akm4xxx_reset(ak, 1); 78 tmp = snd_akm4xxx_get(ak, 0, reg); 79 tmp &= ~(0x03 << shift); 80 tmp |= dfs << shift; 81 // snd_akm4xxx_write(ak, 0, reg, tmp); 82 snd_akm4xxx_set(ak, 0, reg, tmp); /* the value is written in reset(0) */ 83 snd_akm4xxx_reset(ak, 0); 84 } 85 86 /* 87 * initialize the chips on M-Audio Revolution cards 88 */ 89 90 static unsigned int revo71_num_stereo_front[] = {2}; 91 static char *revo71_channel_names_front[] = {"PCM Playback Volume"}; 92 93 static unsigned int revo71_num_stereo_surround[] = {1, 1, 2, 2}; 94 static char *revo71_channel_names_surround[] = {"PCM Center Playback Volume", "PCM LFE Playback Volume", 95 "PCM Side Playback Volume", "PCM Rear Playback Volume"}; 96 97 static unsigned int revo51_num_stereo[] = {2, 1, 1, 2}; 98 static char *revo51_channel_names[] = {"PCM Playback Volume", "PCM Center Playback Volume", 99 "PCM LFE Playback Volume", "PCM Rear Playback Volume"}; 100 101 static struct snd_akm4xxx akm_revo_front __devinitdata = { 102 .type = SND_AK4381, 103 .num_dacs = 2, 104 .ops = { 105 .set_rate_val = revo_set_rate_val 106 }, 107 .num_stereo = revo71_num_stereo_front, 108 .channel_names = revo71_channel_names_front 109 }; 110 111 static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { 112 .caddr = 1, 113 .cif = 0, 114 .data_mask = VT1724_REVO_CDOUT, 115 .clk_mask = VT1724_REVO_CCLK, 116 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 117 .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS2, 118 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 119 .add_flags = VT1724_REVO_CCLK, /* high at init */ 120 .mask_flags = 0, 121 }; 122 123 static struct snd_akm4xxx akm_revo_surround __devinitdata = { 124 .type = SND_AK4355, 125 .idx_offset = 1, 126 .num_dacs = 6, 127 .ops = { 128 .set_rate_val = revo_set_rate_val 129 }, 130 .num_stereo = revo71_num_stereo_surround, 131 .channel_names = revo71_channel_names_surround 132 }; 133 134 static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { 135 .caddr = 3, 136 .cif = 0, 137 .data_mask = VT1724_REVO_CDOUT, 138 .clk_mask = VT1724_REVO_CCLK, 139 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 140 .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS1, 141 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 142 .add_flags = VT1724_REVO_CCLK, /* high at init */ 143 .mask_flags = 0, 144 }; 145 146 static struct snd_akm4xxx akm_revo51 __devinitdata = { 147 .type = SND_AK4358, 148 .num_dacs = 6, 149 .ops = { 150 .set_rate_val = revo_set_rate_val 151 }, 152 .num_stereo = revo51_num_stereo, 153 .channel_names = revo51_channel_names 154 }; 155 156 static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { 157 .caddr = 2, 158 .cif = 0, 159 .data_mask = VT1724_REVO_CDOUT, 160 .clk_mask = VT1724_REVO_CCLK, 161 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 162 .cs_addr = 0, 163 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 164 .add_flags = VT1724_REVO_CCLK, /* high at init */ 165 .mask_flags = 0, 166 }; 167 168 static int __devinit revo_init(struct snd_ice1712 *ice) 169 { 170 struct snd_akm4xxx *ak; 171 int err; 172 173 /* determine I2C, DACs and ADCs */ 174 switch (ice->eeprom.subvendor) { 175 case VT1724_SUBDEVICE_REVOLUTION71: 176 ice->num_total_dacs = 8; 177 ice->num_total_adcs = 2; 178 ice->gpio.i2s_mclk_changed = revo_i2s_mclk_changed; 179 break; 180 case VT1724_SUBDEVICE_REVOLUTION51: 181 ice->num_total_dacs = 6; 182 ice->num_total_adcs = 2; 183 break; 184 default: 185 snd_BUG(); 186 return -EINVAL; 187 } 188 189 /* second stage of initialization, analog parts and others */ 190 ak = ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL); 191 if (! ak) 192 return -ENOMEM; 193 ice->akm_codecs = 2; 194 switch (ice->eeprom.subvendor) { 195 case VT1724_SUBDEVICE_REVOLUTION71: 196 ice->akm_codecs = 2; 197 if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo_front, &akm_revo_front_priv, ice)) < 0) 198 return err; 199 if ((err = snd_ice1712_akm4xxx_init(ak + 1, &akm_revo_surround, &akm_revo_surround_priv, ice)) < 0) 200 return err; 201 /* unmute all codecs */ 202 snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); 203 break; 204 case VT1724_SUBDEVICE_REVOLUTION51: 205 ice->akm_codecs = 1; 206 if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, &akm_revo51_priv, ice)) < 0) 207 return err; 208 /* unmute all codecs - needed! */ 209 snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); 210 break; 211 } 212 213 return 0; 214 } 215 216 217 static int __devinit revo_add_controls(struct snd_ice1712 *ice) 218 { 219 int err; 220 221 switch (ice->eeprom.subvendor) { 222 case VT1724_SUBDEVICE_REVOLUTION71: 223 case VT1724_SUBDEVICE_REVOLUTION51: 224 err = snd_ice1712_akm4xxx_build_controls(ice); 225 if (err < 0) 226 return err; 227 } 228 return 0; 229 } 230 231 /* entry point */ 232 struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = { 233 { 234 .subvendor = VT1724_SUBDEVICE_REVOLUTION71, 235 .name = "M Audio Revolution-7.1", 236 .model = "revo71", 237 .chip_init = revo_init, 238 .build_controls = revo_add_controls, 239 }, 240 { 241 .subvendor = VT1724_SUBDEVICE_REVOLUTION51, 242 .name = "M Audio Revolution-5.1", 243 .model = "revo51", 244 .chip_init = revo_init, 245 .build_controls = revo_add_controls, 246 }, 247 { } /* terminator */ 248 }; 249