Пример #1
0
static int snd_atiixp_pcm_hw_free(snd_pcm_substream_t * substream)
{
    atiixp_t *chip = snd_pcm_substream_chip(substream);
    atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;

    if (dma->pcm_open_flag) {
        struct ac97_pcm *pcm = chip->pcms[dma->ac97_pcm_type];
        snd_ac97_pcm_close(pcm);
        dma->pcm_open_flag = 0;
    }
    atiixp_clear_dma_packets(chip, dma, substream);
    snd_pcm_lib_free_pages(substream);
    return 0;
}
Пример #2
0
/*
 * hw_params - allocate the buffer and set up buffer descriptors
 */
static int snd_atiixp_pcm_hw_params(snd_pcm_substream_t *substream,
                                    snd_pcm_hw_params_t *hw_params)
{
    atiixp_t *chip = snd_pcm_substream_chip(substream);
    atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
    int err;

    err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
    if (err < 0)
        return err;
    dma->buf_addr = substream->runtime->dma_addr;
    dma->buf_bytes = params_buffer_bytes(hw_params);

    err = atiixp_build_dma_packets(chip, dma, substream,
                                   params_periods(hw_params),
                                   params_period_bytes(hw_params));
    if (err < 0)
        return err;

    if (dma->ac97_pcm_type >= 0) {
        struct ac97_pcm *pcm = chip->pcms[dma->ac97_pcm_type];
        /* PCM is bound to AC97 codec(s)
         * set up the AC97 codecs
         */
        if (dma->pcm_open_flag) {
            snd_ac97_pcm_close(pcm);
            dma->pcm_open_flag = 0;
        }
        err = snd_ac97_pcm_open(pcm, params_rate(hw_params),
                                params_channels(hw_params),
                                pcm->r[0].slots);
        if (err >= 0)
            dma->pcm_open_flag = 1;
    }

    return err;
}
Пример #3
0
/**
 * snd_ac97_pcm_open - opens the given AC97 pcm
 * @pcm: the ac97 pcm instance
 * @rate: rate in Hz, if codec does not support VRA, this value must be 48000Hz
 * @cfg: output stream characteristics
 * @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm
 *
 * It locks the specified slots and sets the given rate to AC97 registers.
 *
 * Return: Zero if successful, or a negative error code on failure.
 */
int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
		      enum ac97_pcm_cfg cfg, unsigned short slots)
{
	struct snd_ac97_bus *bus;
	int i, cidx, r, ok_flag;
	unsigned int reg_ok[4] = {0,0,0,0};
	unsigned char reg;
	int err = 0;

	r = rate > 48000;
	bus = pcm->bus;
	if (cfg == AC97_PCM_CFG_SPDIF) {
		for (cidx = 0; cidx < 4; cidx++)
			if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) {
				err = set_spdif_rate(bus->codec[cidx], rate);
				if (err < 0)
					return err;
			}
	}
	spin_lock_irq(&pcm->bus->bus_lock);
	for (i = 3; i < 12; i++) {
		if (!(slots & (1 << i)))
			continue;
		ok_flag = 0;
		for (cidx = 0; cidx < 4; cidx++) {
			if (bus->used_slots[pcm->stream][cidx] & (1 << i)) {
				spin_unlock_irq(&pcm->bus->bus_lock);
				err = -EBUSY;
				goto error;
			}
			if (pcm->r[r].rslots[cidx] & (1 << i)) {
				bus->used_slots[pcm->stream][cidx] |= (1 << i);
				ok_flag++;
			}
		}
		if (!ok_flag) {
			spin_unlock_irq(&pcm->bus->bus_lock);
			snd_printk(KERN_ERR "cannot find configuration for AC97 slot %i\n", i);
			err = -EAGAIN;
			goto error;
		}
	}
	pcm->cur_dbl = r;
	spin_unlock_irq(&pcm->bus->bus_lock);
	for (i = 3; i < 12; i++) {
		if (!(slots & (1 << i)))
			continue;
		for (cidx = 0; cidx < 4; cidx++) {
			if (pcm->r[r].rslots[cidx] & (1 << i)) {
				reg = get_slot_reg(pcm, cidx, i, r);
				if (reg == 0xff) {
					snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i);
					continue;
				}
				if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE)))
					continue;
				//printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate);
				err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate);
				if (err < 0)
					snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err);
				else
					reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE));
			}
		}
	}
	pcm->aslots = slots;
	return 0;

 error:
	pcm->aslots = slots;
	snd_ac97_pcm_close(pcm);
	return err;
}