1 /* 2 * Driver for Digigram VX soundcards 3 * 4 * IEC958 stuff 5 * 6 * Copyright (c) 2002 by 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 #include <linux/delay.h> 24 #include <sound/core.h> 25 #include <sound/vx_core.h> 26 #include "vx_cmd.h" 27 28 29 /* 30 * vx_modify_board_clock - tell the board that its clock has been modified 31 * @sync: DSP needs to resynchronize its FIFO 32 */ 33 static int vx_modify_board_clock(struct vx_core *chip, int sync) 34 { 35 struct vx_rmh rmh; 36 37 vx_init_rmh(&rmh, CMD_MODIFY_CLOCK); 38 /* Ask the DSP to resynchronize its FIFO. */ 39 if (sync) 40 rmh.Cmd[0] |= CMD_MODIFY_CLOCK_S_BIT; 41 return vx_send_msg(chip, &rmh); 42 } 43 44 /* 45 * vx_modify_board_inputs - resync audio inputs 46 */ 47 static int vx_modify_board_inputs(struct vx_core *chip) 48 { 49 struct vx_rmh rmh; 50 51 vx_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS); 52 rmh.Cmd[0] |= 1 << 0; /* reference: AUDIO 0 */ 53 return vx_send_msg(chip, &rmh); 54 } 55 56 /* 57 * vx_read_one_cbit - read one bit from UER config 58 * @index: the bit index 59 * returns 0 or 1. 60 */ 61 static int vx_read_one_cbit(struct vx_core *chip, int index) 62 { 63 unsigned long flags; 64 int val; 65 spin_lock_irqsave(&chip->lock, flags); 66 if (chip->type >= VX_TYPE_VXPOCKET) { 67 vx_outb(chip, CSUER, 1); /* read */ 68 vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); 69 val = (vx_inb(chip, RUER) >> 7) & 0x01; 70 } else { 71 vx_outl(chip, CSUER, 1); /* read */ 72 vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK); 73 val = (vx_inl(chip, RUER) >> 7) & 0x01; 74 } 75 spin_unlock_irqrestore(&chip->lock, flags); 76 return val; 77 } 78 79 /* 80 * vx_write_one_cbit - write one bit to UER config 81 * @index: the bit index 82 * @val: bit value, 0 or 1 83 */ 84 static void vx_write_one_cbit(struct vx_core *chip, int index, int val) 85 { 86 unsigned long flags; 87 val = !!val; /* 0 or 1 */ 88 spin_lock_irqsave(&chip->lock, flags); 89 if (vx_is_pcmcia(chip)) { 90 vx_outb(chip, CSUER, 0); /* write */ 91 vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); 92 } else { 93 vx_outl(chip, CSUER, 0); /* write */ 94 vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK)); 95 } 96 spin_unlock_irqrestore(&chip->lock, flags); 97 } 98 99 /* 100 * vx_read_uer_status - read the current UER status 101 * @mode: pointer to store the UER mode, VX_UER_MODE_XXX 102 * 103 * returns the frequency of UER, or 0 if not sync, 104 * or a negative error code. 105 */ 106 static int vx_read_uer_status(struct vx_core *chip, int *mode) 107 { 108 int val, freq; 109 110 /* Default values */ 111 freq = 0; 112 113 /* Read UER status */ 114 if (vx_is_pcmcia(chip)) 115 val = vx_inb(chip, CSUER); 116 else 117 val = vx_inl(chip, CSUER); 118 if (val < 0) 119 return val; 120 /* If clock is present, read frequency */ 121 if (val & VX_SUER_CLOCK_PRESENT_MASK) { 122 switch (val & VX_SUER_FREQ_MASK) { 123 case VX_SUER_FREQ_32KHz_MASK: 124 freq = 32000; 125 break; 126 case VX_SUER_FREQ_44KHz_MASK: 127 freq = 44100; 128 break; 129 case VX_SUER_FREQ_48KHz_MASK: 130 freq = 48000; 131 break; 132 } 133 } 134 if (val & VX_SUER_DATA_PRESENT_MASK) 135 /* bit 0 corresponds to consumer/professional bit */ 136 *mode = vx_read_one_cbit(chip, 0) ? 137 VX_UER_MODE_PROFESSIONAL : VX_UER_MODE_CONSUMER; 138 else 139 *mode = VX_UER_MODE_NOT_PRESENT; 140 141 return freq; 142 } 143 144 145 /* 146 * compute the sample clock value from frequency 147 * 148 * The formula is as follows: 149 * 150 * HexFreq = (dword) ((double) ((double) 28224000 / (double) Frequency)) 151 * switch ( HexFreq & 0x00000F00 ) 152 * case 0x00000100: ; 153 * case 0x00000200: 154 * case 0x00000300: HexFreq -= 0x00000201 ; 155 * case 0x00000400: 156 * case 0x00000500: 157 * case 0x00000600: 158 * case 0x00000700: HexFreq = (dword) (((double) 28224000 / (double) (Frequency*2)) - 1) 159 * default : HexFreq = (dword) ((double) 28224000 / (double) (Frequency*4)) - 0x000001FF 160 */ 161 162 static int vx_calc_clock_from_freq(struct vx_core *chip, int freq) 163 { 164 int hexfreq; 165 166 if (snd_BUG_ON(freq <= 0)) 167 return 0; 168 169 hexfreq = (28224000 * 10) / freq; 170 hexfreq = (hexfreq + 5) / 10; 171 172 /* max freq = 55125 Hz */ 173 if (snd_BUG_ON(hexfreq <= 0x00000200)) 174 return 0; 175 176 if (hexfreq <= 0x03ff) 177 return hexfreq - 0x00000201; 178 if (hexfreq <= 0x07ff) 179 return (hexfreq / 2) - 1; 180 if (hexfreq <= 0x0fff) 181 return (hexfreq / 4) + 0x000001ff; 182 183 return 0x5fe; /* min freq = 6893 Hz */ 184 } 185 186 187 /* 188 * vx_change_clock_source - change the clock source 189 * @source: the new source 190 */ 191 static void vx_change_clock_source(struct vx_core *chip, int source) 192 { 193 unsigned long flags; 194 195 /* we mute DAC to prevent clicks */ 196 vx_toggle_dac_mute(chip, 1); 197 spin_lock_irqsave(&chip->lock, flags); 198 chip->ops->set_clock_source(chip, source); 199 chip->clock_source = source; 200 spin_unlock_irqrestore(&chip->lock, flags); 201 /* unmute */ 202 vx_toggle_dac_mute(chip, 0); 203 } 204 205 206 /* 207 * set the internal clock 208 */ 209 void vx_set_internal_clock(struct vx_core *chip, unsigned int freq) 210 { 211 int clock; 212 unsigned long flags; 213 /* Get real clock value */ 214 clock = vx_calc_clock_from_freq(chip, freq); 215 snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq); 216 spin_lock_irqsave(&chip->lock, flags); 217 if (vx_is_pcmcia(chip)) { 218 vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f); 219 vx_outb(chip, LOFREQ, clock & 0xff); 220 } else { 221 vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f); 222 vx_outl(chip, LOFREQ, clock & 0xff); 223 } 224 spin_unlock_irqrestore(&chip->lock, flags); 225 } 226 227 228 /* 229 * set the iec958 status bits 230 * @bits: 32-bit status bits 231 */ 232 void vx_set_iec958_status(struct vx_core *chip, unsigned int bits) 233 { 234 int i; 235 236 if (chip->chip_status & VX_STAT_IS_STALE) 237 return; 238 239 for (i = 0; i < 32; i++) 240 vx_write_one_cbit(chip, i, bits & (1 << i)); 241 } 242 243 244 /* 245 * vx_set_clock - change the clock and audio source if necessary 246 */ 247 int vx_set_clock(struct vx_core *chip, unsigned int freq) 248 { 249 int src_changed = 0; 250 251 if (chip->chip_status & VX_STAT_IS_STALE) 252 return 0; 253 254 /* change the audio source if possible */ 255 vx_sync_audio_source(chip); 256 257 if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL || 258 (chip->clock_mode == VX_CLOCK_MODE_AUTO && 259 chip->audio_source == VX_AUDIO_SRC_DIGITAL)) { 260 if (chip->clock_source != UER_SYNC) { 261 vx_change_clock_source(chip, UER_SYNC); 262 mdelay(6); 263 src_changed = 1; 264 } 265 } else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL || 266 (chip->clock_mode == VX_CLOCK_MODE_AUTO && 267 chip->audio_source != VX_AUDIO_SRC_DIGITAL)) { 268 if (chip->clock_source != INTERNAL_QUARTZ) { 269 vx_change_clock_source(chip, INTERNAL_QUARTZ); 270 src_changed = 1; 271 } 272 if (chip->freq == freq) 273 return 0; 274 vx_set_internal_clock(chip, freq); 275 if (src_changed) 276 vx_modify_board_inputs(chip); 277 } 278 if (chip->freq == freq) 279 return 0; 280 chip->freq = freq; 281 vx_modify_board_clock(chip, 1); 282 return 0; 283 } 284 285 286 /* 287 * vx_change_frequency - called from interrupt handler 288 */ 289 int vx_change_frequency(struct vx_core *chip) 290 { 291 int freq; 292 293 if (chip->chip_status & VX_STAT_IS_STALE) 294 return 0; 295 296 if (chip->clock_source == INTERNAL_QUARTZ) 297 return 0; 298 /* 299 * Read the real UER board frequency 300 */ 301 freq = vx_read_uer_status(chip, &chip->uer_detected); 302 if (freq < 0) 303 return freq; 304 /* 305 * The frequency computed by the DSP is good and 306 * is different from the previous computed. 307 */ 308 if (freq == 48000 || freq == 44100 || freq == 32000) 309 chip->freq_detected = freq; 310 311 return 0; 312 } 313