Update of /cvsroot/alsa/alsa-kernel/pci In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25029
Modified Files: atiixp.c Log Message: - fixed SPDIF support. restricted only 48k sample rate. - fixed the address assignment for bigendian (not existing, though) Index: atiixp.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/atiixp.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- atiixp.c 11 Mar 2004 13:14:56 -0000 1.1 +++ atiixp.c 4 Apr 2004 16:02:43 -0000 1.2 @@ -246,9 +246,10 @@ snd_pcm_substream_t *substream; /* assigned PCM substream */ unsigned int buf_addr, buf_bytes; /* DMA buffer address, bytes */ unsigned int period_bytes, periods; + int opened; int running; - struct ac97_pcm *pcm; int pcm_open_flag; + int ac97_pcm_type; /* index # of ac97_pcm to access, -1 = not used */ }; /* @@ -270,12 +271,14 @@ spinlock_t ac97_lock; atiixp_dma_t dmas[3]; /* playback, capture, spdif */ + struct ac97_pcm *pcms[3]; /* playback, capture, spdif */ int max_channels; /* max. channels for PCM out */ unsigned int codec_not_ready_bits; /* for codec detection */ int spdif_over_aclink; /* passed from the module option */ + struct semaphore open_mutex; /* playback open mutex */ }; @@ -393,7 +396,7 @@ addr += period_bytes; } - writel(cpu_to_le32((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN), + writel((u32)dma->desc_buf.addr | ATI_REG_LINKPTR_EN, chip->remap_addr + dma->ops->llp_offset); dma->period_bytes = period_bytes; @@ -452,7 +455,9 @@ return data >> ATI_REG_PHYS_IN_DATA_SHIFT; udelay(1); } while (--timeout); - snd_printk(KERN_WARNING "atiixp: codec read timeout\n"); + /* time out may happen during reset */ + if (reg < 0x7c) + snd_printk(KERN_WARNING "atiixp: codec read timeout (reg %x)\n", reg); return 0xffff; } @@ -585,12 +590,16 @@ { unsigned int reg; - /* enable burst mode */ + /* set up spdif, enable burst mode */ reg = atiixp_read(chip, CMD); reg |= 0x02 << ATI_REG_CMD_SPDF_THRESHOLD_SHIFT; reg |= ATI_REG_CMD_BURST_EN; atiixp_write(chip, CMD, reg); + reg = atiixp_read(chip, SPDF_CMD); + reg &= ~(ATI_REG_SPDF_CMD_LFSR|ATI_REG_SPDF_CMD_SINGLE_CH); + atiixp_write(chip, SPDF_CMD, reg); + /* clear all interrupt source */ atiixp_write(chip, ISR, 0xffffffff); /* enable irqs */ @@ -657,7 +666,7 @@ { if (! dma->substream || ! dma->running) return; - snd_printd(KERN_DEBUG "atiixp: XRUN detected (DMA %d)\n", dma->ops->type); + snd_printdd("atiixp: XRUN detected (DMA %d)\n", dma->ops->type); snd_pcm_stop(dma->substream, SNDRV_PCM_STATE_XRUN); } @@ -800,15 +809,10 @@ { unsigned int data; data = atiixp_read(chip, CMD); - if (on) { + if (on) data |= ATI_REG_CMD_SPDF_OUT_EN; - if (chip->spdif_over_aclink) - data |= ATI_REG_CMD_SEND_EN; - } else { + else data &= ~ATI_REG_CMD_SPDF_OUT_EN; - if (chip->spdif_over_aclink) - data &= ~ATI_REG_CMD_SEND_EN; - } atiixp_write(chip, CMD, data); } @@ -835,25 +839,27 @@ static int snd_atiixp_spdif_prepare(snd_pcm_substream_t *substream) { atiixp_t *chip = snd_pcm_substream_chip(substream); - unsigned int data; spin_lock(&chip->reg_lock); if (chip->spdif_over_aclink) { + unsigned int data; /* enable slots 10/11 */ atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_CONFIG_MASK, ATI_REG_CMD_SPDF_CONFIG_01); - data = atiixp_read(chip, OUT_DMA_SLOT); + data = atiixp_read(chip, OUT_DMA_SLOT) & ~ATI_REG_OUT_DMA_SLOT_MASK; data |= ATI_REG_OUT_DMA_SLOT_BIT(10) | ATI_REG_OUT_DMA_SLOT_BIT(11); data |= 0x04 << ATI_REG_OUT_DMA_THRESHOLD_SHIFT; atiixp_write(chip, OUT_DMA_SLOT, data); + atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_OUT, + substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ? + ATI_REG_CMD_INTERLEAVE_OUT : 0); } else { atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_CONFIG_MASK, 0); + atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_SPDF, + substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ? + ATI_REG_CMD_INTERLEAVE_SPDF : 0); } - - atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_SPDF, - substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ? - ATI_REG_CMD_INTERLEAVE_SPDF : 0); spin_unlock(&chip->reg_lock); return 0; } @@ -938,17 +944,18 @@ if (err < 0) return err; - if (dma->pcm) { + 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(dma->pcm); + snd_ac97_pcm_close(pcm); dma->pcm_open_flag = 0; } - err = snd_ac97_pcm_open(dma->pcm, params_rate(hw_params), + err = snd_ac97_pcm_open(pcm, params_rate(hw_params), params_channels(hw_params), - dma->pcm->r[0].slots); + pcm->r[0].slots); if (err >= 0) dma->pcm_open_flag = 1; } @@ -962,7 +969,8 @@ atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data; if (dma->pcm_open_flag) { - snd_ac97_pcm_close(dma->pcm); + 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); @@ -992,7 +1000,7 @@ .periods_max = ATI_MAX_DESCRIPTORS, }; -static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma) +static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma, int pcm_type) { atiixp_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; @@ -1001,10 +1009,13 @@ snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL); + if (dma->opened) + return -EBUSY; dma->substream = substream; runtime->hw = snd_atiixp_pcm_hw; - if (dma->pcm) { - runtime->hw.rates = dma->pcm->rates; + dma->ac97_pcm_type = pcm_type; + if (pcm_type >= 0) { + runtime->hw.rates = chip->pcms[pcm_type]->rates; snd_pcm_limit_hw_rates(runtime); } else { /* SPDIF */ @@ -1019,6 +1030,7 @@ spin_lock_irqsave(&chip->reg_lock, flags); dma->ops->enable_dma(chip, 1); spin_unlock_irqrestore(&chip->reg_lock, flags); + dma->opened = 1; return 0; } @@ -1032,6 +1044,7 @@ dma->ops->enable_dma(chip, 0); spin_unlock_irq(&chip->reg_lock); dma->substream = NULL; + dma->opened = 0; return 0; } @@ -1042,26 +1055,33 @@ atiixp_t *chip = snd_pcm_substream_chip(substream); int err; - err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK]); + down(&chip->open_mutex); + err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 0); + up(&chip->open_mutex); + if (err < 0) + return err; substream->runtime->hw.channels_max = chip->max_channels; if (chip->max_channels > 2) /* channels must be even */ snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 2); - return 0; } static int snd_atiixp_playback_close(snd_pcm_substream_t *substream) { atiixp_t *chip = snd_pcm_substream_chip(substream); - return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); + int err; + down(&chip->open_mutex); + err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); + up(&chip->open_mutex); + return err; } static int snd_atiixp_capture_open(snd_pcm_substream_t *substream) { atiixp_t *chip = snd_pcm_substream_chip(substream); - return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE]); + return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE], 1); } static int snd_atiixp_capture_close(snd_pcm_substream_t *substream) @@ -1073,13 +1093,27 @@ static int snd_atiixp_spdif_open(snd_pcm_substream_t *substream) { atiixp_t *chip = snd_pcm_substream_chip(substream); - return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_SPDIF]); + int err; + down(&chip->open_mutex); + if (chip->spdif_over_aclink) /* share DMA_PLAYBACK */ + err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_PLAYBACK], 2); + else + err = snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_SPDIF], -1); + up(&chip->open_mutex); + return err; } static int snd_atiixp_spdif_close(snd_pcm_substream_t *substream) { atiixp_t *chip = snd_pcm_substream_chip(substream); - return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_SPDIF]); + int err; + down(&chip->open_mutex); + if (chip->spdif_over_aclink) + err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]); + else + err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_SPDIF]); + up(&chip->open_mutex); + return err; } /* AC97 playback */ @@ -1188,7 +1222,8 @@ /* initialize constants */ chip->dmas[ATI_DMA_PLAYBACK].ops = &snd_atiixp_playback_dma_ops; chip->dmas[ATI_DMA_CAPTURE].ops = &snd_atiixp_capture_dma_ops; - chip->dmas[ATI_DMA_SPDIF].ops = &snd_atiixp_spdif_dma_ops; + if (! chip->spdif_over_aclink) + chip->dmas[ATI_DMA_SPDIF].ops = &snd_atiixp_spdif_dma_ops; /* assign AC97 pcm */ if (chip->spdif_over_aclink) @@ -1198,6 +1233,8 @@ err = snd_ac97_pcm_assign(pbus, num_pcms, atiixp_pcm_defs); if (err < 0) return err; + for (i = 0; i < num_pcms; i++) + chip->pcms[i] = &pbus->pcms[i]; chip->max_channels = 2; if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) { @@ -1207,11 +1244,6 @@ chip->max_channels = 4; } - chip->dmas[ATI_DMA_PLAYBACK].pcm = &pbus->pcms[0]; - chip->dmas[ATI_DMA_CAPTURE].pcm = &pbus->pcms[1]; - if (chip->spdif_over_aclink) - chip->dmas[ATI_DMA_SPDIF].pcm = &pbus->pcms[2]; - /* PCM #0: analog I/O */ err = snd_pcm_new(chip->card, "ATI IXP AC97", 0, 1, 1, &pcm); if (err < 0) @@ -1225,9 +1257,13 @@ snd_dma_pci_data(chip->pci), 64*1024, 128*1024); /* no SPDIF support on codec? */ - if (chip->dmas[ATI_DMA_SPDIF].pcm && ! chip->dmas[ATI_DMA_SPDIF].pcm->rates) + if (chip->pcms[2] && ! chip->pcms[2]->rates) return 0; + /* FIXME: non-48k sample rate doesn't work on my test machine with AD1888 */ + if (chip->pcms[2]) + chip->pcms[2]->rates = SNDRV_PCM_RATE_48000; + /* PCM #1: spdif playback */ err = snd_pcm_new(chip->card, "ATI IXP IEC958", 1, 1, 0, &pcm); if (err < 0) @@ -1272,10 +1308,12 @@ snd_atiixp_xrun_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]); else if (status & ATI_REG_ISR_IN_STATUS) snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_CAPTURE]); - if (status & ATI_REG_ISR_SPDF_XRUN) - snd_atiixp_xrun_dma(chip, &chip->dmas[ATI_DMA_SPDIF]); - else if (status & ATI_REG_ISR_SPDF_STATUS) - snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_SPDIF]); + if (! chip->spdif_over_aclink) { + if (status & ATI_REG_ISR_SPDF_XRUN) + snd_atiixp_xrun_dma(chip, &chip->dmas[ATI_DMA_SPDIF]); + else if (status & ATI_REG_ISR_SPDF_STATUS) + snd_atiixp_update_dma(chip, &chip->dmas[ATI_DMA_SPDIF]); + } /* for codec detection */ if (status & CODEC_CHECK_BITS) { @@ -1412,6 +1450,7 @@ spin_lock_init(&chip->reg_lock); spin_lock_init(&chip->ac97_lock); + init_MUTEX(&chip->open_mutex); chip->card = card; chip->pci = pci; chip->irq = -1; ------------------------------------------------------- This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click _______________________________________________ Alsa-cvslog mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-cvslog