1/* 2 * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> 3 * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit 4 * Version: 0.0.18 5 * 6 * FEATURES currently supported: 7 * See ca0106_main.c for features. 8 * 9 * Changelog: 10 * Support interrupts per period. 11 * Removed noise from Center/LFE channel when in Analog mode. 12 * Rename and remove mixer controls. 13 * 0.0.6 14 * Use separate card based DMA buffer for periods table list. 15 * 0.0.7 16 * Change remove and rename ctrls into lists. 17 * 0.0.8 18 * Try to fix capture sources. 19 * 0.0.9 20 * Fix AC3 output. 21 * Enable S32_LE format support. 22 * 0.0.10 23 * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".) 24 * 0.0.11 25 * Add Model name recognition. 26 * 0.0.12 27 * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period. 28 * Remove redundent "voice" handling. 29 * 0.0.13 30 * Single trigger call for multi channels. 31 * 0.0.14 32 * Set limits based on what the sound card hardware can do. 33 * playback periods_min=2, periods_max=8 34 * capture hw constraints require period_size = n * 64 bytes. 35 * playback hw constraints require period_size = n * 64 bytes. 36 * 0.0.15 37 * Separate ca0106.c into separate functional .c files. 38 * 0.0.16 39 * Modified Copyright message. 40 * 0.0.17 41 * Add iec958 file in proc file system to show status of SPDIF in. 42 * 0.0.18 43 * Implement support for Line-in capture on SB Live 24bit. 44 * 45 * This code was initially based on code from ALSA's emu10k1x.c which is: 46 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> 47 * 48 * This program is free software; you can redistribute it and/or modify 49 * it under the terms of the GNU General Public License as published by 50 * the Free Software Foundation; either version 2 of the License, or 51 * (at your option) any later version. 52 * 53 * This program is distributed in the hope that it will be useful, 54 * but WITHOUT ANY WARRANTY; without even the implied warranty of 55 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 56 * GNU General Public License for more details. 57 * 58 * You should have received a copy of the GNU General Public License 59 * along with this program; if not, write to the Free Software 60 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 61 * 62 */ 63#include <linux/delay.h> 64#include <linux/init.h> 65#include <linux/interrupt.h> 66#include <linux/moduleparam.h> 67#include <linux/io.h> 68#include <sound/core.h> 69#include <sound/initval.h> 70#include <sound/pcm.h> 71#include <sound/ac97_codec.h> 72#include <sound/info.h> 73#include <sound/asoundef.h> 74 75#include "ca0106.h" 76 77 78struct snd_ca0106_category_str { 79 int val; 80 const char *name; 81}; 82 83static struct snd_ca0106_category_str snd_ca0106_con_category[] = { 84 { IEC958_AES1_CON_DAT, "DAT" }, 85 { IEC958_AES1_CON_VCR, "VCR" }, 86 { IEC958_AES1_CON_MICROPHONE, "microphone" }, 87 { IEC958_AES1_CON_SYNTHESIZER, "synthesizer" }, 88 { IEC958_AES1_CON_RATE_CONVERTER, "rate converter" }, 89 { IEC958_AES1_CON_MIXER, "mixer" }, 90 { IEC958_AES1_CON_SAMPLER, "sampler" }, 91 { IEC958_AES1_CON_PCM_CODER, "PCM coder" }, 92 { IEC958_AES1_CON_IEC908_CD, "CD" }, 93 { IEC958_AES1_CON_NON_IEC908_CD, "non-IEC908 CD" }, 94 { IEC958_AES1_CON_GENERAL, "general" }, 95}; 96 97 98static void snd_ca0106_proc_dump_iec958( struct snd_info_buffer *buffer, u32 value) 99{ 100 int i; 101 u32 status[4]; 102 status[0] = value & 0xff; 103 status[1] = (value >> 8) & 0xff; 104 status[2] = (value >> 16) & 0xff; 105 status[3] = (value >> 24) & 0xff; 106 107 if (! (status[0] & IEC958_AES0_PROFESSIONAL)) { 108 /* consumer */ 109 snd_iprintf(buffer, "Mode: consumer\n"); 110 snd_iprintf(buffer, "Data: "); 111 if (!(status[0] & IEC958_AES0_NONAUDIO)) { 112 snd_iprintf(buffer, "audio\n"); 113 } else { 114 snd_iprintf(buffer, "non-audio\n"); 115 } 116 snd_iprintf(buffer, "Rate: "); 117 switch (status[3] & IEC958_AES3_CON_FS) { 118 case IEC958_AES3_CON_FS_44100: 119 snd_iprintf(buffer, "44100 Hz\n"); 120 break; 121 case IEC958_AES3_CON_FS_48000: 122 snd_iprintf(buffer, "48000 Hz\n"); 123 break; 124 case IEC958_AES3_CON_FS_32000: 125 snd_iprintf(buffer, "32000 Hz\n"); 126 break; 127 default: 128 snd_iprintf(buffer, "unknown\n"); 129 break; 130 } 131 snd_iprintf(buffer, "Copyright: "); 132 if (status[0] & IEC958_AES0_CON_NOT_COPYRIGHT) { 133 snd_iprintf(buffer, "permitted\n"); 134 } else { 135 snd_iprintf(buffer, "protected\n"); 136 } 137 snd_iprintf(buffer, "Emphasis: "); 138 if ((status[0] & IEC958_AES0_CON_EMPHASIS) != IEC958_AES0_CON_EMPHASIS_5015) { 139 snd_iprintf(buffer, "none\n"); 140 } else { 141 snd_iprintf(buffer, "50/15us\n"); 142 } 143 snd_iprintf(buffer, "Category: "); 144 for (i = 0; i < ARRAY_SIZE(snd_ca0106_con_category); i++) { 145 if ((status[1] & IEC958_AES1_CON_CATEGORY) == snd_ca0106_con_category[i].val) { 146 snd_iprintf(buffer, "%s\n", snd_ca0106_con_category[i].name); 147 break; 148 } 149 } 150 if (i >= ARRAY_SIZE(snd_ca0106_con_category)) { 151 snd_iprintf(buffer, "unknown 0x%x\n", status[1] & IEC958_AES1_CON_CATEGORY); 152 } 153 snd_iprintf(buffer, "Original: "); 154 if (status[1] & IEC958_AES1_CON_ORIGINAL) { 155 snd_iprintf(buffer, "original\n"); 156 } else { 157 snd_iprintf(buffer, "1st generation\n"); 158 } 159 snd_iprintf(buffer, "Clock: "); 160 switch (status[3] & IEC958_AES3_CON_CLOCK) { 161 case IEC958_AES3_CON_CLOCK_1000PPM: 162 snd_iprintf(buffer, "1000 ppm\n"); 163 break; 164 case IEC958_AES3_CON_CLOCK_50PPM: 165 snd_iprintf(buffer, "50 ppm\n"); 166 break; 167 case IEC958_AES3_CON_CLOCK_VARIABLE: 168 snd_iprintf(buffer, "variable pitch\n"); 169 break; 170 default: 171 snd_iprintf(buffer, "unknown\n"); 172 break; 173 } 174 } else { 175 snd_iprintf(buffer, "Mode: professional\n"); 176 snd_iprintf(buffer, "Data: "); 177 if (!(status[0] & IEC958_AES0_NONAUDIO)) { 178 snd_iprintf(buffer, "audio\n"); 179 } else { 180 snd_iprintf(buffer, "non-audio\n"); 181 } 182 snd_iprintf(buffer, "Rate: "); 183 switch (status[0] & IEC958_AES0_PRO_FS) { 184 case IEC958_AES0_PRO_FS_44100: 185 snd_iprintf(buffer, "44100 Hz\n"); 186 break; 187 case IEC958_AES0_PRO_FS_48000: 188 snd_iprintf(buffer, "48000 Hz\n"); 189 break; 190 case IEC958_AES0_PRO_FS_32000: 191 snd_iprintf(buffer, "32000 Hz\n"); 192 break; 193 default: 194 snd_iprintf(buffer, "unknown\n"); 195 break; 196 } 197 snd_iprintf(buffer, "Rate Locked: "); 198 if (status[0] & IEC958_AES0_PRO_FREQ_UNLOCKED) 199 snd_iprintf(buffer, "no\n"); 200 else 201 snd_iprintf(buffer, "yes\n"); 202 snd_iprintf(buffer, "Emphasis: "); 203 switch (status[0] & IEC958_AES0_PRO_EMPHASIS) { 204 case IEC958_AES0_PRO_EMPHASIS_CCITT: 205 snd_iprintf(buffer, "CCITT J.17\n"); 206 break; 207 case IEC958_AES0_PRO_EMPHASIS_NONE: 208 snd_iprintf(buffer, "none\n"); 209 break; 210 case IEC958_AES0_PRO_EMPHASIS_5015: 211 snd_iprintf(buffer, "50/15us\n"); 212 break; 213 case IEC958_AES0_PRO_EMPHASIS_NOTID: 214 default: 215 snd_iprintf(buffer, "unknown\n"); 216 break; 217 } 218 snd_iprintf(buffer, "Stereophonic: "); 219 if ((status[1] & IEC958_AES1_PRO_MODE) == IEC958_AES1_PRO_MODE_STEREOPHONIC) { 220 snd_iprintf(buffer, "stereo\n"); 221 } else { 222 snd_iprintf(buffer, "not indicated\n"); 223 } 224 snd_iprintf(buffer, "Userbits: "); 225 switch (status[1] & IEC958_AES1_PRO_USERBITS) { 226 case IEC958_AES1_PRO_USERBITS_192: 227 snd_iprintf(buffer, "192bit\n"); 228 break; 229 case IEC958_AES1_PRO_USERBITS_UDEF: 230 snd_iprintf(buffer, "user-defined\n"); 231 break; 232 default: 233 snd_iprintf(buffer, "unknown\n"); 234 break; 235 } 236 snd_iprintf(buffer, "Sample Bits: "); 237 switch (status[2] & IEC958_AES2_PRO_SBITS) { 238 case IEC958_AES2_PRO_SBITS_20: 239 snd_iprintf(buffer, "20 bit\n"); 240 break; 241 case IEC958_AES2_PRO_SBITS_24: 242 snd_iprintf(buffer, "24 bit\n"); 243 break; 244 case IEC958_AES2_PRO_SBITS_UDEF: 245 snd_iprintf(buffer, "user defined\n"); 246 break; 247 default: 248 snd_iprintf(buffer, "unknown\n"); 249 break; 250 } 251 snd_iprintf(buffer, "Word Length: "); 252 switch (status[2] & IEC958_AES2_PRO_WORDLEN) { 253 case IEC958_AES2_PRO_WORDLEN_22_18: 254 snd_iprintf(buffer, "22 bit or 18 bit\n"); 255 break; 256 case IEC958_AES2_PRO_WORDLEN_23_19: 257 snd_iprintf(buffer, "23 bit or 19 bit\n"); 258 break; 259 case IEC958_AES2_PRO_WORDLEN_24_20: 260 snd_iprintf(buffer, "24 bit or 20 bit\n"); 261 break; 262 case IEC958_AES2_PRO_WORDLEN_20_16: 263 snd_iprintf(buffer, "20 bit or 16 bit\n"); 264 break; 265 default: 266 snd_iprintf(buffer, "unknown\n"); 267 break; 268 } 269 } 270} 271 272static void snd_ca0106_proc_iec958(struct snd_info_entry *entry, 273 struct snd_info_buffer *buffer) 274{ 275 struct snd_ca0106 *emu = entry->private_data; 276 u32 value; 277 278 value = snd_ca0106_ptr_read(emu, SAMPLE_RATE_TRACKER_STATUS, 0); 279 snd_iprintf(buffer, "Status: %s, %s, %s\n", 280 (value & 0x100000) ? "Rate Locked" : "Not Rate Locked", 281 (value & 0x200000) ? "SPDIF Locked" : "No SPDIF Lock", 282 (value & 0x400000) ? "Audio Valid" : "No valid audio" ); 283 snd_iprintf(buffer, "Estimated sample rate: %u\n", 284 ((value & 0xfffff) * 48000) / 0x8000 ); 285 if (value & 0x200000) { 286 snd_iprintf(buffer, "IEC958/SPDIF input status:\n"); 287 value = snd_ca0106_ptr_read(emu, SPDIF_INPUT_STATUS, 0); 288 snd_ca0106_proc_dump_iec958(buffer, value); 289 } 290 291 snd_iprintf(buffer, "\n"); 292} 293 294static void snd_ca0106_proc_reg_write32(struct snd_info_entry *entry, 295 struct snd_info_buffer *buffer) 296{ 297 struct snd_ca0106 *emu = entry->private_data; 298 unsigned long flags; 299 char line[64]; 300 u32 reg, val; 301 while (!snd_info_get_line(buffer, line, sizeof(line))) { 302 if (sscanf(line, "%x %x", ®, &val) != 2) 303 continue; 304 if (reg < 0x40 && val <= 0xffffffff) { 305 spin_lock_irqsave(&emu->emu_lock, flags); 306 outl(val, emu->port + (reg & 0xfffffffc)); 307 spin_unlock_irqrestore(&emu->emu_lock, flags); 308 } 309 } 310} 311 312static void snd_ca0106_proc_reg_read32(struct snd_info_entry *entry, 313 struct snd_info_buffer *buffer) 314{ 315 struct snd_ca0106 *emu = entry->private_data; 316 unsigned long value; 317 unsigned long flags; 318 int i; 319 snd_iprintf(buffer, "Registers:\n\n"); 320 for(i = 0; i < 0x20; i+=4) { 321 spin_lock_irqsave(&emu->emu_lock, flags); 322 value = inl(emu->port + i); 323 spin_unlock_irqrestore(&emu->emu_lock, flags); 324 snd_iprintf(buffer, "Register %02X: %08lX\n", i, value); 325 } 326} 327 328static void snd_ca0106_proc_reg_read16(struct snd_info_entry *entry, 329 struct snd_info_buffer *buffer) 330{ 331 struct snd_ca0106 *emu = entry->private_data; 332 unsigned int value; 333 unsigned long flags; 334 int i; 335 snd_iprintf(buffer, "Registers:\n\n"); 336 for(i = 0; i < 0x20; i+=2) { 337 spin_lock_irqsave(&emu->emu_lock, flags); 338 value = inw(emu->port + i); 339 spin_unlock_irqrestore(&emu->emu_lock, flags); 340 snd_iprintf(buffer, "Register %02X: %04X\n", i, value); 341 } 342} 343 344static void snd_ca0106_proc_reg_read8(struct snd_info_entry *entry, 345 struct snd_info_buffer *buffer) 346{ 347 struct snd_ca0106 *emu = entry->private_data; 348 unsigned int value; 349 unsigned long flags; 350 int i; 351 snd_iprintf(buffer, "Registers:\n\n"); 352 for(i = 0; i < 0x20; i+=1) { 353 spin_lock_irqsave(&emu->emu_lock, flags); 354 value = inb(emu->port + i); 355 spin_unlock_irqrestore(&emu->emu_lock, flags); 356 snd_iprintf(buffer, "Register %02X: %02X\n", i, value); 357 } 358} 359 360static void snd_ca0106_proc_reg_read1(struct snd_info_entry *entry, 361 struct snd_info_buffer *buffer) 362{ 363 struct snd_ca0106 *emu = entry->private_data; 364 unsigned long value; 365 int i,j; 366 367 snd_iprintf(buffer, "Registers\n"); 368 for(i = 0; i < 0x40; i++) { 369 snd_iprintf(buffer, "%02X: ",i); 370 for (j = 0; j < 4; j++) { 371 value = snd_ca0106_ptr_read(emu, i, j); 372 snd_iprintf(buffer, "%08lX ", value); 373 } 374 snd_iprintf(buffer, "\n"); 375 } 376} 377 378static void snd_ca0106_proc_reg_read2(struct snd_info_entry *entry, 379 struct snd_info_buffer *buffer) 380{ 381 struct snd_ca0106 *emu = entry->private_data; 382 unsigned long value; 383 int i,j; 384 385 snd_iprintf(buffer, "Registers\n"); 386 for(i = 0x40; i < 0x80; i++) { 387 snd_iprintf(buffer, "%02X: ",i); 388 for (j = 0; j < 4; j++) { 389 value = snd_ca0106_ptr_read(emu, i, j); 390 snd_iprintf(buffer, "%08lX ", value); 391 } 392 snd_iprintf(buffer, "\n"); 393 } 394} 395 396static void snd_ca0106_proc_reg_write(struct snd_info_entry *entry, 397 struct snd_info_buffer *buffer) 398{ 399 struct snd_ca0106 *emu = entry->private_data; 400 char line[64]; 401 unsigned int reg, channel_id , val; 402 while (!snd_info_get_line(buffer, line, sizeof(line))) { 403 if (sscanf(line, "%x %x %x", ®, &channel_id, &val) != 3) 404 continue; 405 if (reg < 0x80 && val <= 0xffffffff && channel_id <= 3) 406 snd_ca0106_ptr_write(emu, reg, channel_id, val); 407 } 408} 409 410static void snd_ca0106_proc_i2c_write(struct snd_info_entry *entry, 411 struct snd_info_buffer *buffer) 412{ 413 struct snd_ca0106 *emu = entry->private_data; 414 char line[64]; 415 unsigned int reg, val; 416 while (!snd_info_get_line(buffer, line, sizeof(line))) { 417 if (sscanf(line, "%x %x", ®, &val) != 2) 418 continue; 419 if ((reg <= 0x7f) || (val <= 0x1ff)) { 420 snd_ca0106_i2c_write(emu, reg, val); 421 } 422 } 423} 424 425int snd_ca0106_proc_init(struct snd_ca0106 *emu) 426{ 427 struct snd_info_entry *entry; 428 429 if(! snd_card_proc_new(emu->card, "iec958", &entry)) 430 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_iec958); 431 if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) { 432 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read32); 433 entry->c.text.write = snd_ca0106_proc_reg_write32; 434 entry->mode |= S_IWUSR; 435 } 436 if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) 437 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read16); 438 if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry)) 439 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read8); 440 if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) { 441 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1); 442 entry->c.text.write = snd_ca0106_proc_reg_write; 443 entry->mode |= S_IWUSR; 444 } 445 if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { 446 entry->c.text.write = snd_ca0106_proc_i2c_write; 447 entry->private_data = emu; 448 entry->mode |= S_IWUSR; 449 } 450 if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) 451 snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2); 452 return 0; 453} 454