📄 ac97_codec.c
字号:
val & 0x4000 ? "on" : "off", val & 0x2000 ? "on" : "off", val & 0x1000 ? "on" : "off", val & 0x0200 ? "Mic" : "MIX", val & 0x0100 ? "Mic2" : "Mic1", val & 0x0080 ? "on" : "off"); ext = snd_ac97_read(ac97, AC97_EXTENDED_ID); if (ext == 0) return; snd_iprintf(buffer, "Extended ID : codec=%i rev=%i%s%s%s%s DSA=%i%s%s%s%s\n", (ext >> 14) & 3, (ext >> 10) & 3, ext & 0x0200 ? " AMAP" : "", ext & 0x0100 ? " LDAC" : "", ext & 0x0080 ? " SDAC" : "", ext & 0x0040 ? " CDAC" : "", (ext >> 4) & 3, ext & 0x0008 ? " VRM" : "", ext & 0x0004 ? " SPDIF" : "", ext & 0x0002 ? " DRA" : "", ext & 0x0001 ? " VRA" : ""); val = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); snd_iprintf(buffer, "Extended status :%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", val & 0x4000 ? " PRL" : "", val & 0x2000 ? " PRK" : "", val & 0x1000 ? " PRJ" : "", val & 0x0800 ? " PRI" : "", val & 0x0400 ? " SPCV" : "", val & 0x0200 ? " MADC" : "", val & 0x0100 ? " LDAC" : "", val & 0x0080 ? " SDAC" : "", val & 0x0040 ? " CDAC" : "", ext & 0x0004 ? spdif_slots[(val & 0x0030) >> 4] : "", val & 0x0008 ? " VRM" : "", val & 0x0004 ? " SPDIF" : "", val & 0x0002 ? " DRA" : "", val & 0x0001 ? " VRA" : ""); if (ext & 1) { /* VRA */ val = snd_ac97_read(ac97, AC97_PCM_FRONT_DAC_RATE); snd_iprintf(buffer, "PCM front DAC : %iHz\n", val); if (ext & 0x0080) { val = snd_ac97_read(ac97, AC97_PCM_SURR_DAC_RATE); snd_iprintf(buffer, "PCM Surr DAC : %iHz\n", val); } if (ext & 0x0100) { val = snd_ac97_read(ac97, AC97_PCM_LFE_DAC_RATE); snd_iprintf(buffer, "PCM LFE DAC : %iHz\n", val); } val = snd_ac97_read(ac97, AC97_PCM_LR_ADC_RATE); snd_iprintf(buffer, "PCM ADC : %iHz\n", val); } if (ext & 0x0008) { val = snd_ac97_read(ac97, AC97_PCM_MIC_ADC_RATE); snd_iprintf(buffer, "PCM MIC ADC : %iHz\n", val); } if (ext & 0x0004) { val = snd_ac97_read(ac97, AC97_SPDIF); snd_iprintf(buffer, "SPDIF Control :%s%s%s%s Category=0x%x Generation=%i%s%s%s\n", val & 0x0001 ? " PRO" : " Consumer", val & 0x0002 ? " Non-audio" : " PCM", val & 0x0004 ? " Copyright" : "", val & 0x0008 ? " Preemph50/15" : "", (val & 0x07f0) >> 4, (val & 0x0800) >> 11, spdif_rates[(val & 0x3000) >> 12], val & 0x4000 ? " DRS" : "", val & 0x8000 ? " Validity" : ""); }}static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer){ ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; down(&ac97->spec.ad18xx.mutex); for (idx = 0; idx < 3; idx++) if (ac97->spec.ad18xx.id[idx]) { /* select single codec */ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]); snd_ac97_proc_read_main(ac97, buffer, idx); snd_iprintf(buffer, "\n\n"); } /* select all codecs */ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000); up(&ac97->spec.ad18xx.mutex); snd_iprintf(buffer, "\nAD18XX configuration\n"); snd_iprintf(buffer, "Unchained : 0x%04x,0x%04x,0x%04x\n", ac97->spec.ad18xx.unchained[0], ac97->spec.ad18xx.unchained[1], ac97->spec.ad18xx.unchained[2]); snd_iprintf(buffer, "Chained : 0x%04x,0x%04x,0x%04x\n", ac97->spec.ad18xx.chained[0], ac97->spec.ad18xx.chained[1], ac97->spec.ad18xx.chained[2]); } else { snd_ac97_proc_read_main(ac97, buffer, 0); }}static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx){ int reg, val; for (reg = 0; reg < 0x80; reg += 2) { val = snd_ac97_read(ac97, reg); snd_iprintf(buffer, "%i:%02x = %04x\n", subidx, reg, val); }}static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer){ ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return); if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86 int idx; down(&ac97->spec.ad18xx.mutex); for (idx = 0; idx < 3; idx++) if (ac97->spec.ad18xx.id[idx]) { /* select single codec */ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]); snd_ac97_proc_regs_read_main(ac97, buffer, idx); } /* select all codecs */ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000); up(&ac97->spec.ad18xx.mutex); } else { snd_ac97_proc_regs_read_main(ac97, buffer, 0); } }static void snd_ac97_proc_init(snd_card_t * card, ac97_t * ac97){ snd_info_entry_t *entry; char name[12]; sprintf(name, "ac97#%d", ac97->addr); if ((entry = snd_info_create_card_entry(card, name, card->proc_root)) != NULL) { entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = ac97; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; entry->c.text.read_size = 512; entry->c.text.read = snd_ac97_proc_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; } } ac97->proc_entry = entry; sprintf(name, "ac97#%dregs", ac97->addr); if ((entry = snd_info_create_card_entry(card, name, card->proc_root)) != NULL) { entry->content = SNDRV_INFO_CONTENT_TEXT; entry->private_data = ac97; entry->mode = S_IFREG | S_IRUGO | S_IWUSR; entry->c.text.read_size = 1024; entry->c.text.read = snd_ac97_proc_regs_read; if (snd_info_register(entry) < 0) { snd_info_free_entry(entry); entry = NULL; } } ac97->proc_regs_entry = entry;}static void snd_ac97_proc_done(ac97_t * ac97){ if (ac97->proc_regs_entry) { snd_info_unregister(ac97->proc_regs_entry); ac97->proc_regs_entry = NULL; } if (ac97->proc_entry) { snd_info_unregister(ac97->proc_entry); ac97->proc_entry = NULL; }}/* * Chip specific initialization */static int patch_wolfson(ac97_t * ac97){ // for all wolfson codecs (is this correct? --jk) snd_ac97_write_cache(ac97, 0x72, 0x0808); snd_ac97_write_cache(ac97, 0x74, 0x0808); // patch for DVD noise snd_ac97_write_cache(ac97, 0x5a, 0x0200); // init vol snd_ac97_write_cache(ac97, 0x70, 0x0808); snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000); return 0;}static int patch_tritech_tr28028(ac97_t * ac97){ snd_ac97_write_cache(ac97, 0x26, 0x0300); snd_ac97_write_cache(ac97, 0x26, 0x0000); snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000); snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000); return 0;}static int patch_sigmatel_stac9708(ac97_t * ac97){ unsigned int codec72, codec6c; codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000; codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG); if ((codec72==0) && (codec6c==0)) { snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007); } else if ((codec72==0x8000) && (codec6c==0)) { snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001); snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008); } else if ((codec72==0x8000) && (codec6c==0x0080)) { /* nothing */ } snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); return 0;}static int patch_sigmatel_stac9721(ac97_t * ac97){ if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) { // patch for SigmaTel snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); } snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); return 0;}static int patch_sigmatel_stac9744(ac97_t * ac97){ // patch for SigmaTel snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */ snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); return 0;}static int patch_sigmatel_stac9756(ac97_t * ac97){ // patch for SigmaTel snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */ snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); return 0;}static int patch_cirrus_cs4299(ac97_t * ac97){ ac97->flags |= AC97_HAS_PC_BEEP; /* force the detection of PC Beep */ return 0;}static int patch_ad1819(ac97_t * ac97){ // patch for Analog Devices snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000); /* select all codecs */ return 0;}static unsigned short patch_ad1881_unchained(ac97_t * ac97, int idx, unsigned short mask){ unsigned short val; // test for unchained codec snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, mask); snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); /* ID0C, ID1C, SDIE = off */ val = snd_ac97_read(ac97, AC97_VENDOR_ID2); if ((val & 0xff40) != 0x5340) return 0; ac97->spec.ad18xx.unchained[idx] = mask; ac97->spec.ad18xx.id[idx] = val; return mask;}static int patch_ad1881_chained1(ac97_t * ac97, int idx, unsigned short codec_bits){ static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 }; unsigned short val; snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, cfg_bits[idx]); snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004); // SDIE val = snd_ac97_read(ac97, AC97_VENDOR_ID2); if ((val & 0xff40) != 0x5340) return 0; if (codec_bits) snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, codec_bits); ac97->spec.ad18xx.chained[idx] = cfg_bits[idx]; ac97->spec.ad18xx.id[idx] = val; return 1;}static void patch_ad1881_chained(ac97_t * ac97, int unchained_idx, int cidx1, int cidx2){ // already detected? if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1]) cidx1 = -1; if (ac97->spec.ad18xx.unchained[cidx2] || ac97->spec.ad18xx.chained[cidx2]) cidx2 = -1; if (cidx1 < 0 && cidx2 < 0) return; // test for chained codecs snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[unchained_idx]); snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C if (cidx1 >= 0) { if (patch_ad1881_chained1(ac97, cidx1, 0x0006)) // SDIE | ID1C patch_ad1881_chained1(ac97, cidx2, 0); else if (patch_ad1881_chained1(ac97, cidx2, 0x0006)) // SDIE | ID1C patch_ad1881_chained1(ac97, cidx1, 0); } else if (cidx2 >= 0) { patch_ad1881_chained1(ac97, cidx2, 0); }}static int patch_ad1881(ac97_t * ac97){ static const char cfg_idxs[3][2] = { {2, 1}, {0, 2}, {0, 1} }; // patch for Analog Devices unsigned short codecs[3]; int idx, num; init_MUTEX(&ac97->spec.ad18xx.mutex); codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12)); codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14)); codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13)); snd_runtime_check(codecs[0] | codecs[1] | codecs[2], goto __end); for (idx = 0; idx < 3; idx++) if (ac97->spec.ad18xx.unchained[idx]) patch_ad1881_chained(ac97, idx, cfg_idxs[idx][0], cfg_idxs[idx][1]); if (ac97->spec.ad18xx.id[1]) { ac97->flags |= AC97_AD_MULTI; ac97->scaps |= AC97_SCAP_SURROUND_DAC; } if (ac97->spec.ad18xx.id[2]) { ac97->flags |= AC97_AD_MULTI; ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC; } __end: /* select all codecs */ snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000); /* check if only one codec is present */ for (idx = num = 0; idx < 3; idx++) if (ac97->spec.ad18xx.id[idx]) num++; if (num == 1) { /* ok, deselect all ID bits */ snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); } /* required for AD1886/AD1885 combination */ ac97->ext_id = snd_ac97_read(ac97, AC97_EXTENDED_ID); if (ac97->spec.ad18xx.id[0]) { ac97->id &= 0xffff0000; ac97->id |= ac97->spec.ad18xx.id[0]; } return 0;}/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -