Exemple #1
0
/**
 * 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;
}
Exemple #2
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;
}
Exemple #4
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,