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