/** * snd_ac97_set_rate - change the rate of the given input/output. * @ac97: the ac97 instance * @reg: the register to change * @rate: the sample rate to set * * Changes the rate of the given input/output on the codec. * If the codec doesn't support VAR, the rate must be 48000 (except * for SPDIF). * * The valid registers are AC97_PMC_MIC_ADC_RATE, * AC97_PCM_FRONT_DAC_RATE, AC97_PCM_LR_ADC_RATE. * AC97_PCM_SURR_DAC_RATE and AC97_PCM_LFE_DAC_RATE are accepted * if the codec supports them. * AC97_SPDIF is accepted as a pseudo register to modify the SPDIF * status bits. * * Returns zero if successful, or a negative error code on failure. */ int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate) { int dbl; unsigned int tmp; dbl = rate > 48000; if (dbl) { if (!(ac97->flags & AC97_DOUBLE_RATE)) return -EINVAL; if (reg != AC97_PCM_FRONT_DAC_RATE) return -EINVAL; } switch (reg) { case AC97_PCM_MIC_ADC_RATE: if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRM) == 0) /* MIC VRA */ if (rate != 48000) return -EINVAL; break; case AC97_PCM_FRONT_DAC_RATE: case AC97_PCM_LR_ADC_RATE: if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRA) == 0) /* VRA */ if (rate != 48000 && rate != 96000) return -EINVAL; break; case AC97_PCM_SURR_DAC_RATE: if (! (ac97->scaps & AC97_SCAP_SURROUND_DAC)) return -EINVAL; break; case AC97_PCM_LFE_DAC_RATE: if (! (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)) return -EINVAL; break; case AC97_SPDIF: /* special case */ return set_spdif_rate(ac97, rate); default: return -EINVAL; } if (dbl) rate /= 2; tmp = (rate * ac97->bus->clock) / 48000; if (tmp > 65535) return -EINVAL; if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_DRA, dbl ? AC97_EA_DRA : 0); snd_ac97_update(ac97, reg, tmp & 0xffff); snd_ac97_read(ac97, reg); if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) { /* Intel controllers require double rate data to be put in * slots 7+8 */ snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, AC97_GP_DRSS_MASK, dbl ? AC97_GP_DRSS_78 : 0); snd_ac97_read(ac97, AC97_GENERAL_PURPOSE); } return 0; }
void snd_init() { unsigned int codec_id; unsigned int mask; snd_cr_request = 0; snd_cr_reply = 0; CSR_AC97_DCTL = 0; CSR_AC97_UCTL = 0; mask = irq_getmask(); mask |= IRQ_AC97CRREQUEST|IRQ_AC97CRREPLY|IRQ_AC97DMAR|IRQ_AC97DMAW; irq_setmask(mask); codec_id = snd_ac97_read(0x00); if(codec_id == 0x0d50) printf("SND: found LM4550 AC'97 codec\n"); else printf("SND: warning, unknown codec found (ID:%04x)\n", codec_id); /* Unmute and set volumes */ /* TODO: API for this */ snd_ac97_write(0x02, 0x0000); snd_ac97_write(0x04, 0x0f0f); snd_ac97_write(0x18, 0x0000); snd_ac97_write(0x0e, 0x0000); snd_ac97_write(0x1c, 0x0f0f); snd_play_empty(); snd_record_empty(); printf("SND: initialization complete\n"); }
static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice) { if (ice->ac97) /* we use pins 39 and 41 of the VT1616 for left and right read outputs */ snd_ac97_write_cache(ice->ac97, 0x5a, snd_ac97_read(ice->ac97, 0x5a) & ~0x8000); return 0; }
void snd_init() { unsigned int codec_id; unsigned int mask; if(!(CSR_CAPABILITIES & CAP_AC97)) { printf("SND: not supported by SoC, giving up.\n"); return; } snd_cr_request = 0; snd_cr_reply = 0; /* Reset AC'97 controller */ CSR_AC97_CRCTL = 0; CSR_AC97_DCTL = 0; CSR_AC97_UCTL = 0; irq_ack(IRQ_AC97CRREQUEST|IRQ_AC97CRREPLY|IRQ_AC97DMAR|IRQ_AC97DMAW); mask = irq_getmask(); mask |= IRQ_AC97CRREQUEST|IRQ_AC97CRREPLY|IRQ_AC97DMAR|IRQ_AC97DMAW; irq_setmask(mask); codec_id = snd_ac97_read(0x00); if(codec_id == 0x0d50) printf("SND: found LM4550 AC'97 codec\n"); else if(codec_id == 0x6150) printf("SND: found WM9707 AC'97 codec\n"); else printf("SND: warning, unknown codec found (ID:%04x)\n", codec_id); /* Unmute and set volumes */ /* TODO: API for this */ snd_ac97_write(0x02, 0x0000); /* master volume */ snd_ac97_write(0x04, 0x0f0f); /* headphones volume */ snd_ac97_write(0x18, 0x0000); /* PCM out volume */ snd_ac97_write(0x1c, 0x0f0f); /* record gain */ snd_ac97_write(0x0e, 0x0000); /* mic volume: max */ snd_ac97_write(0x10, 0x0000); /* line in volume: max */ snd_ac97_write(0x1a, 0x0505); /* record select: stero mix */ snd_play_empty(); snd_record_empty(); printf("SND: initialization complete\n"); }
static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate) { unsigned short old, bits, reg, mask; unsigned int sbits; if (! (ac97->ext_id & AC97_EI_SPDIF)) return -ENODEV; /* TODO: double rate support */ if (ac97->flags & AC97_CS_SPDIF) { switch (rate) { case 48000: bits = 0; break; case 44100: bits = 1 << AC97_SC_SPSR_SHIFT; break; default: /* invalid - disable output */ snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); return -EINVAL; } reg = AC97_CSR_SPDIF; mask = 1 << AC97_SC_SPSR_SHIFT; } else { if (ac97->id == AC97_ID_CM9739 && rate != 48000) { snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); return -EINVAL; } switch (rate) { case 44100: bits = AC97_SC_SPSR_44K; break; case 48000: bits = AC97_SC_SPSR_48K; break; case 32000: bits = AC97_SC_SPSR_32K; break; default: /* invalid - disable output */ snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); return -EINVAL; } reg = AC97_SPDIF; mask = AC97_SC_SPSR_MASK; } mutex_lock(&ac97->reg_mutex); old = snd_ac97_read(ac97, reg) & mask; if (old != bits) { snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); snd_ac97_update_bits_nolock(ac97, reg, mask, bits); /* update the internal spdif bits */ sbits = ac97->spdif_status; if (sbits & IEC958_AES0_PROFESSIONAL) { sbits &= ~IEC958_AES0_PRO_FS; switch (rate) { case 44100: sbits |= IEC958_AES0_PRO_FS_44100; break; case 48000: sbits |= IEC958_AES0_PRO_FS_48000; break; case 32000: sbits |= IEC958_AES0_PRO_FS_32000; break; } } else { sbits &= ~(IEC958_AES3_CON_FS << 24); switch (rate) { case 44100: sbits |= IEC958_AES3_CON_FS_44100<<24; break; case 48000: sbits |= IEC958_AES3_CON_FS_48000<<24; break; case 32000: sbits |= IEC958_AES3_CON_FS_32000<<24; break; } } ac97->spdif_status = sbits; } snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF); mutex_unlock(&ac97->reg_mutex); return 0; }
if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) { for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) wm_put(ice, wm_inits[i], wm_inits[i+1]); } return 0; } static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice) { <<<<<<< HEAD if (ice->ac97) /* we use pins 39 and 41 of the VT1616 for left and right read outputs */ snd_ac97_write_cache(ice->ac97, 0x5a, snd_ac97_read(ice->ac97, 0x5a) & ~0x8000); ======= /* we use pins 39 and 41 of the VT1616 for left and right read outputs */ snd_ac97_write_cache(ice->ac97, 0x5a, snd_ac97_read(ice->ac97, 0x5a) & ~0x8000); >>>>>>> 296c66da8a02d52243f45b80521febece5ed498a return 0; } /* entry point */ struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = { { .subvendor = VT1724_SUBDEVICE_AV710, .name = "Chaintech AV-710", .model = "av710", .chip_init = snd_vt1724_amp_init,